我在针对.Net 4.5的Windows服务中使用了数据库优先的Entity Framework层中的以下代码:
var existingState = DataProcessor.GetProcessState(workerId);
existingState.ProcessStatusTypeId = (int)status;
existingState.PercentProgress = percentProgress;
existingState.ProgressLog = log;
DataProcessor.UpdateProcessState(existingState);
和下面的代码在数据处理类中的相同解决方案:
public ProcessState GetProcessState(int id)
{
using (var context = new TaskManagerEntities())
{
var processes = (from p in context.ProcessStates.Include("ProcessType").Include("ProcessStatusType")
where p.IsActive && p.ProcessStateId == id
select p);
return processes.FirstOrDefault();
}
}
public ProcessState UpdateProcessState(ProcessState processState)
{
using (var context = new TaskManagerEntities())
{
context.ProcessStates.Add(processState);
context.Entry(processState).State = System.Data.EntityState.Modified;
context.SaveChanges();
}
return processState;
}
ProcessState是其他两个类的父类,即ProcessStatusType和ProcessType。当我在Windows服务中运行该代码时,它会检索一条记录,更新实体并保存它。尽管上述代码中从未使用过ProcessType子级,但在执行ProcessState实体上的保存时,EF会对ProcessType表进行插入并在其中创建新记录。然后,它更改ProcessStatus实体中的FK以将其指向新的子项并将其保存到数据库中。
它在使用基本相同的FK父子关系设置的ProcessStatusType表中不执行此操作。
我现在有一个数据库,里面装满了我不需要的相同ProcessType条目,而且我也不知道为什么会这样。我觉得我犯了一个我看不见的明显错误,因为这是我的第一个EF项目。我允许上下文在两次调用之间终止但保持相同实体的问题吗?
最佳答案
使用“添加”会将所有元素的状态设置为“已添加”,这将导致插入子元素。当您为此元素指定EntityState.Modified时,不会插入父元素。
尝试在UpdateProcessState中使用以下内容,而不是使用Add。
context.ProcessStates.Attach(processState);
context.Entry(processState).State = EntityState.Modified;
context.SaveChanges();
Attach将把所有元素的状态设置为Unchanged,并通过为父元素指定Modified来指示仅应更新此元素。
另一个注意事项。您应该使用强类型的
Include(x => x.ProcessType)
而不是Include("ProcessType")
。关于asp.net-mvc - 为什么在更新父级时,Entity Framework会插入子级?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/14902408/