Reputation: 2084
I simply load a page using the find() method which returns one record for display as a summary and my viewmodel also returns a list of what I call metrics so that the customer can visually identify the metrics they used for a project. If they did not use those metrics, then they can update the value to zero. Once they update the metrics, they click save to insert these metrics into the table. So what we find is that I originally had metrics pulled in from the Metrics table with a status ='Planned' for planned metrics. When they load these metrics into the page, these metrics will get updated with new values if necessary and then reinserted as new rows with the status='Actual'.
Original planned metric record - metricid = 1, metricstatus = 'Planned' New Actual metircs record - no id prior to insert, metricstatus = 'Actual'
I get the following error during insert.
An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key. This is how I insert the record
IList<Metric> MetricList = new List<Metric>();
foreach (var projectMetric in ProjectMetrics){
if (projectMetric.MetricTypeId != 0)
{
var metric = new Metric
{
Value = Int32.Parse(projectMetric.Value),
MetricTypeId = projectMetric.MetricTypeId,
ProjectId = project.ProjectId,
MetricPhase = "Actual"
};
project.Metrics.Add(metric);
}
}
This is how I save the change
this.Context.Projects.Attach(project);
this.Context.Entry(project).State = System.Data.EntityState.Modified;
this.Context.SaveChanges();
Any help is greatly appreciated.
public Project GetProjectByID(int? id)
{
Project ProjectQuery = Context.Projects.Find(id);
return ProjectQuery;
}
I actually send a json string back to the server which has all of my metrics. I deserialize my json string as follows:
List InsertableProjectMetrics = JsonConvert.DeserializeObject>(metricsJSON);
I then call the InsertMetricMethod which loops through the Jason metric data.
public void InsertProjectMetrics(List ProjectMetrics, int projectid, ref Project project, string Status)
{
//Insert Record: Insert New Record
try
{
this.Context.Projects.Attach(project);
foreach (var projectMetric in ProjectMetrics)
{
if (projectMetric.MetricTypeId != 0)
{
var metric = new Metric
{
Value = Int32.Parse(projectMetric.Value),
MetricTypeId = projectMetric.MetricTypeId,
ProjectId = project.ProjectId,
MetricPhase = "Actual"
};
project.Metrics.Add(metric);
}
}
Upvotes: 0
Views: 1628
Reputation: 41
Please check below mention things when facing this error:
RequestId = Guid.NewGuid();
Eventhough primary key is being populated within insert stored procedure using sql function newid()
.Upvotes: 1
Reputation: 177133
The order when you add a new metric
to project.Metrics
and when you attach the project
to the context is wrong.
You have many metrics with ID = 0 in the Metrics
collection of your project
. When you attach now this graph to the context EF puts the project and all children collections into Unchanged
state. The exception complains that there is more than one instance with ID = 0.
To solve the problem you must call this line...
this.Context.Projects.Attach(project)
... before you start the foreach loop and add new metrics to the Metrics
collection of the attached project
. EF change detection will then automatically recognize them as new children and put them into Added
state into the context. In Added
state duplicate IDs are allowed (as long as your primary key is a database identity column).
Upvotes: 0