AspNetCoreOData icon indicating copy to clipboard operation
AspNetCoreOData copied to clipboard

EF6 Compatibility - $filter ; $select does not work

Open cyril-iselin opened this issue 4 years ago • 40 comments

I used the sample "ODataRoutingSample" and replaced EF-Core with EF6.

It generally works until you use "Queryable Features" like $filter or $select then you will recive this expcetion:

NotSupportedException: Unable to create a constant value of type 'Microsoft.OData.Edm.IEdmModel'. Only primitive types or enumeration types are supported in this context. System.Data.Entity.Core.Objects.ELinq.ExpressionConverter+ConstantTranslator.TypedTranslate(ExpressionConverter parent, ConstantExpression linq) System.Data.Entity.Core.Objects.ELinq.ExpressionConverter+TypedTranslator<T_Linq>.Translate(ExpressionConverter parent, Expression linq) System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq) System.Data.Entity.Core.Objects.ELinq.ExpressionConverter+MemberInitTranslator.TypedTranslate(ExpressionConverter parent, MemberInitExpression linq) System.Data.Entity.Core.Objects.ELinq.ExpressionConverter+TypedTranslator<T_Linq>.Translate(ExpressionConverter parent, Expression linq) System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq) System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateLambda(LambdaExpression lambda, DbExpression input) System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateLambda(LambdaExpression lambda, DbExpression input, out DbExpressionBinding binding) System.Data.Entity.Core.Objects.ELinq.ExpressionConverter+MethodCallTranslator+OneLambdaTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, out DbExpression source, out DbExpressionBinding sourceBinding, out DbExpression lambda) System.Data.Entity.Core.Objects.ELinq.ExpressionConverter+MethodCallTranslator+SelectTranslator.Translate(ExpressionConverter parent, MethodCallExpression call) System.Data.Entity.Core.Objects.ELinq.ExpressionConverter+MethodCallTranslator+SequenceMethodTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, SequenceMethod sequenceMethod) System.Data.Entity.Core.Objects.ELinq.ExpressionConverter+MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq) System.Data.Entity.Core.Objects.ELinq.ExpressionConverter+TypedTranslator<T_Linq>.Translate(ExpressionConverter parent, Expression linq) System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq) System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateSet(Expression linq) System.Data.Entity.Core.Objects.ELinq.ExpressionConverter+MethodCallTranslator+UnarySequenceMethodTranslator.Translate(ExpressionConverter parent, MethodCallExpression call) System.Data.Entity.Core.Objects.ELinq.ExpressionConverter+MethodCallTranslator+SequenceMethodTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, SequenceMethod sequenceMethod) System.Data.Entity.Core.Objects.ELinq.ExpressionConverter+MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq) System.Data.Entity.Core.Objects.ELinq.ExpressionConverter+TypedTranslator<T_Linq>.Translate(ExpressionConverter parent, Expression linq) System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq) System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.Convert() System.Data.Entity.Core.Objects.ELinq.ELinqQueryState.GetExecutionPlan(Nullable<MergeOption> forMergeOption) System.Data.Entity.Core.Objects.ObjectQuery<T>+<>c__DisplayClass41_0.<GetResults>b__1() System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction<T>(Func<T> func, IDbExecutionStrategy executionStrategy, bool startLocalTransaction, bool releaseConnectionOnSuccess) System.Data.Entity.Core.Objects.ObjectQuery<T>+<>c__DisplayClass41_0.<GetResults>b__0() System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute<TResult>(Func<TResult> operation) System.Data.Entity.Core.Objects.ObjectQuery<T>.GetResults(Nullable<MergeOption> forMergeOption) System.Data.Entity.Core.Objects.ObjectQuery<T>.<System.Collections.Generic.IEnumerable<T>.GetEnumerator>b__31_0() System.Data.Entity.Internal.LazyEnumerator<T>.MoveNext() System.Collections.Generic.List<T>..ctor(IEnumerable<T> collection) Microsoft.AspNetCore.OData.Query.Container.TruncatedCollection<T>..ctor(IQueryable<T> source, int pageSize, bool parameterize) in TruncatedCollectionOfT.cs : base(Take(source, pageSize, parameterize)) Microsoft.AspNetCore.OData.Query.ODataQueryOptions.LimitResults<T>(IQueryable<T> queryable, int limit, bool parameterize, out bool resultsLimited) in ODataQueryOption.cs TruncatedCollection<T> truncatedCollection = new TruncatedCollection<T>(queryable, limit, parameterize);

Show raw exception details TargetInvocationException: Exception has been thrown by the target of an invocation. System.RuntimeMethodHandle.InvokeMethod(object target, object[] arguments, Signature sig, bool constructor, bool wrapExceptions) System.Reflection.RuntimeMethodInfo.Invoke(object obj, BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture) System.Reflection.MethodBase.Invoke(object obj, object[] parameters) Microsoft.AspNetCore.OData.Query.ODataQueryOptions.LimitResults(IQueryable queryable, int limit, bool parameterize, out bool resultsLimited) in ODataQueryOption.cs + IQueryable results = genericMethod.Invoke(null, args) as IQueryable; Microsoft.AspNetCore.OData.Query.ODataQueryOptions.ApplyPaging(IQueryable result, ODataQuerySettings querySettings) in ODataQueryOption.cs + result = LimitResults(result, pageSize, querySettings.EnableConstantParameterization, out resultsLimited); Microsoft.AspNetCore.OData.Query.ODataQueryOptions.ApplyTo(IQueryable query, ODataQuerySettings querySettings) in ODataQueryOption.cs + result = ApplyPaging(result, querySettings); Microsoft.AspNetCore.OData.Query.EnableQueryAttribute.ApplyQuery(IQueryable queryable, ODataQueryOptions queryOptions) in EnableQueryAttribute.cs + return queryOptions.ApplyTo(queryable, _querySettings); Microsoft.AspNetCore.OData.Query.EnableQueryAttribute.ExecuteQuery(object responseValue, IQueryable singleResultCollection, ControllerActionDescriptor actionDescriptor, HttpRequest request) in EnableQueryAttribute.cs + queryable = ApplyQuery(queryable, queryOptions); Microsoft.AspNetCore.OData.Query.EnableQueryAttribute.OnActionExecuted(ActionExecutedContext actionExecutedContext, object responseValue, IQueryable singleResultCollection, ControllerActionDescriptor actionDescriptor, HttpRequest request) in EnableQueryAttribute.cs + object queryResult = ExecuteQuery(responseValue, singleResultCollection, actionDescriptor, request); Microsoft.AspNetCore.OData.Query.EnableQueryAttribute.OnActionExecuted(ActionExecutedContext actionExecutedContext) in EnableQueryAttribute.cs + object queryResult = OnActionExecuted( Microsoft.AspNetCore.Mvc.Filters.ActionFilterAttribute.OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted) Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context) Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted) Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync() Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted) Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope) Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger) Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext) Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider) Microsoft.AspNetCore.OData.Batch.ODataBatchMiddleware.Invoke(HttpContext context) in ODataBatchMiddleware.cs + await _next(context).ConfigureAwait(false); Microsoft.AspNetCore.OData.Query.ODataQueryRequestMiddleware.Invoke(HttpContext context) in ODataQueryRequestMiddleware.cs + await _next(context).ConfigureAwait(false); Microsoft.AspNetCore.OData.Routing.ODataRouteDebugMiddleware.Invoke(HttpContext context) in ODataRouteDebugMiddleware.cs + await _next(context).ConfigureAwait(false); Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

cyril-iselin avatar May 22 '21 18:05 cyril-iselin

Same here. $expand is also causing the same issue.

tomvanoost avatar Jul 21 '21 13:07 tomvanoost

Same issue with oData 8.0.1

gcfalck avatar Jul 24 '21 05:07 gcfalck

I also have same issue with OData 8.0.1. After some trial and error I did find that by removing the [EnableQuery] attribute (but keeping the [ODataAttributeRouting] attribute), I was able to retrieve all columns without error, so at least I can use my solution, but without the benefit of selecting columns..

gwruck avatar Jul 25 '21 11:07 gwruck

A further note on this: - I managed to get around the error by creating a new .Net 5 project with parallel .Net EF Context that uses the .Net4.8 model. Not ideal, but it got me going again. I am not able to upgrade the base project as it references other (older) libraries. Had to change some of my entities a bit (particularly around the different [key attribute] handling between EF and EF Core), but didn't take too long to implement - once I worked out what to do. Hopefully this helps someone else get around it.

gwruck avatar Jul 26 '21 03:07 gwruck

Are expands working properly for you? I can't seem to get the expand depth beyond 1 level

TehWardy avatar Jul 28 '21 09:07 TehWardy

This is more detail on my issue (in the hopes you can see something I missed) https://github.com/OData/AspNetCoreOData/issues/248

TehWardy avatar Jul 28 '21 09:07 TehWardy

Any news?

newclaus avatar Nov 11 '21 11:11 newclaus

I'm also waiting for a reply since 22 May :-)

I created a fork with the modified version (change ef core to ef6) here: https://github.com/cyril-iselin/AspNetCoreOData

  • Checkout Repo
  • Run OdataRoutingSample

Query which doesnt work:

  • http://localhost:64771/v1/Customers?$select=Name
  • http://localhost:64771/Products?$filter=Id%20eq%202&$expand=Detail

Query which are working:

  • http://localhost:64771/v1/Customers
  • http://localhost:64771/v1/Customers?$filter=name%20eq%20%27Jonier%27
  • http://localhost:64771/Products?$filter=Id%20eq%202

Thanks for helping.

cyril-iselin avatar Nov 11 '21 22:11 cyril-iselin

I have the same problem, I have opened an Issue, hopefully it's going to be fixed soon https://github.com/OData/AspNetCoreOData/issues/367

athinadev avatar Nov 12 '21 08:11 athinadev

In our project we have EF 6.4.4 and Data 8.0.4 and same issue ('Microsoft.OData.Edm.IEdmModel'. Only primitive types or enumeration types are supported in this context.) when we try to use expand feature. Do you have any plan for fixing that bug?

mczachurski avatar Dec 10 '21 10:12 mczachurski

Do we have any update to this on the number of issues that are open here? I'm also affected by this.

theentropic avatar Feb 09 '22 17:02 theentropic

Too many issues open with similar errors and this one really lacks proper details. Would be nice if you guys could unify all these issues into one if they are all the same problem.

Also, I don't personally understand the EntityFramework mentions here. As far as I'm aware, OData is completely oblivious to EF so I can't see how EF would have any impact on OData functionality.

julealgon avatar Feb 09 '22 19:02 julealgon

All I know is that I'm currently using EF6.4.4 with the latest OData (Microsoft.AspNetCore.OData 8.0.7). When I attempt to query an endpoint with $expand, I get the error listed above. I did not have this problem in OData 7 and below.

I do agree that this appears to be duplicates with #367 and #380, but I'm trying to update to the latest version and this is a deal breaker if it does not work.

theentropic avatar Feb 09 '22 19:02 theentropic

@julealgon Incidents #380 describes exactly the problem. And it is relevant to EF6 for sure. I gave look to the odata source code and there is a specific handling for EF6

@theentropic I‘ve managed to solve the $expand issue by declaring the objects wish to expand as Complex Types and remove $expand completely. $select does not work. It is amazing how oData does not offer any more a projection method.

athinadev avatar Feb 09 '22 20:02 athinadev

I gave look to the odata source code and there is a specific handling for EF6

This is very surprising to hear @athinadev . I wonder why that is the case at all. Thanks for letting me know!

julealgon avatar Feb 09 '22 20:02 julealgon

We exposed the functionality to replace/customize OData query LINQ expression. Anyone can try that to build your own LINQ Expression?

xuzhg avatar Feb 09 '22 20:02 xuzhg

Do you have an example of how to override this? I'd be happy to implement it on my end, or is this simply overriding the ApplyQuery function in the EnableQueryAttribute?

theentropic avatar Feb 09 '22 20:02 theentropic

The root cause is from the following changes:

https://github.com/OData/AspNetCoreOData/commit/96abeffdb3c3270a49f0a47c3b90668b0900a5a2

image

By design, we'd target 8.x to EF Core only.

xuzhg avatar Feb 09 '22 23:02 xuzhg

Well thank you for the bad news. You could at least document this as breaking change. We could migrate to EFCore, but there oData has another Issue and the GroupBy raises an error. I think it’s time to abandon oData.

athinadev avatar Feb 10 '22 07:02 athinadev

@xuzhg Thanks for identifying the breaking change. Forgive my ignorance, I'm unfamiliar with the OData implementation, but was this a conscious decision and made of necessity? If so, is OData 8's compatibility with EF documented somewhere? Can it be please?

If by chance compatibility with EF6 was inadvertently broken, given the issues with EFCore and Groupby, OData users (well this user at least, but I suspect there are others...) would very much like OData to remain compatible with EF6 for as long as it takes to address the group by issue. Is there a way this can be achieved?

If not my reading of this is that for anyone wanting to continue using odata $apply groupby with EF will be stuck on OData 7.x and EF6. As @athinadev indicates, this is disappointing.

cam-m avatar Mar 22 '22 00:03 cam-m

@cam-m @athinadev It may not be perfect, but I've managed to hack back in support for EF6 in OData 8. I plan on wrapping the code up in a nuget module and publishing it on github. I will ping you here if you're interested when it's ready.

theentropic avatar Mar 22 '22 13:03 theentropic

@cam-m Yes of course I am interested!!! Please let me know when is fixed

thanks in advance

athinadev avatar Mar 22 '22 15:03 athinadev

@theentropic I'm interested too :). May you can make a PR to this repository? Then the odata team must not document that they have broken ef6 support since more then one year :)

cyril-iselin avatar Mar 22 '22 16:03 cyril-iselin

@theentropic Good on you for that! I'm interested of course but am a bit hamstrung by my project as to which nuget packages I can use - so for me a pull request to this repo is ideal. I'm sure others will appreciate it though.

cam-m avatar Mar 22 '22 20:03 cam-m

I'll see what I can do in terms of a pull request, the way I currently implemented it replaces some of the services, so would need to figure out what to do there.

theentropic avatar Mar 23 '22 13:03 theentropic

Any news? Or an official statement that EF 6 is not supported anymore? @xuzhg

cyril-iselin avatar Apr 09 '22 12:04 cyril-iselin

Or an official statement that EF 6 is not supported anymore?

As far as I know, this has already been confirmed. If you need EF6 support for now, I'd stick with OData v7.

julealgon avatar Apr 11 '22 12:04 julealgon

Or an official statement that EF 6 is not supported anymore?

As far as I know, this has already been confirmed. If you need EF6 support for now, I'd stick with OData v7.

Where has it been confirmed? Here in the comments of this issue or elsewhere?

We've established OData7/EF6 as the technical option. The points remaining to be addressed are, a) was this intentional? b) if not can support be fixed and c) if so, can it be documented clearly (on the releases page) so people don't unwittingly go down this track.

cam-m avatar Apr 11 '22 21:04 cam-m

I had the same issues as mentioned in the other posts. After many many ours of trying all sort of things I got it working. I downgraded from 8.0.10 to 7.5.10 and then it started working. At first I downgraded to 7.5.15 but this conflicted with another Microsoft package. Beside this downgrade I changed nothing.

Glad that I got it working but it's a bit disappointing to see how this bug/feature is treated.

Hope I save someone all the ours I waisted!!

paulschalkwijk avatar Jul 26 '22 12:07 paulschalkwijk

@paulschalkwijk to late. After migrating 240 projects from .Net Framework WebApi.Odata to net6 AspNetCore.OData 8 I found this issue with EF6. Now i must downgrade to 7.x. Disappointing.

yannolaf avatar Aug 24 '22 13:08 yannolaf