4

我想用EF 4.3.1设置一个简单的继承场景,使用代码优先和流畅的配置。EF 4.3.1在LinqToEntities查询中包含继承的导航属性

我创建一个抽象基类“A”与一对一的导航属性和继承的类“AA”还与一对一的导航属性有以下:

public abstract class A 
{ 
    public Guid ID { get; set; } 
    public B ChildB { get; set; } 
} 

public class AA : A 
{ 
    public C ChildC { get; set; } 
} 

public class B 
{ 
    public Guid ID { get; set; } 
    public A Parent { get; set; } 
} 

public class C 
{ 
    public Guid ID { get; set; } 
    public AA Parent { get; set; } 
} 

public class AConfiguration : EntityTypeConfiguration<A> 
{ 
    public AConfiguration() 
    { 
     this.HasRequired(o => o.ChildB) 
      .WithRequiredPrincipal(o => o.Parent); 

     this.Map(o => 
     { 
      o.ToTable("A"); 
     }); 
    } 
} 

public class AAConfiguration : EntityTypeConfiguration<AA> 
{ 
    public AAConfiguration() 
    { 
     this.HasRequired(o => o.ChildC) 
      .WithRequiredPrincipal(o => o.Parent); 

     this.Map(o => 
     { 
      o.ToTable("AA"); 
     }); 
    } 
} 

public class BConfiguration : EntityTypeConfiguration<B> 
{ 
    public BConfiguration() 
    { 
     this.HasRequired(o => o.Parent) 
      .WithRequiredDependent(o => o.ChildB); 

     this.Map(o => 
     { 
      o.ToTable("B"); 
     }); 
    } 
} 

public class CConfiguration : EntityTypeConfiguration<C> 
{ 
    public CConfiguration() 
    { 
     this.HasRequired(o => o.Parent) 
      .WithRequiredDependent(o => o.ChildC); 

     this.Map(o => 
     { 
      o.ToTable("C"); 
     }); 
    } 
} 

public class DataContext : DbContext 
{ 
    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Configurations.Add<A>(new AConfiguration()); 
     modelBuilder.Configurations.Add<AA>(new AAConfiguration()); 
     modelBuilder.Configurations.Add<B>(new BConfiguration()); 
     modelBuilder.Configurations.Add<C>(new CConfiguration()); 
    } 

    public DbSet<AA> AASet { get; set; } 
    public DbSet<B> BSet { get; set; } 
    public DbSet<C> CSet { get; set; } 
} 

当我试图让我的数据回来导航属性的第一级,它按预期工作:

... dataContext.AASet.Include("ChildB") ... 

但是当我尝试包括继承类型的导航属性类似如下:

... dataContext.AASet.Include("ChildC") ... 

我得到一个EntityCommandCompilationException在运行时用下面的内部异常消息:

指定表达式的与resultType不与 所需类型兼容。表达式ResultType是 'Transient.reference [... A]',但所需的类型是 'Transient.reference [... AA]'。参数名称:参数[0]

有没有人遇到类似的问题?

我可能错过了一些东西,但是我看不出这个示例有什么问题。

我该如何让我的模型按预期工作?

回答

4

不,你不会错过任何东西。其实你遇到了一个旧的实体框架错误。你的第二个查询可以这样写:

var result = dataContext.ASet.OfType<AA>().Include("ChildC").ToList(); 

(当您更换DbSet AASet通过ASet)。

有关继承类型这种类型的一个一对一映射孩子的渴望加载本文应用于:http://weblogs.asp.net/johnkatsiotis/archive/2010/04/28/huge-ef4-inheritance-bug.aspx

这个bug已经报道很久以前这里:https://connect.microsoft.com/VisualStudio/feedback/details/544639/ef4-inheritance-defined-using-queryview-doesnt-work-properly-with-association

的错误仍然存​​在EF 4.3.1。但微软已经在这个线程中宣布该错误在.NET 4.5(= EF 5.0)中得到了修复。

如果关系是一对多而不是一对一,那么代码就可以工作。懒惰或明确的加载也将工作(也与一对一的关系),我相信:

var result = dataContext.ASet.OfType<AA>().ToList(); 
foreach (var item in result) 
    dataContext.Entry(item).Reference(a => a.ChildC).Load(); 

但是,这将生成多个查询。如果您对多个查询没有性能问题,我宁愿使用上一个解决方法 - 直到您可以迁移到EF 5.0。

+0

Thanx为您的答复Sauma,但您的第一个解决方法生成相同的异常和使用显式负载不是我的项目的选项。 – P0lO