Webapi: [vNext] Support for Entity Framework Core

Created on 10 Mar 2016  路  16Comments  路  Source: OData/WebApi

Hi,

What is the roadmap for support of Entity Framework Core?

Thanks,

P1 efcore feature featurnetcore

Most helpful comment

Hi,

I am looking for Entity Framework Core support in OData v4 with release that lines up with ASP.NET and Entity Framework Core.

EF Core Roadmap lines up with ASP.NET Core: https://github.com/aspnet/EntityFramework/wiki/Roadmap

Overall trying to understand how the roadmaps of ASP.NET, Entity Framework and OData v4 line up.

Thanks,

All 16 comments

@pisees which version do you want to support EF core? Can you mention more?

Hi,

I am looking for Entity Framework Core support in OData v4 with release that lines up with ASP.NET and Entity Framework Core.

EF Core Roadmap lines up with ASP.NET Core: https://github.com/aspnet/EntityFramework/wiki/Roadmap

Overall trying to understand how the roadmaps of ASP.NET, Entity Framework and OData v4 line up.

Thanks,

@pisees - We are working on an AspNetCore compatible version of OData WebApi (see #939) but that does not include the work for EFCore yet, we'll use this item to track it. But we'd likely only look at making our AspNetCore version work with the EFCore. Is this what you are looking for?

with regards to efcore support will odata also support entities that have no primary key as announced by the ef core v2.1 ?

Users have had some success with OData WebApi for NetCore and EFCore. One notable exception, Aggregation fails due to lack of AsQueryable support, is discussed in #1154.

One obstacle is the lack of lazy-loading in EFCore:

### Lazy loading
Lazy loading is not yet supported by EF Core. You can view the lazy loading item on our backlog to track [this feature](https://github.com/aspnet/EntityFramework/issues/3797).

OData WebApi expects that navigation properties can be loaded lazily. Using [EnableQuery] essential says "return to me a collection of something and I'll run queries against it for you". When those queries involve navigation properties, the lack of lazy loading causes the query to fail.

I have a branch with the EFCore version of Aggregation tests + solution here: https://github.com/robward-ms/WebApi/tree/NetCore-E2ECore-EFCore

when can we migrate from asp.net 4.x + ef + web api + odata
to asp.net core, Is there an estimate time ?
or it's still a long way off.

@keatkeat87 OData has already released beta version for ASP.NET Core OData, see https://www.nuget.org/packages/Microsoft.AspNetCore.OData/7.0.0-beta4.

You can use it as a starting point. Besides, we are planning to release 7.0 RTM this week.

If you want some sample code, you can refer to:
https://github.com/OData/ODataSamples/tree/master/WebApi/v7.x/AspNetCoreODataBasicSample

Please let us know any feedback. Thanks.

@xuzhg Any plans to support $aggregate before the release of 7.0.0?

I'm currently on beta2 and noticed feature/netcore hadn't been updated in about 2 months, but now that I look, it appears that that development might have moved backed to master?

I've also been investigating https://github.com/voronov-maxim/OdataToEntity as it appears to have good odata spec coverage

@xuzhg $aggregate and https://github.com/OData/WebApi/issues/1257 (Ability to modify query after applying queryOptions) are my 2 biggest blockers right now

@techniq Yes. we have moved to master branch for v7.0 for almost 2 months.

For the $aggregate, would you please test your scenarios with beta4 and EFCore 2.1.x? I had some tests before, it seems the basic scenario can work.

@xuzhg I'm upgrading now and will report back. Want me to respond within #1154 (and I'll close #1221 if resolved).

Any thoughts on #1257?

@techniq Any help needed for your problem?

@xuzhg Yes please :). Sorry, I've been swamped and haven't had a chance to reply. I'm currently using 7.0.0 (I haven't gotten around to upgrading to 7.0.2 yet) but I just tested $apply=aggregate and still throwing an exception:

System.ArgumentException: Value does not fall within the expected range.
   at System.SharedTypeExtensions.GetSequenceType(Type type)
   at Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.VisitMainFromClause(MainFromClause fromClause, QueryModel queryModel)
   at Remotion.Linq.Clauses.MainFromClause.Accept(IQueryModelVisitor visitor, QueryModel queryModel)
   at Remotion.Linq.QueryModelVisitorBase.VisitQueryModel(QueryModel queryModel)
   at Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.VisitQueryModel(QueryModel queryModel)
   at Microsoft.EntityFrameworkCore.Query.RelationalQueryModelVisitor.VisitQueryModel(QueryModel queryModel)
   at Microsoft.EntityFrameworkCore.Query.RelationalQueryModelVisitor.VisitSubQueryModel(QueryModel queryModel)
   at Microsoft.EntityFrameworkCore.Query.RelationalQueryModelVisitor.LiftSubQuery(IQuerySource querySource, SubQueryExpression subQueryExpression)
   at Microsoft.EntityFrameworkCore.Query.RelationalQueryModelVisitor.CompileMainFromClauseExpression(MainFromClause mainFromClause, QueryModel queryModel)
   at Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.VisitMainFromClause(MainFromClause fromClause, QueryModel queryModel)
   at Remotion.Linq.Clauses.MainFromClause.Accept(IQueryModelVisitor visitor, QueryModel queryModel)
   at Remotion.Linq.QueryModelVisitorBase.VisitQueryModel(QueryModel queryModel)
   at Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.VisitQueryModel(QueryModel queryModel)
   at Microsoft.EntityFrameworkCore.Query.RelationalQueryModelVisitor.VisitQueryModel(QueryModel queryModel)
   at Microsoft.EntityFrameworkCore.Query.RelationalQueryModelVisitor.VisitSubQueryModel(QueryModel queryModel)
   at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.SqlTranslatingExpressionVisitor.VisitSubQuery(SubQueryExpression expression)
   at Remotion.Linq.Clauses.Expressions.SubQueryExpression.Accept(ExpressionVisitor visitor)
   at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
   at Remotion.Linq.Parsing.ThrowingExpressionVisitor.Visit(Expression expression)
   at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.SqlTranslatingExpressionVisitor.Visit(Expression expression)
   at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.RelationalProjectionExpressionVisitor.Visit(Expression expression)
   at System.Linq.Expressions.ExpressionVisitor.VisitMemberAssignment(MemberAssignment node)
   at System.Linq.Expressions.ExpressionVisitor.VisitMemberBinding(MemberBinding node)
   at System.Linq.Expressions.ExpressionVisitor.Visit[T](ReadOnlyCollection`1 nodes, Func`2 elementVisitor)
   at System.Linq.Expressions.ExpressionVisitor.VisitMemberInit(MemberInitExpression node)
   at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.RelationalProjectionExpressionVisitor.VisitMemberInit(MemberInitExpression memberInitExpression)
   at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.RelationalProjectionExpressionVisitor.Visit(Expression expression)
   at System.Linq.Expressions.ExpressionVisitor.VisitMemberAssignment(MemberAssignment node)
   at System.Linq.Expressions.ExpressionVisitor.VisitMemberBinding(MemberBinding node)
   at System.Linq.Expressions.ExpressionVisitor.Visit[T](ReadOnlyCollection`1 nodes, Func`2 elementVisitor)
   at System.Linq.Expressions.ExpressionVisitor.VisitMemberInit(MemberInitExpression node)
   at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.RelationalProjectionExpressionVisitor.VisitMemberInit(MemberInitExpression memberInitExpression)
   at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.RelationalProjectionExpressionVisitor.Visit(Expression expression)
   at Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.VisitSelectClause(SelectClause selectClause, QueryModel queryModel)
   at Microsoft.EntityFrameworkCore.Query.RelationalQueryModelVisitor.VisitSelectClause(SelectClause selectClause, QueryModel queryModel)
   at Remotion.Linq.Clauses.SelectClause.Accept(IQueryModelVisitor visitor, QueryModel queryModel)
   at Remotion.Linq.QueryModelVisitorBase.VisitQueryModel(QueryModel queryModel)
   at Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.VisitQueryModel(QueryModel queryModel)
   at Microsoft.EntityFrameworkCore.Query.RelationalQueryModelVisitor.VisitQueryModel(QueryModel queryModel)
   at Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.CreateQueryExecutor[TResult](QueryModel queryModel)
   at Microsoft.EntityFrameworkCore.Storage.Database.CompileQuery[TResult](QueryModel queryModel)

I have been experimenting with https://github.com/voronov-maxim/OdataToEntity which supports EF Core and $apply=aggregate so I don't thin the issue is on the EF Core side, as some thoughts believed. See their SelectTest suite (which I had running locally and fully passing.

I currently have 2 major issues if you could look into, I would be very happy:

$apply=aggreate support (tracked via #1154 and #1221)

Issue #1221 might be able to be closed now as it appears to throw System.ArgumentException: Value does not fall within the expected range. with something like http://localhost:5000/odata/Balances?$apply=aggregate(Actual with sum as TotalActual) I also tried http://localhost:5000/odata/Departments?$apply=groupby((IsActive)) and it threw

System.NullReferenceException: Object reference not set to an instance of an object.
   at Microsoft.AspNet.OData.Query.Expressions.GroupByWrapper.GetHashCode()
   at System.Collections.Generic.ObjectEqualityComparer`1.GetHashCode(T obj)
   at System.Linq.Lookup`2.InternalGetHashCode(TKey key)
   at System.Linq.Lookup`2.GetGrouping(TKey key, Boolean create)
   at System.Linq.Lookup`2.Create[TSource](IEnumerable`1 source, Func`2 keySelector, Func`2 elementSelector, IEqualityComparer`1 comparer)
   at System.Linq.GroupedEnumerable`3.GetEnumerator()
   at System.Linq.Enumerable.SelectEnumerableIterator`2.MoveNext()
   at Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.ExceptionInterceptor`1.EnumeratorExceptionInterceptor.MoveNext()
   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeList(JsonWriter writer, IEnumerable values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter jsonWriter, Object value, Type objectType)
   at Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter jsonWriter, Object value, Type objectType)
   at Newtonsoft.Json.JsonSerializer.Serialize(JsonWriter jsonWriter, Object value)
   at Microsoft.AspNetCore.Mvc.Formatters.JsonOutputFormatter.WriteObject(TextWriter writer, Object value)
   at Microsoft.AspNetCore.Mvc.Formatters.JsonOutputFormatter.WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeResultAsync(IActionResult result)
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextResultFilterAsync[TFilter,TFilterAsync]()
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResultExecutedContext context)
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeResultFilters()
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextResourceFilter()
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context)
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeFilterPipelineAsync()
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeAsync()
   at Microsoft.AspNetCore.Builder.RouterMiddleware.Invoke(HttpContext httpContext)
   at Microsoft.AspNetCore.Diagnostics.StatusCodePagesMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)

Ability to modify query after applying queryOptions (tracked via #1257)

The Issue explains in detail the issue (a regression from .NET Framework / 6.0.0).

@xuzhg It would probably be best to discuss these in there applicable issues, but since you asked here, I wanted to make sure it didn't get lost)

@xuzhg Any thoughts on my previous comment regarding aggregate and fixing queryOptions.ApplyTo() regression

what would the teams thoughts be around supporting non relation data sources via ef core ie. CosmosDB and Graph via germlin etc.

I think that's supported. Let's close it.

Was this page helpful?
0 / 5 - 0 ratings