我在针对.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/

10-13 06:46