Suppose we have three entities A, B, C with a many-to-one relationship A -> B and a many-to-one relationship B -> C.
In our domain source of A we then have:
class A
{
public ICollection<B> relatedBs { get; private set; }
}
Since the relationship is mapped via HasOne(...).WithMany(...) a call to dbContext.As.SelectMany(a => a.relatedBs) will be translated to a join on sql level, especially returning an IQueryable<B> which I can extend without enforcing client side evaluation.
The situation with B.relatedCs is analogous.
Now, the call
dbContext.As.SelectMany(a => a.relatedBs.SelectMany(b => b.relatedCs))
will be translated into a join of all three tables as expected.
But: if we add the following property to A:
public IEnumerable allRelatedCs => relatedBs.SelectMany(b => b.relatedCs)
which is ignored in the db configuration because there is no direct relation, the expression
dbContext.As.SelectMany(a => a.allRelatedCs).ToQueryString()
throws:
InvalidOperationException: "The LINQ expression 'ag => ag.Vorgaenge' could not be translated."
The point is, that I need the property A.allRelatedCs since it is part of the domain logic, but I also want that the above call correctly resolves to the same IQueryable as the two-layer-select-many above which resolves to the same SQL query.
My questions:
- Is this possible?
- Why does it not work this way? As far as I see, I am just writing the same expression in another way, so what goes wrong? I thought it could be because allRelatedCs is an
IEnumerable, but the resulting expression is in fact anIQueryable, only the call toToQueryString()fails (from which I conclude that further LINQ calls force client side evaluation)