实体框架TPC映射导致错误

时间:2014-02-01 13:00:58

标签: c# entity-framework-5

我有这些模特:

public class Person
{
    public int PersonId { get; set; }

    public string Name { get; set; }

    public int Age { get; set; }
}

public class Student : Person
{
    public int Payment { get; set; }
}

public class Teacher : Person
{
    public int Wage { get; set; }
}

在数据库中,我有两个名为TeachersStudents的表。我想使用Entity Framework的TPC映射。我的上下文类是:

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Person>()
        .Property(i => i.PersonId)
        .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

        modelBuilder.Entity<Teacher>().Map(m =>
        {
            m.MapInheritedProperties();
            m.ToTable("Teacher", "dbo");
        }); 

        modelBuilder.Entity<Student>().Map(m =>
        {
            m.MapInheritedProperties();
            m.ToTable("Student", "dbo");
        }); 
    }

但是当我想添加老师时,我收到了这个错误:

  

已成功提交对数据库的更改,但更新对象上下文时发生错误。 ObjectContext可能处于不一致状态。内部异常消息:AcceptChanges无法继续,因为对象的键值与ObjectStateManager中的另一个对象冲突。在调用AcceptChanges之前,请确保键值是唯一的。

这里有什么问题?

1 个答案:

答案 0 :(得分:3)

请参阅此link

  

我们得到此异常的原因是因为DbContext.SaveChanges()   在内部调用其内部ObjectContext的SaveChanges方法。   默认情况下,ObjectContext的SaveChanges方法默认调用   在执行数据库修改后接受AcceptAllChanges。

     

AcceptAllChanges方法仅迭代所有条目   ObjectStateManager并在每个上调用AcceptChanges。以来   实体处于已添加状态,AcceptChanges方法替换它们   具有基于主键的常规EntityKey的临时EntityKey   从数据库返回的值(即PersonId)   这就是问题发生的地方,因为两个实体都是   数据库为其主键分配了相同的值(即打开   PersonId = 1)和问题是ObjectStateManager   无法跟踪相同类型的对象   因此它抛出相同的EntityKey值。如果你仔细看看   上面的TPC的SQL模式,你会看到为什么数据库生成的相同   主键的值:两者中的PersonId列   学生和教师表已被标记为身份。

试试这个:

public srting PersonId { get; set; }

并将配置更改为:

   modelBuilder.Entity<Person>()
        .Property(i => i.PersonId)
        .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);

并将您的班级更改为abstract /