Open fabiocbr75 opened 3 years ago
Hello. I'm getting a similar error when trying to use simple groupby:
?$apply=groupby((Title))
An unhandled exception occurred while processing the request. InvalidOperationException: The converter specified on 'Microsoft.AspNetCore.OData.Query.Wrapper.GroupByWrapper' is not compatible with the type 'Microsoft.AspNetCore.OData.Query.Wrapper.GroupByWrapper'. System.Text.Json.ThrowHelper.ThrowInvalidOperationException_SerializationConverterOnAttributeNotCompatible(Type classTypeAttributeIsOn, PropertyInfo propertyInfo, Type typeToConvert)
I managed to track the resulting query in MySql db and the result was pretty weird
SELECT 'Title' AS 'Name', 'f'.'title' AS 'Value' FROM 'table' AS 'f' GROUP BY 'f'.'title'
That was not expected, 'cause I still want all other fields and the query force select new fields with some weird names. The query run on my db, but the odata always return this error
Our APIs produce similar errors for aggregates:
{{baseUrl}}/Article?$apply=aggregate(CurrentPP with sum as mySum)
{{baseUrl}}/OrderDetail?$apply=filter(OrderPositionId eq 2462)/aggregate(Quantity with sum as TotalQuantity)
System.InvalidOperationException: Processing of the LINQ expression 'GroupByShaperExpression:
KeySelector: new NoGroupByWrapper(),
ElementSelector:EntityShaperExpression:
EntityType: Article
ValueBufferExpression:
ProjectionBindingExpression: EmptyProjectionMember
IsNullable: False
' by 'RelationalProjectionBindingExpressionVisitor' failed. This may indicate either a bug or a limitation in Entity Framework. See https://go.microsoft.com/fwlink/?linkid=2101433 for more detailed information.
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.VisitExtension(Expression extensionExpression)
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.Visit(Expression expression)
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.VisitUnary(UnaryExpression unaryExpression)
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.Visit(Expression expression)
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.Visit(Expression expression)
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.VisitUnary(UnaryExpression unaryExpression)
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.Visit(Expression expression)
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.VisitMemberAssignment(MemberAssignment memberAssignment)
at System.Linq.Expressions.ExpressionVisitor.VisitMemberBinding(MemberBinding node)
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.VisitMemberInit(MemberInitExpression memberInitExpression)
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.Visit(Expression expression)
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.VisitMemberAssignment(MemberAssignment memberAssignment)
at System.Linq.Expressions.ExpressionVisitor.VisitMemberBinding(MemberBinding node)
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.VisitMemberInit(MemberInitExpression memberInitExpression)
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.Visit(Expression expression)
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.Translate(SelectExpression selectExpression, Expression expression)
at Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.TranslateSelect(ShapedQueryExpression source, LambdaExpression selector)
at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
at Microsoft.EntityFrameworkCore.Query.QueryCompilationContext.CreateQueryExecutor[TResult](Expression query)
at Microsoft.EntityFrameworkCore.Storage.Database.CompileQuery[TResult](Expression query, Boolean async)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileQueryCore[TResult](IDatabase database, Expression query, IModel model, Boolean async)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass12_0`1.<ExecuteAsync>b__0()
at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult](Object cacheKey, Func`1 compiler)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.ExecuteAsync[TResult](Expression query, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.ExecuteAsync[TResult](Expression expression, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1.GetAsyncEnumerator(CancellationToken cancellationToken)
at Microsoft.AspNetCore.Mvc.Infrastructure.AsyncEnumerableReader.ReadInternal[T](Object value)
at Microsoft.AspNetCore.Mvc.Infrastructure.ObjectResultExecutor.ExecuteAsyncEnumerable(ActionContext context, ObjectResult result, Object asyncEnumerable, Func`2 reader)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeResultAsync>g__Logged|21_0(ResourceInvoker invoker, IActionResult result)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResultFilterAsync>g__Awaited|29_0[TFilter,TFilterAsync](ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
We also had problems with groupby using Newtonsoft.
We were able to solve that problem opting out of Newtonsoft, by removing .AddNewtonsoftJson()
.
Here are the cases we had problems with which now work without Newtonsoft:
{{baseUrl}}/Article?$apply=groupby((Brand/Name))&$top=10&$skip=30&$orderby=Brand/Name
{{baseUrl}}/Article?$apply=groupby((Brand/Id))&$top=10&$skip=30&$orderby=Brand/Id
As of v8.0.0.0-rc2
this is still not working. Is this being tracked someplace else?
It does work on the sample since it's using the In Memory Database, as soon as you switch to Sqlite or SqlServer it stops working.
To reproduce, make the following changes to the sample:
// Program.cs
public static void Main(string[] args)
{
var host = CreateHostBuilder(args).Build();
// keep a connection open for the duration of the process so it's not deleted.
using var conn = new SqliteConnection($"Data Source = TestApp;" +
$" Mode = Memory; Cache = Shared");
conn.Open();;
using var scope = host.Services.CreateScope();
scope.ServiceProvider.GetRequiredService<MyDataContext>().Database.EnsureCreated();
host.Run();
conn.Close();
}
// Startup.cs
services.AddDbContext<MyDataContext>(opt =>
opt.UseLazyLoadingProxies()
.UseSqlite($"Data Source = TestApp;" +
$" Mode = Memory; Cache = Shared")
// .UseInMemoryDatabase("MyDataContextList")
);
Then execute an $apply
: http://localhost:5000/products?$apply=aggregate($count as OrderCount)
fail: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1]
An unhandled exception has occurred while executing the request.
System.InvalidOperationException: Processing of the LINQ expression 'GroupByShaperExpression:
KeySelector: new NoGroupByWrapper(),
ElementSelector:EntityShaperExpression:
EntityType: Product
ValueBufferExpression:
ProjectionBindingExpression: EmptyProjectionMember
IsNullable: False
' by 'RelationalProjectionBindingExpressionVisitor' failed. This may indicate either a bug or a limitation in Entity Framework. See https://go.microsoft.com/fwlink/?linkid=2101433 for more detailed information.
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.VisitExtension(Expression extensionExpression)
at System.Linq.Expressions.Expression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.Visit(Expression expression)
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.VisitUnary(UnaryExpression unaryExpression)
at System.Linq.Expressions.UnaryExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.Visit(Expression expression)
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.Visit(Expression expression)
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.VisitUnary(UnaryExpression unaryExpression)
at System.Linq.Expressions.UnaryExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.Visit(Expression expression)
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.VisitMemberAssignment(MemberAssignment memberAssignment)
at System.Linq.Expressions.ExpressionVisitor.VisitMemberBinding(MemberBinding node)
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.VisitMemberInit(MemberInitExpression memberInitExpression)
at System.Linq.Expressions.MemberInitExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.Visit(Expression expression)
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.VisitMemberAssignment(MemberAssignment memberAssignment)
at System.Linq.Expressions.ExpressionVisitor.VisitMemberBinding(MemberBinding node)
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.VisitMemberInit(MemberInitExpression memberInitExpression)
at System.Linq.Expressions.MemberInitExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.Visit(Expression expression)
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.Translate(SelectExpression selectExpression, Expression expression)
at Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.TranslateSelect(ShapedQueryExpression source, LambdaExpression selector)
at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at Microsoft.EntityFrameworkCore.Query.QueryCompilationContext.CreateQueryExecutor[TResult](Expression query)
at Microsoft.EntityFrameworkCore.Storage.Database.CompileQuery[TResult](Expression query, Boolean async)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileQueryCore[TResult](IDatabase database, Expression query, IModel model, Boolean async)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass12_0`1.<ExecuteAsync>b__0()
at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult](Object cacheKey, Func`1 compiler)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.ExecuteAsync[TResult](Expression query, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.ExecuteAsync[TResult](Expression expression, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1.GetAsyncEnumerator(CancellationToken cancellationToken)
at Microsoft.AspNetCore.Mvc.Infrastructure.AsyncEnumerableReader.ReadInternal[T](Object value)
at Microsoft.AspNetCore.Mvc.Infrastructure.ObjectResultExecutor.ExecuteAsyncEnumerable(ActionContext context, ObjectResult result, Object asyncEnumerable, Func`2 reader)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResultFilterAsync>g__Awaited|29_0[TFilter,TFilterAsync](ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
at Microsoft.AspNetCore.OData.Batch.ODataBatchMiddleware.Invoke(HttpContext context) in /home/lchaia/dev/AspNetCoreOData/src/Microsoft.AspNetCore.OData/Batch/ODataBatchMiddleware.cs:line 66
at Microsoft.AspNetCore.OData.Query.ODataQueryRequestMiddleware.Invoke(HttpContext context) in /home/lchaia/dev/AspNetCoreOData/src/Microsoft.AspNetCore.OData/Query/ODataQueryRequestMiddleware.cs:line 64
at Microsoft.AspNetCore.OData.Routing.ODataRouteDebugMiddleware.Invoke(HttpContext context) in /home/lchaia/dev/AspNetCoreOData/src/Microsoft.AspNetCore.OData/Routing/ODataRouteDebugMiddleware.cs:line 82
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
Still no change on 8.0.0-rc3
.
I have got a temporary workaround that might be of interest until this issue is solved.
The following example to use aggregates will materialize the whole dataset before applying the query. Which means the whole dataset will be loaded into memory of the API before filters and so on apply. At least the whole dataset has not to be returned to the client. So be aware of that when making use of the following example.
Create a generic ApiController with an Action that should execute the Aggregate and materializes the dataset before applying the query:
[ApiController]
public class AggregateController<TEntity> : ControllerBase
{
private readonly MyContext _myContext;
public AggregateController(MyContext myContext)
{
_myContext = myContext;
}
[HttpGet("")]
public async Task<IActionResult> Aggregate(ODataQueryOptions<TEntity> queryOptions)
{
var dbSet = _myContext.Set<TEntity>();
var dataArray = dbSet.ToArray();
IQueryable query = queryOptions.ApplyTo(dataArray().AsQueryable());
return Ok(query);
}
}
Create a GenericControllerFeatureProvider which is required to provide a generic controller for each available Entity:
public class GenericControllerFeatureProvider : IApplicationFeatureProvider<ControllerFeature>
{
public void PopulateFeature(IEnumerable<ApplicationPart> parts, ControllerFeature feature)
{
var contextType = typeof(MyContext);
var entityTypes = contextType.GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance)
.Where(x => x.PropertyType.IsGenericType)
.Where(x => x.PropertyType.GetGenericTypeDefinition() == typeof(DbSet<>))
.Select(x => x.PropertyType.GetGenericArguments().FirstOrDefault())
.Where(x => x != null)
.ToArray();
foreach (var entityType in entityTypes)
{
feature.Controllers.Add(typeof(AggregateController<>).MakeGenericType(entityType).GetTypeInfo());
}
}
}
public static class GenericControllerFeatureProviderExtensions
{
public static IMvcBuilder AddGenericControllerFeatureProvider(this IMvcBuilder builder)
{
return builder.ConfigureApplicationPartManager(x => x.FeatureProviders.Add(new GenericControllerFeatureProvider()));
}
}
Create a GenericControllerConvention which adds the routes for each entity to a generic controller:
public class GenericControllerConvention : Attribute, IControllerModelConvention
{
public void Apply(ControllerModel controller)
{
if (controller.ControllerType.IsGenericType)
{
var entityType = controller.ControllerType.GenericTypeArguments.FirstOrDefault();
if (entityType != null)
{
if (controller.ControllerType.AsType() == typeof(AggregateController<>).MakeGenericType(entityType))
{
controller.Selectors.Add(new SelectorModel()
{
AttributeRouteModel = new AttributeRouteModel(new RouteAttribute($"api/Aggregate/{entityType.Name}"))
});
}
}
}
}
}
Wire everything up in Startup.cs:
services.AddControllers(options =>
{
options.Conventions.Add(new GenericControllerConvention());
}).AddGenericControllerFeatureProvider();
Same on 8.0.1, simple groupBy do work, not with aggregate (makes the groupBy useless in most situations).
Works
?$apply=groupby((Field))
Doesn't
?$apply=groupby((Field),aggregate(Title with countdistinct as total)))
I know that a lot of effort is made every day on this great piece of software, but can this feature benefit from a higher priority ?
I'm starting to become convinced that this has never worked as i've been asking about it for some time.
... it doesn't seem to have a home where someone will actually look at it either.
any progress here ?
Seems like this is dead in the water? The fallback seems to be making custom functions for the required functionality
Yeh I've been doing that or supporting non odata based params that do the same thing ... tricky though if the returned object set changes shape.
I'm having the same problem when I try to use $expand.
PackageReference Include="Microsoft.AspNetCore.OData" Version="8.0.2"
I have been following this topic since .Net Core 2.0 and it is still not fixed. I have an application that is dependent on apply/groupby and this is the only reason why I am still on .Net Framework for this app. Very annoying. Starting to doubt that it will ever be fixed. Considering to learn node or graphql...
Are there are alternative ORMs that do support this?
This small hack works for me and allow to use $apply
<PackageReference Include="linq2db.EntityFrameworkCore" Version="5.3.1" />
var query = _context.Set<TEntity>().AsNoTracking();
if (Request.Query.ContainsKey("$apply"))
query = query.ToLinqToDB();
return query;
Thanx Airex. I got groupby working in .Net core 2.0 by using Linq2db, but it was broken in .net 3.1 and could not get it working. Is your example tested on .Net Core 3.1? Thx / Richard
Thanx Airex. I got groupby working in .Net core 2.0 by using Linq2db, but it was broken in .net 3.1 and could not get it working. Is your example tested on .Net Core 3.1? Thx / Richard
I am using this approach in .net 5.0 and EF 5.0.7. For 3.1 may be good idea to try different versions of Linq2db
Thanx Airex. I got groupby working in .Net core 2.0 by using Linq2db, but it was broken in .net 3.1 and could not get it working. Is your example tested on .Net Core 3.1? Thx / Richard
I am using this approach in .net 5.0 and EF 5.0.7. For 3.1 may be good idea to try different versions of Linq2db
Ok, thanx! Will try it out!
Would it be possible to just use Linq2db for all of the OData calls and remove EF entirely?
This seems to be fixed in .NET 6.
<PackageReference Include="Microsoft.AspNetCore.OData" Version="8.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.0" />
Yes! I can confirm it has finally been fixed for .Net core in .Net 6. Have tested group by with different aggregates and it is working fine now, without the Linq2db workaround. Som hero at Microsoft has finally got it working after 5 years (!) since .Net core initial release. Now I can finally ugrade my core 2.0 apps with the Linq2db workaraound and also convert my other apps from .Net Framework 4.x (that has been working all along)...
Same old story, force another framework version on us that's broken in 100 other ways. Sigh ...
I'm getting whiplash with this once a year having to completely rebuild my apps from scratch because of breaking changes between framework versions.
Will Microsoft ever stop this BS so I can stabilise my codebase for 5 minutes?
I say this because the title literally states the version of frameworks that are broken and as always the answer is "don't use this, use another version" ... in the past i've been in the situation where multiple teams at Microsoft told me to both upgrade and downgrade my framework version in the same week.
Is there no way this fix can be pulled in to .Net 5 at least so I can avoid using an unstable .Net version?
The long term solution is to avoid Entity Framework entirely. I think EF Core 6 was the first time I wasn't burned by a new version breaking something I'm using. The team just can't be trusted to maintain stability.
Yeh I can't find a decent replacement for it though ... When you use features like OData it handles stuff like wiring up related entities in expands for you. I'm open to replacing it though, but I do recall the dapper guys not even understanding the question when I asked them.
EF is both a major pain in some ways but a god send in others ... you're right though, the constant breaking changes are a very bad running joke.
Dapper is definitely not an option unless you want to create your own SQL generator from scratch.
Presumably any ORM that supports IQueryable would work, but I never looked into it deeply.
Exactly my thoughts
Hello,
I have problems with Apply/GroupBy/Aggregate in .NET 5 / Odata v8preview3 / EFCore 5.
I'm not able to use simple expression like $apply=aggregate($count as OrderCount).
I receive the following error:
Can you help me to resolve this problem?
Obviously for me, it's not a solution to use ToList() and aggregate client side.
Thanks
Fabio