EF Eager fetching derived class

后端 未结 2 692
心在旅途
心在旅途 2020-12-11 04:55

I´m using EF6 and trying to eager fetch the whole structure of an object. The problem is that i´m using inheritance.

Let´s say that i have this classes.

相关标签:
2条回答
  • 2020-12-11 05:25

    Shortly, it's not possible out of the box.

    The only workaround I can suggest is to materialize the master query result, then execute several OfType queries with the necessary Includes using the same filter as the master query, and rely on EF navigation property fixup.

    It requires an inverse navigation property in the Base class:

    public abstract class Base
    {
       // ...
       public A A { get; set; }
    }
    

    Then you can use something like this:

    public IEnumerable<A> GetAll(string id)
    {
        var a = _ctx.A.Where(x => x.Id == id).ToList();
        _ctx.Base.OfType<Base1>().Include(e => e.SomeClass).Where(e => e.A.Id == id).Load();
        _ctx.Base.OfType<Base3>().Include(e => e.SomeOtherClass).Where(e => e.A.Id == id).Load();
        return a;
    }
    

    The same idea can be used w/o inverse navigation property but with using the returned base Ids as filter:

    public IEnumerable<A> GetAll(string id)
    {
        var a = _ctx.A.Include(e => e.Bases)
            .Where(x => x.Id == id).ToList();
    
        var baseIds = a.SelectMany(e => e.Bases.OfType<ModelA.Base1>().Select(b => b.Id));
        db.Base.OfType<Base1>().Include(e => e.SomeClass)
            .Where(e => baseIds.Contains(e.Id)).Load();
    
        baseIds = a.SelectMany(e => e.Bases.OfType<Base3>().Select(b => b.Id));
        db.Base.OfType<Base3>().Include(e => e.SomeOtherClass)
            .Where(e => baseIds.Contains(e.Id)).Load();
    
        return a;
    }
    
    0 讨论(0)
  • 2020-12-11 05:28

    Your problem is not in the Select(y=>y.SomeClass) it self, if you try to remove it from your query and execute your query again, you will get same problem. You cannot query the inherited type as child and you expect from entity framework to take care for everything.

    If you look to your database, the table Base has a reference to A which is relation 1-many from A to Base.

    you can either get all the Base entities where A.Id = something, by adding a navigational property A in the class Base, and in your DbContext you add DbSet<Base> Bases{get;set;} then your query will look like this

    var details = _ctx.Bases.OfType<Base1>()
                            .Include(t=>t.Box)
                            .Include(t=>t.SomeClass)
                            .Where(t=>t.Box.Id ==something);
    

    Other option, to use a DTO, in the below sample I used Anonymous type, but you can create a strongly DTO typed to meet your requirements.

    var details  = _ctx.A
                       .Where (t=>t.Id ==something)
                       .Select(a => new {
                            Id = a.Id,
                            // ... other A properites , 
                            Bases = _ctx.Bases.OfType<Base1>().Select(m=> new {
                                Id = m.Id,
                                Name = m.Name,
                                SomeClass = m.SomeClass
                            });
                       }
    

    Hope this will help you

    0 讨论(0)
提交回复
热议问题