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)