【问题标题】:EF 4.3.1 Include inherited navigation properties in LinqToEntities queryEF 4.3.1 在 LinqToEntities 查询中包含继承的导航属性
【发布时间】:2012-05-22 15:32:26
【问题描述】:

我正在尝试使用代码优先方法和流畅的配置在 EF 4.3.1 中设置一个简单的继承场景。

我创建了一个具有一对一导航属性的抽象基类型“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]' 但所需的类型是 '瞬态.reference [...AA]'。参数名称:arguments[0]

有人遇到过类似的问题吗?

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

我该怎么做才能让我的模型按预期工作?

【问题讨论】:

    标签: c# inheritance ef-code-first entity-framework-4.3 navigation-properties


    【解决方案1】:

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

    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。

    【讨论】:

    • 感谢您的回复 Sauma,但您的第一个解决方法会产生相同的异常,并且使用显式加载不是我的项目的选项。
    猜你喜欢
    • 1970-01-01
    • 2020-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多