Open peterwurzinger opened 4 years ago
@smitpatel @maumar Thoughts?
We cannot translate Coalesce over entityType to Sql. This particular form will always client eval. It could be written to have coalesce over properties in final projection so it can be evaluated on client. productToShip.Documents
is never going to be Sql representable.
@smitpatel @ajcvickers I digged a little deeper into that, and I got a better understanding of why EF Core can't translate coalescing on an entity level. For the sake of completeness, with that understanding I rephrased the projection in the example above to:
FirstDocumentId = (welcomePackage.Documents.FirstOrDefault()
?? product.Documents.FirstOrDefault()).Id
It's not pretty, but it works.
What I want to elaborate now is another alternative of the projection, which also didn't work
FirstDocumentId = (product.WelcomePackage ?? product).Documents.FirstOrDefault().Id
Because this expression has quite an easy equivalent in SQL:
select FirstDocumentId = doc.Id
from Product product
left join Document doc
on doc.ProductId = coalesce(product.WelcomePackageId, product.Id)
The difference between those two expressions
product.Documents.FirstOrDefault().Id
//and
(product.WelcomePackage ?? product).Documents.FirstOrDefault().Id
is only represented in the join condition of the resulting SQL:
on doc.ProductId = product.Id
-- and
on doc.ProductId = coalesce(product.WelcomePackageId, product.Id)
I might be wrong, but I could think about this being not too hard to implement..?
Most likely related/dupe: #17782
Hi,
To simplify things I will treat the domain model for reproducing the issue as "our domain".
We have an entity
Product
with a self-referencing optional (!) relationship:In a query we project properties from this entity, as well as ones from other related entities - e.g.
Document
s. For this projections we use some kind of fallback - ifWelcomePackage
is set, we treat that as the entity to project from, else we fall back to the selectedProduct
. Basicallylet projectionProduct = (product.WelcomePackage ?? product)
When we try to project
projectionProduct.Documents.Select(...)/FirstOrDefault().Id/...
an exception is thrown:System.InvalidOperationException : When called from 'VisitLambda', rewriting a node of type 'System.Linq.Expressions.ParameterExpression' must return a non-null value of the same type. Alternatively, override 'VisitLambda' and change it to not visit children of this type.
Stack traced included below.Steps to reproduce
Exception:
Further technical details
EF Core version: 3.1.2 Database provider: Microsoft.EntityFrameworkCore.SqlServer 3.1.2 Target framework: .NET Core 3.1 Operating system: Windows 10 x64 IDE: Visual Studio 2019 16.4