如何从MVC应用程序中解析DataModel的异常,其中DataModel使用EF6包含与同一表的2个FK关系



我正在使用C#/MVC和EF6开发Web应用程序。我正在使用数据库第一种方法,因为我将其附加到现有数据库(SQL Server 2008-R2)。

我有一个表格,其中包含2个外国键,与以下方式相同的目标:

Table Artifact:
    int ArtifactId;
    int AnalystId;  //Employee performing analysis work on artifact
    int ChampionId; //Employee servind as champion for artifact

,目标表非常简单。

Table Employee:
    int EmployeeId;
    // Employee info

我将Datbase访问作为断开的存储库管理,以便我检索和更新信息时,我可以管理状态。

    public Candidate GetArtifact(int artifactId)
    {
        using (var context = new DataEntities())
        {
            return context.Artifacts.AsNoTracking()
                .Where(x => x.ArtifactId == artifactId)
                .Include(x => x.Employee)         //Analyst
                .Include(x => x.Employee1)        //Champion
                .FirstOrDefault();
        }
    }
    public int SaveArtifact(Artifact artifact)
    {
        using (var context = new DataEntities())
        {
            if (artifact.ArtifactId > 0)
            {
                context.Entry(artifact).State = EntityState.Modified;
            }
            else
            {
                context.Artifacts.Add(artifact);
            }
            context.SaveChanges();
            return artifact.CandidateId;
        }
    }

一切正常,除了分析师和冠军参考员工记录相同记录的情况外。在测试"更新"现有代码路径时,我会得到2个例外之一,具体取决于数据的初始状态。请注意,仅在数据更新时才发生异常,它可以正确检索而没有问题。

当我尝试与分析师和冠军同时提及同一员工记录的人工制品时。我得到以下例外:

Attaching an entity of type 'Data.DataModel.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.

关于我可以做什么的任何建议?

进行一些额外的挖掘后,我找到了解决我特定问题的解决方案。我遵循的模式(由我的一位同事确定)是急于加载所有数据记录。因此,工件的获取包括两个包括包括两个不同键的陈述,如我最初的示例中所示。

这引起问题的地方是,在冠军和分析师都在参考同一员工记录的情况下,更新看到了已经附加到上下文的分析师的主要密钥/记录,因此在尝试时会抛出异常为冠军再次将实际记录附加到上下文中。

我的解决方案是从检索中删除急切的加载,对于我的特定设计而言,这没有真正的问题,因为员工记录确实是指的,并且从未与文物更新结合使用。

所以我的getArtifact方法在修复后看起来如下:

public Candidate GetArtifact(int artifactId)
{
    using (var context = new DataEntities())
    {
        return context.Artifacts.AsNoTracking()
            .Where(x => x.ArtifactId == artifactId)
            .FirstOrDefault();
    }
}

和实际引用员工记录的几个位置只需使用适当的ID并直接获取记录。这阻止了问题。

对我来说,学到的教训是了解急切的加载以及何时使用它(更重要的是在不使用它时)。

最新更新