简体   繁体   English

实体框架的TPC映射导致错误

[英]Entity Framework's TPC mapping results in error

I have these models: 我有以下模型:

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; }
}

And in database, I have two tables called Teachers and Students . 在数据库中,我有两个表叫做TeachersStudents I want to use Entity Framework's TPC mapping. 我想使用实体框架的TPC映射。 My context class is: 我的上下文类是:

    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");
        }); 
    }

But when I want to add a teacher, I get this error: 但是当我想添加一名老师时,出现以下错误:

The changes to the database were committed successfully, but an error occurred while updating the object context. 已成功提交对数据库的更改,但是在更新对象上下文时发生错误。 The ObjectContext might be in an inconsistent state. ObjectContext可能处于不一致状态。 Inner exception message: AcceptChanges cannot continue because the object's key values conflict with another object in the ObjectStateManager. 内部异常消息:AcceptChanges无法继续,因为对象的键值与ObjectStateManager中的另一个对象冲突。 Make sure that the key values are unique before calling AcceptChanges. 在调用AcceptChanges之前,请确保键值是唯一的。

What's wrong here? 怎么了

See this link : 看到这个链接

The reason we got this exception is because DbContext.SaveChanges() internally invokes SaveChanges method of its internal ObjectContext. 我们得到此异常的原因是因为DbContext.SaveChanges()在内部调用其内部ObjectContext的SaveChanges方法。 ObjectContext's SaveChanges method on its turn by default calls AcceptAllChanges after it has performed the database modifications. 默认情况下,ObjectContext的SaveChanges方法在执行数据库修改后默认调用AcceptAllChanges。

AcceptAllChanges method merely iterates over all entries in ObjectStateManager and invokes AcceptChanges on each of them. AcceptAllChanges方法仅迭代ObjectStateManager中的所有条目,并在每个条目上调用AcceptChanges。 Since the entities are in Added state, AcceptChanges method replaces their temporary EntityKey with a regular EntityKey based on the primary key values (ie PersonId ) that come back from the database and that's where the problem occurs since both the entities have been assigned the same value for their primary key by the database (ie on both PersonId = 1) and the problem is that ObjectStateManager cannot track objects of the same type with the same EntityKey value hence it throws. 由于实体处于“已添加”状态,因此基于数据库返回的主键值(即PersonId),AcceptChanges方法将它们的临时EntityKey替换为常规EntityKey,这是发生问题的原因,因为两个实体都被分配了相同的值对于数据库的主键(即在两个PersonId = 1上),问题是ObjectStateManager无法跟踪具有相同EntityKey值的相同类型的对象,因此会抛出该异常。 If you take a closer look at the TPC's SQL schema above, you'll see why the database generated the same values for the primary keys: the PersonId column in both Student and Teacher table has been marked as identity. 如果您仔细查看上面的TPC的SQL模式,您将看到为什么数据库为主键生成相同值的原因:Student和Teacher表中的PersonId列已被标记为身份。

Try this: 尝试这个:

public srting PersonId { get; set; }

and change your config to: 并将您的配置更改为:

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

and change you class to abstract / 并将您的班级更改为abstract /

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM