You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I've found that NetTopologySuite (I'm using Microsoft.EntityFrameworkCore.SqlServer.NetTopologySuite, but looking at the code this can affect other providers) can't translate queries which uses properties that are defined on base class, for example:
Point inherits from Geometry
While writing query in the code, like:
.Where(x =>x.Point.IsValid)
it works fine, compiler generates expression pointing at Geometry class, however if you build an expression manually (in my case HotChocolate generates that) you need to use MemberInfo from Geometry class. This is inconsistent with EF Core behavior with any other objects, for example normal hierarchy like:
with the expression built in the same way translates just fine.
Analyzing the code of EF I've found that SqlServerGeometryMemberTranslator uses dictionary with MemberInfo as a key, however MemberInfo got from reflection on Point type is different than the one got from base Geometry type, although they both point to the same property.
Similar code is used in other translators in other supported providers.
I have created a simple test reproducing this issue.
System.InvalidOperationException: The LINQ expression 'DbSet<Test>()
.Where(t => t.GeoLocation.IsValid == True)' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'. See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.
Stack Trace:
QueryableMethodTranslatingExpressionVisitor.Translate(Expression expression)
QueryCompilationContext.CreateQueryExecutorExpression[TResult](Expression query)
QueryCompilationContext.CreateQueryExecutor[TResult](Expression query)
Database.CompileQuery[TResult](Expression query, Boolean async)
QueryCompiler.CompileQueryCore[TResult](IDatabase database, Expression query, IModel model, Boolean async)
<>c__DisplayClass11_0`1.<ExecuteCore>b__0()
CompiledQueryCache.GetOrAddQuery[TResult](Object cacheKey, Func`1 compiler)
QueryCompiler.ExecuteCore[TResult](Expression query, Boolean async, CancellationToken cancellationToken)
QueryCompiler.Execute[TResult](Expression query)
EntityQueryProvider.Execute[TResult](Expression expression)
EntityFrameworkQueryableExtensions.ToQueryString(IQueryable source)
Verbose output
EF Core version
9.0.2
Database provider
Microsoft.EntityFrameworkCore.SqlServer
Target framework
.NET 9.0
Operating system
Windows 11
IDE
Visual Studio 2022 17.14
The text was updated successfully, but these errors were encountered:
it works fine, compiler generates expression pointing at Geometry class, however if you build an expression manually (in my case HotChocolate generates that) you need to use MemberInfo from Geometry class.
If I understand the above correctly, this means that the manually-constructed expression tree somehow differs from the expression tree built by the compiler. It's generally the user's responsibility to build expression trees in ways which exactly match the compiler, since EF generally can't support all expression tree shapes and deviations from the standard, compiler-generated representations.
These property expressions are structurally exactly the same, both point to the same property, the only difference is that in one MemberInfo has ReflectedType set to Point, in other to Geometry. From what I found the only places in EF Core that use MemberInfo as a key for replacements are NetTopologySuite-related providers. I would say that this can be fixed by replacing the key with a tuple of DeclaringType and Name from MemberInfo. https://github.com/dotnet/efcore/blob/59fc95bf505123c79e01aeccecc57ea95b2a5394/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryMemberTranslator.cs
I know that client code can create exactly the same expression as the compiler, however as I've pointed out that in different cases this works fine, you can use MemberInfo with different ReflectedType with queries not touching NetTopologySuite objects.
@Mephistofeles I understand, but expression trees that diverge from the standard compiler representations may be - at least in some sense - incorrect. I'd have to dive in and research this specific discrepancy to know for sure, and since such reports are not uncommon, we typically just tell users to produce the same tree structure as the compiler does. Is there a specific reason you can't just correct the cilent code here?
Bug description
I've found that NetTopologySuite (I'm using Microsoft.EntityFrameworkCore.SqlServer.NetTopologySuite, but looking at the code this can affect other providers) can't translate queries which uses properties that are defined on base class, for example:
Point inherits from Geometry
While writing query in the code, like:
it works fine, compiler generates expression pointing at Geometry class, however if you build an expression manually (in my case HotChocolate generates that) you need to use MemberInfo from Geometry class. This is inconsistent with EF Core behavior with any other objects, for example normal hierarchy like:
with the expression built in the same way translates just fine.
Analyzing the code of EF I've found that SqlServerGeometryMemberTranslator uses dictionary with MemberInfo as a key, however MemberInfo got from reflection on Point type is different than the one got from base Geometry type, although they both point to the same property.
Similar code is used in other translators in other supported providers.
I have created a simple test reproducing this issue.
Your code
Stack traces
Verbose output
EF Core version
9.0.2
Database provider
Microsoft.EntityFrameworkCore.SqlServer
Target framework
.NET 9.0
Operating system
Windows 11
IDE
Visual Studio 2022 17.14
The text was updated successfully, but these errors were encountered: