I have a scenario very similar to this question but I am trying to to something a bit more complex.
To recap, I basically have a List of Cases, each one of a different type:
Case -> CaseA
Case -> CaseB
Case -> CaseC
Every derived Case
class has one or more navigational properties which I need to include:
Case -> CaseA -> Employee
Case -> CaseB -> List<Something>
Case -> CaseC -> List<SomethingElse>
Now, of course I could do a massive switch
statement but I am looking for something clever like this:
foreach(var myCase in ListOfCases)
{
context.LoadAll(myCase); // <- THIS!
context.Entry(myCase).LoadAllProperties() // <- OR THIS...
// etc. etc.
}
Of course the methods do not exist so I was wondering if anyone has ever had a similar problem and what could be a nice and clever way to solve it.
Thanks!
In the end the solution was really simple: do nothing! :)
Basically if the object hierarchy is set up properly and the navigational properties (and collections) all have the virtual
modifier so that LazyLoading
could be enabled, EF will dive into the object hierarchy on its own to load properties that are not loaded during the first SELECT
:
public CasesDbContext() {
Configuration.LazyLoadingEnabled = true;
Configuration.ProxyCreationEnabled = true;
}
and then for example this is the method:
var result = new List<CaseViewModel>();
var cases = _casesRepository.All;
foreach (var customCase in cases) {
result.Add(new CaseViewModel() {
Complete = customCase.IsComplete(), // <- at this point, the customCase is
// the derived implementation
// but the full hierarchy is missing
});
}
and this is an example derived class:
public class CaseB : Case {
public int ReferenceId { get; set; }
public virtual Reference Reference { get; set; } // <- "virtual" here is important!
protected override bool IsComplete() {
return Reference.Name == "Tallmaris"; // <- at this point the EF
// will load the Reference.
}
}
The other caveat is that loading a reference while iterating through a set of entities may give an error like There is already an open DataReader associated with this Command which must be closed first
. The solution is either to use ToList()
before iterating or enable MultipleActiveResultSets
in the connection string (credits to @Ladislav for his answer here).