在 EFCore 中按多列分组会导致 InvalidOperationException
Grouping by multiple columns in EFCore results in InvalidOperationException
假设我们有模型 A、B 和 C。A 与 B 和 C 之间存在多对多关系。我想创建以下聚合:
+--------+----------------+--------------+---------+
| a_id | b_value_sum | c_value_sum | c_count |
+--------+----------------+--------------+---------+
| 1 | 20 | 10 | 40 |
+--------+----------------+--------------+---------+
查询:
var query =
from a in context.A
from b in a.B.DefaultIfEmpty()
from c in b.C.DefaultIfEmpty()
group new { b, c } by new { a.Id } into g
select new
{
Id = g.Key.ToString(),
ValueBSum = g.Sum(y => y.b.Value),
ValueCSum = g.Sum(y => y.c.Value),
ValueCCount = g.Count()
};
生成的查询:
SELECT
[c].[Id],
COALESCE(SUM([t].[Value]), 0.0),
COALESCE(SUM([t0].[Value]), 0.0),
COUNT(*)
FROM [A] AS [c]
LEFT JOIN (
SELECT
[b].[Value],
[c1].[A_Id]
FROM [AB] AS [c1]
INNER JOIN [B] AS [b] ON [c1].[B_Id] = [b].[Id]
) AS [t] ON [c].[Id] = [t].[A_Id]
LEFT JOIN (
SELECT
[s0].[Value],
[s].[A_Id]
FROM [AC] AS [s]
INNER JOIN [C] AS [s0] ON [s].[C_Id] = [s0].[Id]
) AS [t0] ON [c].[Id] = [t0].[A_Id]
GROUP BY [c].[Id]
结果
System.InvalidOperationException: Operation is not valid due to the current state of the object.
需要注意的一件事是,外部 select 缺少 AS 语句。例如。作为 BValueSum.
将 new { a.Id }
替换为 a.id
可解决问题。但是我想按多列分组,这总是给我上面的错误。
堆栈跟踪:
fail: UseCase[0]
MyProject Request: Unhandled Exception for Request UseCase
System.InvalidOperationException: Operation is not valid due to the current state of the object.
at System.Linq.Expressions.ExpressionExtensions.GetConstantValue[T](Expression expression)
at Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.GetProjectionIndex(ProjectionBindingExpression projectionBindingExpression)
at Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.VisitExtension(Expression extensionExpression)
at System.Linq.Expressions.ExpressionVisitor.VisitUnary(UnaryExpression node)
at Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.ProcessShaper(Expression shaperExpression, RelationalCommandCache& relationalCommandCache, LambdaExpression& relatedDataLoaders, Int32& collectionId)
at Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.VisitShapedQuery(ShapedQueryExpression shapedQueryExpression)
at Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor.VisitExtension(Expression extensionExpression)
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.EntityFrameworkQueryableExtensions.ExecuteAsync[TSource,TResult](MethodInfo operatorMethodInfo, IQueryable`1 source, Expression expression, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ExecuteAsync[TSource,TResult](MethodInfo operatorMethodInfo, IQueryable`1 source, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.CountAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)
at MyProject.Shared.Models.PaginatedList`1.CreateAsync(IQueryable`1 source, Int32 pageNumber, Int32 pageSize) in MyProject\Shared\Models\PaginatedList.cs:line 0
at MyProject.Shared.Behaviours.ValidationBehaviour`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next) in MyProject\Shared\Behaviours\ValidationBehaviour.cs:line 35
at MyProject.Shared.Behaviours.UnhandledExceptionBehaviour`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next) in MyProject\Shared\Behaviours\UnhandledExceptionBehaviour.cs:line 18
可能 EF Core 无法从匿名对象为 .ToString()
创建投影。
尝试删除 .ToString()
,如果需要,post 在客户端实现后处理记录。
假设我们有模型 A、B 和 C。A 与 B 和 C 之间存在多对多关系。我想创建以下聚合:
+--------+----------------+--------------+---------+
| a_id | b_value_sum | c_value_sum | c_count |
+--------+----------------+--------------+---------+
| 1 | 20 | 10 | 40 |
+--------+----------------+--------------+---------+
查询:
var query =
from a in context.A
from b in a.B.DefaultIfEmpty()
from c in b.C.DefaultIfEmpty()
group new { b, c } by new { a.Id } into g
select new
{
Id = g.Key.ToString(),
ValueBSum = g.Sum(y => y.b.Value),
ValueCSum = g.Sum(y => y.c.Value),
ValueCCount = g.Count()
};
生成的查询:
SELECT
[c].[Id],
COALESCE(SUM([t].[Value]), 0.0),
COALESCE(SUM([t0].[Value]), 0.0),
COUNT(*)
FROM [A] AS [c]
LEFT JOIN (
SELECT
[b].[Value],
[c1].[A_Id]
FROM [AB] AS [c1]
INNER JOIN [B] AS [b] ON [c1].[B_Id] = [b].[Id]
) AS [t] ON [c].[Id] = [t].[A_Id]
LEFT JOIN (
SELECT
[s0].[Value],
[s].[A_Id]
FROM [AC] AS [s]
INNER JOIN [C] AS [s0] ON [s].[C_Id] = [s0].[Id]
) AS [t0] ON [c].[Id] = [t0].[A_Id]
GROUP BY [c].[Id]
结果
System.InvalidOperationException: Operation is not valid due to the current state of the object.
需要注意的一件事是,外部 select 缺少 AS 语句。例如。作为 BValueSum.
将 new { a.Id }
替换为 a.id
可解决问题。但是我想按多列分组,这总是给我上面的错误。
堆栈跟踪:
fail: UseCase[0]
MyProject Request: Unhandled Exception for Request UseCase
System.InvalidOperationException: Operation is not valid due to the current state of the object.
at System.Linq.Expressions.ExpressionExtensions.GetConstantValue[T](Expression expression)
at Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.GetProjectionIndex(ProjectionBindingExpression projectionBindingExpression)
at Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.VisitExtension(Expression extensionExpression)
at System.Linq.Expressions.ExpressionVisitor.VisitUnary(UnaryExpression node)
at Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.ProcessShaper(Expression shaperExpression, RelationalCommandCache& relationalCommandCache, LambdaExpression& relatedDataLoaders, Int32& collectionId)
at Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.VisitShapedQuery(ShapedQueryExpression shapedQueryExpression)
at Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor.VisitExtension(Expression extensionExpression)
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.EntityFrameworkQueryableExtensions.ExecuteAsync[TSource,TResult](MethodInfo operatorMethodInfo, IQueryable`1 source, Expression expression, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ExecuteAsync[TSource,TResult](MethodInfo operatorMethodInfo, IQueryable`1 source, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.CountAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)
at MyProject.Shared.Models.PaginatedList`1.CreateAsync(IQueryable`1 source, Int32 pageNumber, Int32 pageSize) in MyProject\Shared\Models\PaginatedList.cs:line 0
at MyProject.Shared.Behaviours.ValidationBehaviour`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next) in MyProject\Shared\Behaviours\ValidationBehaviour.cs:line 35
at MyProject.Shared.Behaviours.UnhandledExceptionBehaviour`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next) in MyProject\Shared\Behaviours\UnhandledExceptionBehaviour.cs:line 18
可能 EF Core 无法从匿名对象为 .ToString()
创建投影。
尝试删除 .ToString()
,如果需要,post 在客户端实现后处理记录。