9

我在面向 .Net 4.5 的 Windows 服务中有此代码,该服务使用数据库优先的实体框架层:

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 以将其指向新的子对象并将其保存到数据库中。

它不会ProcessStatusType 表中执行此操作,该表设置有基本相同的 FK 父子关系。

我现在有一个数据库,其中充满了我不需要的相同 ProcessType 条目,我不知道为什么会发生这种情况。我觉得我犯了一些我看不到的明显错误,因为这是我的第一个 EF 项目。问题是我允许上下文在调用之间过期但保持相同的实体吗?

4

1 回答 1

5

使用 Add 会将所有元素的状态设置为已添加,这会导致插入子元素。当您为此元素指定 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").

于 2013-02-15T21:24:18.927 回答