EF 4.3.1 Включить унаследованные свойства навигации в запросе LinqueEntities

StackOverflow https://stackoverflow.com//questions/10705218

Вопрос

Я пытаюсь настроить простой сценарий наследования с EF 4.3.1, используя первый код Approch и Configuration.

Я создал абстрактный базовый тип «A» с использованием навигационного свойства One-to-One, а наследственный класс «AA» также с помощью свойства навигации One-One следуют:

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 во время выполнения со следующим сообщением Inner Exception:

Реальтип указанного выражения не совместим с требуемый тип. Выражение resulttype «Трансферриент] [... A], но требуемый тип 'Transient.Reference [... AA]. Имя параметра: аргументы [0]

Кто-нибудь столкнулся с подобной проблемой?

Я, наверное, не хватает чего-то, но я не вижу, что не так с этой выборкой.

Что я могу сделать, чтобы получить мою модель, как ожидалось?

Это было полезно?

Решение

Нет, вы ничего не пропустите. На самом деле вы столкнулись с ошибкой Old Entity Framework. Ваш второй запрос можно записать так:

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

(когда вы заменяете свой dbset AASet by ASet).

Для этого типа нетерпеливой загрузке изображенных детей из одной на один на унаследованных типах эта статья применяется: http://weblogs.ass.asp.net/johnkatsiotis/Archive/2010/04/28/huge-ef4-inheritance-bug.aspx P >.

Ошибка была сообщена здесь давно: https://connect.microsoft.com/visualstudio/feedback/details/544639/ef4-neritance-defined-using-queryview-doesnt-work-properly-with-sAsciation / a>

ошибка все еще существует в EF 4.3.1. Но Microsoft объявила в этой теме, что ошибка фиксируется в .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.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top