【发布时间】:2014-11-26 10:16:44
【问题描述】:
初步情况
我有一个使用现有数据库的应用程序,目前使用 NHibernate 作为 O/R-Mapper。
现在我需要使用 Code First 和 Fluent API Configuration 迁移到 Entity Framework 6.1.1。
但是现在我对数据模型的一部分有问题,因为它使用了不同类型的继承策略(TPT 和 TPH)
结构
注意:在这里发布完整的数据模型对我来说似乎有点太大了,所以我在一个小型 POC 程序中重现了我面临的问题。
CLASS | TABLE | TYPE
-----------------------+--------------------+------
BaseEntity (abstract) | BaseTable |
Inherited_TPH | BaseTable | 1
Inherited_TPT | Inherited_TPT | 2
表中用作鉴别器的列称为Type
基于this answer我添加了一个抽象类Intermediate_TPH作为中间层:
一些示例数据:带有ID=3 的条目属于Inherited_TPT 类型
代码
这些是我的实体类和我的上下文类:
class MyContext : DbContext
{
public MyContext ( string connectionString )
: base ( connectionString )
{
}
public DbSet<Inherited_TPH> TPH_Set { get; set; }
public DbSet<Inherited_TPT> TPT_Set { get; set; }
public DbSet<SomethingElse> Another_Set { get; set; }
protected override void OnModelCreating ( DbModelBuilder modelBuilder )
{
modelBuilder
.Entity<BaseEntity> ()
.ToTable ( "BaseTable" );
modelBuilder
.Entity<Inherited_TPH> ()
.Map ( t => t.Requires ( "Type" ).HasValue ( 1 ) );
modelBuilder
.Entity<Intermediate_TPT> ()
.Map ( t => t.Requires ( "Type" ).HasValue ( 2 ) );
modelBuilder
.Entity<Intermediate_TPT> ()
.Map<Inherited_TPT> ( t => t.ToTable ( "Inherited_TPT" ) );
modelBuilder
.Entity<SomethingElse> ()
.ToTable ( "SomethingElse" )
.HasKey ( t => t.Id );
}
}
public abstract class BaseEntity
{
public virtual int Id { get; set; }
public virtual string Title { get; set; }
}
public class Inherited_TPH : BaseEntity
{
}
public abstract class Intermediate_TPT : BaseEntity
{
}
public class Inherited_TPT : Intermediate_TPT
{
public virtual string Comment { get; set; }
}
public class SomethingElse
{
public virtual string Description { get; set; }
public virtual int Id { get; set; }
}
运行以下代码会报错。
static void Main ( string[] args )
{
Database.SetInitializer<MyContext> ( null );
var ctx = new MyContext ( @"Data Source=(local);Initial Catalog=nh_ef;Integrated Security=true" );
try
{
// Accessing Inherited_TPH works just fine
foreach ( var item in ctx.TPH_Set ) Console.WriteLine ( "{0}: {1}", item.Id, item.Title );
// Accessing Inherited_TPT works just fine
foreach ( var item in ctx.TPT_Set ) Console.WriteLine ( "{0}: {1} ({2})", item.Id, item.Title, item.Comment );
// The rror occurs when accessing ANOTHER entity:
foreach ( var item in ctx.Another_Set ) Console.WriteLine ( "{0}: {1}", item.Id, item.Description );
}
catch ( Exception ex )
{
Console.WriteLine ( ex.Message );
if( ex.InnerException != null ) { Console.WriteLine ( ex.InnerException.Message ); }
}
}
输出
程序产生以下输出:
1:辛普森
2:约翰逊
3:史密斯(更多关于史密斯的细节)
4:米勒(关于米勒的更多细节)
准备命令定义时出错。有关详细信息,请参阅内部异常。(26,10):错误 3032:从第 14、26 行开始映射片段时出现问题:EntityTypes PoC.Inherited_TPH、PoC.Inherited_TPT 被映射到表 BaseEntity 中的相同行。映射条件可用于区分这些类型映射到的行。
问题
如您所见,映射似乎工作,因为我可以从Inherited_TPT 和Inherited_TPH 加载所有数据。但是当访问另一个实体时,我得到一个异常。
我需要如何配置映射以消除此错误并能够访问现有的数据库结构?
【问题讨论】:
标签: c# entity-framework inheritance ef-code-first entity-framework-6