实体框架递归关系和附加错误

时间:2018-03-31 15:29:01

标签: c# .net database entity-framework logic

我正在创建一个应用程序来管理项目,员工并使用WPF和EF 6.2.0将员工分配给项目。

所以我有一个具有不同属性的Employee实体(其中一些是对其他实体的引用),我得到了一个具有不同特性的Project实体(同样,其中一些是其他实体)实体)。

这是我的数据库方案:

My Database Scheme

现在我要创建一个Job实体,该实体已分配给EmployeeProject。 所以要添加一个,我必须将整个EmployeeProject实体(包括所有引用的实体)附加到我的上下文中才能添加作业吗?

如果我不这样做或忘记实体的关系/属性之一,它会尝试在数据库上创建整个实体,并抛出一些错误,例如该员工的主键已经存在(显然,因为它不应该不要创建它,而是附加现有的本地文件

另一方面,如果我尝试附加它,则在附加Project时失败,因为{现在是疯狂的部分} Project.CostCentre.Location.CostCentres[0].Projects[0].ContactEmployee)已经附加。它试图以递归方式附加每一件事,包括所有列表?!

这是造成这种情况的堆栈跟踪:

private void Attach(Job job, bool attachEntity = true)
{
    Attach(job.Employee);
    Attach(job.Project); // Calls next func
    if (attachEntity && !Attached(job))
        Context.Jobs.Attach(job);
}

private void Attach(Project project, bool attachEntity = true)
{
    Attach(project.Contact);
    Attach(project.CostCentre); // Calls next func
    Attach(project.CostType);
    Attach(project.Status);
    if (attachEntity && !Attached(project))
        Context.Projects.Attach(project);
}

private void Attach(CostCentre costCentre, bool attachEntity = true)
{
    Attach(costCentre.Location); // Calls next func
    if (attachEntity && !Attached(costCentre))
        Context.CostCentres.Attach(costCentre);
}

private void Attach(Location location, bool attachEntity = true)
{
    if (attachEntity && !Attached(location))
        Context.Locations.Attach(location); // The error (that code tries to attach location.CostCentres[0].Projects[0].Contact aswell, which is an already attached Employee!!)
}

完整的错误消息:

System.InvalidOperationException: 'Attaching an entity of type 'ForecastLibrary.Employee' failed because another entity of the same type already has the same primary key value.
This can happen when using the 'Attach' method or setting the state of an entity to 'Unchanged' or 'Modified' if any entities in the graph have conflicting key values.
This may be because some entities are new and have not yet received database-generated key values.
In this case use the 'Add' method or the 'Added' entity state to track the graph and then set the state of non-new entities to 'Unchanged' or 'Modified' as appropriate.'

完整的源代码在这里:https://pastebin.com/8YU0xQUC

我已经尝试解决这个模糊的错误几周了,我希望有人可以帮我成功添加Job

编辑:这是调用所有这些的代码:

// DataService::Add Function
public void Add(Job job)
{
    Attach(job, false);
    Context.Jobs.Add(job);
}

// UI Add job snippet
using (var service = new DataService(Session.ConnectionString))
{
    service.Add(JobToAdd);
    await service.SaveAsync();
}

1 个答案:

答案 0 :(得分:2)

如果您确切知道自己需要什么并拥有更大的数据模型,我建议您使用Eager加载。

Context.Configuration.LazyLoadingEnabled = false;的构造函数中调用DataService,并在需要导航属性的地方使用.Include

然后您需要使用Find代替Attach

所以你的Job Add功能看起来像这样:

public void Add(Job job)
{
    var employee = Context.Employees.Find(job.Employee.Id);
    var project = Context.Projects.Find(job.Project.Id);
    Context.Jobs.Add(new Job { Employee = employee, Project = project, Time = job.Time });
}