表每个具体类型(TPC)的实体框架6继承(EF6) [英] Table Per Concrete Type (TPC) Inheritance in Entity Framework 6 (EF6)

查看:271
本文介绍了表每个具体类型(TPC)的实体框架6继承(EF6)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在努力避免使用表每个层级(TPH)我一直在寻找如何最好地实现我的数据库表的模型每个具体类(TPC)继承的例子。我碰到href=\"https://msdn.microsoft.com/en-us/data/jj591617#2.6\" rel=\"nofollow\">官方文档并的这篇文章



下面是一些模拟补课一些简单的继承。

 公共类BaseEntity 
{
公共BaseEntity()
{
ModifiedDateTime = DateTime.Now;
}

[关键]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)
公众诠释标识{搞定;组; }

公众的DateTime ModifiedDateTime {搞定;组; }
}

公共类人:BaseEntity
{
公共字符串名字{获得;组; }
公共字符串名字{获得;组; }
}

公共类业务:BaseEntity
{
公共字符串名称{;组; }
公共字符串位置{搞定;组; }
}



两篇文章在每例中使用的DbModelBuilder配置。



  modelBuilder.Entity< BaseEntity>()
.Property(C => c.Id)
.HasDatabaseGeneratedOption( DatabaseGeneratedOption.None);

modelBuilder.Entity<人方式>()地图(M = GT;
{
m.MapInheritedProperties();
m.ToTable(人) ;
});

modelBuilder.Entity<经营方式>()地图(M = GT;
{
m.MapInheritedProperties();
m.ToTable(业务) ;
});



应用程序成功运行,但是当我回去的数据库,我觉得三(3)表,而不是两(2)我希望能够找到。有些测试会出现BaseEntity表创建,但从未使用过之后。一切似乎都工作得很好,这个空孤表除外。



我混乱与周围的DbModelBuilder配置,最终去掉它提供了预期的结果了BaseEntity配置;两(2)表中,他们每个人具有正确的属性和功能正常。



我最后一次测试中,撕裂了所有的DbModelBuilder配置,仅包含两个( 2)DbSet属性人和业务,并再次测试

 公共DbSet<&人GT;人们{搞定;组; } 
公共DbSet<商业与GT;企业{搞定;组; }

要我吃惊的是项目建立,出去到数据库中,仅创建所有的两个表类的属性,包括从BaseEntity类继承的。我可以做的CRUD操作没有问题。



运行多项测试后,我无法找到最后的测试任何问题,我一直无法重现重复键错误这两篇文章警告。




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





  1. 我很好奇,为什么该示例使用MapInheritedProperties财产;这是一个过时的方法是什么?

  2. 为什么这两个例子说,以包括BaseEntity配置属性还包括无论是DbSet财产或为BaseEntity任何DbModelBuilder配置类导致未使用表中创建

  3. 在参考了独特的键错误的文章警告。我无法重现错误,我曾与主键或者通过数据库生成一个int,并通过数据库生成一个GUID多次测试。是关于此错误的信息也已过时,或者是有一个测试,我可以运行,以产生所说的错误?


解决方案

我用马平类,但请不要介意。我解决这个问题是这样的:

 公共类PersonMap:EntityTypeConfiguration<&人GT; 
{
公众人物图()
{
地图(M = GT; {m.ToTable(人); m.MapInheritedProperties();});

HasKey(P => p.Id);
房产(P => p.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
}

}



Remeber - 基类必须是抽象


In an effort to avoid the use of Table Per Hierarchy (TPH) I have been looking at examples of how best to implement Table-Per-Concrete Class (TPC) inheritance in my database model. I came across the official documentation and this article.

Below are some mock-up classes with some simple inheritance.

public class BaseEntity
{
    public BaseEntity()
    {
        ModifiedDateTime = DateTime.Now;
    }

    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    public DateTime ModifiedDateTime { get; set; }
}

public class Person : BaseEntity
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

public class Business :  BaseEntity
{
    public string Name { get; set; }
    public string Location { get; set; }
}

The DbModelBuilder configurations used per the examples in both articles.

modelBuilder.Entity<BaseEntity>() 
    .Property(c => c.Id) 
    .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None); 

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

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

The application runs successfully but when I go back to the database I find three (3) tables instead of the two (2) I expected to find. After a bit of testing it would appear the "BaseEntity" table is created but is never used. Everything seems to work just fine with the exception of this empty orphaned table.

I mess around with the DbModelBuilder configurations, eventually removing the "BaseEntity" configurations which provides the expected result; Two (2) tables, each of them having the correct properties and functioning correctly.

I do one last test, rip out all the DbModelBuilder configurations, only include the two (2) DbSet properties for "Person" and "Business" and test again.

public DbSet<Person> People { get; set; }
public DbSet<Business> Businesses { get; set; }

To my surprise the project builds, goes out to the database, creates only the two tables with all the class properties including the inherited ones from the "BaseEntity" class. I can do CRUD operations without issue.

After running many tests I can't find any issues with the final test and I have not been able to reproduce the duplicate key error both articles warned about.

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. Inner exception message: AcceptChanges cannot continue because the object's key values conflict with another object in the ObjectStateManager. Make sure that the key values are unique before calling AcceptChanges.

  1. I am curious why the examples use the MapInheritedProperties property; is this an outdated method?
  2. Why do both examples say to include configuration properties for the "BaseEntity" yet including either the DbSet property or any DbModelBuilder configurations for the "BaseEntity" class causes an unused table to be created.
  3. In reference to the unique key error the articles warned of; I am unable to reproduce the error and I have tested many times with the primary key as either an int generated by the database and a guid generated by the database. Is the information about this error also obsolete or is there a test I can run to produce said error?

解决方案

I use maping classes, but nevermind. I solve it like this:

public class PersonMap : EntityTypeConfiguration<Person>
{
    public Person Map()
    {
        Map(m => { m.ToTable("Person"); m.MapInheritedProperties(); });

        HasKey(p => p.Id);
        Property(p => p.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
    }

}

Remeber - base class must be abstract.

这篇关于表每个具体类型(TPC)的实体框架6继承(EF6)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆