Reputation: 1593
The main question I'm asking is:
Is there a way to keep a DbSet based off the base class and still support eager loading for a Derived object in a single retrieve method that only requires an Id? The answer may be that you can't. I'm just hoping I'm overlooking something.
Consider the following situation:
//Models
public class Base {
public int Id {get;set;}
public string BaseProp {get;set;}
}
public class Derived : Base {
public string DerivedProp {get;set;}
}
//Context
DbSet<Base> Bases {get;set;}
//Saving
public void Save(Base obj){
// Adding only for brevity
context.Bases.Add(obj)
context.SaveChanges();
}
//Retrieval
public Base Retrieve(int id){
return context.Bases.FirstOrDefault(x => x.Id == id);
}
EF6 is smart enough to know when Base objects are actually Derived objects and populate the additional fields on save as well as retrieve the objects as Derived objects.
However, if I change the derived class to be:
public class Derived : Base {
public string DerivedProp {get;set;}
public ICollection<SomeLookup> Lookup {get; set;} // Creates junction table with Id/LookupId as columns
}
I can still save (and it populates the junction table beautifully with the selected lookups), but I no longer can retrieve the full object in my Base DbSet because I can't change it to have an eager include on a collection that Base doesn't know exists.
I could virtualize the collection so it will lazy load when the mapping occurs down the line, but I'm wondering, and this is the root question:
Update: Essentially all I want to know is, if I only have an Id to work with for my retrieve, the following wont work, but is there something like it that will?
context.Bases.Include(x => ((Derived)x).Lookup).FirstOrDefault(x => x.Id == id)
The use case would be that I have a list page. That page doesn't need to care what types it is because it only has the base properties on it. Should I go into one of the edit pages, the server only gets passed the Id.
I'll settle for the lazy load if that's the only way as that will happen when I build the DTO after the retrieve, but I was wondering if there was some EF configuration that I don't know about for modelBuilder or a way to write a project query that I haven't found yet that allows an Eager Load for that Derived Lookup collection?
Update 2: Accepted answer based on him letting me know I can't do what I was hoping. Also found this on the EF uservoice.
Upvotes: 0
Views: 3389
Reputation: 54638
Essentially all I want to know is, if I only have an Id to work with for my retrieve, the following wont work, but is there something like it that will?
If your derived objects use some type of Entity Framework Inheritence; Mapping the Table-Per-Type (TPT) Inheritance or Mapping the Table-Per-Hierarchy (TPH) Inheritance or Mapping the Table-Per-Concrete Class (TPC) Inheritance.
Then Yes,
db.Bases
.OfType<Derived>()
.Include(d => d.Lookup)
.Where(d => d.Id = someId)
.ToList();
Otherwise No, it will not.
Upvotes: 1