Группировать по свойству JsonDocument с неизвестным типом с помощью Entity Framework Core - PullRequest
2 голосов
/ 13 июля 2020

Я использую Entity Framework Core 3.1.5

Я пытаюсь сгруппировать сущности по некоторому свойству JsonDocument, тип которого мне неизвестен. AdditionalData - это свойство JsonDocument сущностей.

Мне нужно выполнить команды в базе данных.

Мне удалось сделать это с двумя ограничениями

  1. Я указал тип свойства (с помощью GetInt32)
  2. Команды выполнялись на клиенте, а не в БД.
    IEnumerable<MetricEntity> metricEntities = _tenantDbContext.Set<MetricEntity>();
    var ii2 = metricEntities.Where(metric => metric.Name == metricName).GroupBy(e =>
        e.AdditionalData!.RootElement.GetProperty(groupByProperty).GetInt32())
    .Select(entities => new
    {
        Count = entities.Count(), MetType = entities.Key, Ent = entities,
    }).ToList();

Мне тоже удалось это сделать, не получив все сущности в результате и с ограничением, что команды выполнялись на клиенте, а не в БД.

var i2 = _tenantDbContext.Set<MetricEntity>()
.Where(metric => metric.Name == metricName)
.GroupBy(e =>
    e.AdditionalData!.RootElement.GetProperty(groupByProperty).GetString())
.Select(entities => new
{
    Count = entities.Count(), MetType = entities.Key
}).ToList();

Но когда я добавляю сущности к результату, как показано ниже:

var i2 = _tenantDbContext.Set<MetricEntity>()
.GroupBy(e =>
    e.AdditionalData!.RootElement.GetProperty(groupByProperty).GetString())
.Select(entities => new
{
    Count = entities.Count(), MetType = entities.Key, ent = entities,
}).ToList();

У меня следующее исключение:

System.InvalidOperationException: Processing of the LINQ expression '(GroupByShaperExpression:
KeySelector: ((m.AdditionalData)#>>{(@__groupByProperty_1)}),
ElementSelector:(EntityShaperExpression:
    EntityType: MetricEntity
    ValueBufferExpression:
        (ProjectionBindingExpression: EmptyProjectionMember)
    IsNullable: False
)
)' by 'RelationalProjectionBindingExpressionVisitor' failed. This may indicate either a bug or a limitation in EF Core. 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.VisitNew(NewExpression newExpression)
   at System.Linq.Expressions.NewExpression.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 Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.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__DisplayClass9_0`1.<Execute>b__0()
   at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQueryCore[TFunc](Object cacheKey, Func`1 compiler)
   at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult](Object cacheKey, Func`1 compiler)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.Execute[TResult](Expression query)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.Execute[TResult](Expression expression)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1.GetEnumerator()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)

1 Ответ

0 голосов
/ 13 июля 2020

Каждый запрос group by должен содержать один или несколько ключей и других свойств, которые имеют функцию агрегирования только в операторе select (Sum, Count и et c). EF попытался преобразовать LINQ в запрос SQL и выдает исключение из-за отсутствия внутренних проверок.

Существует обходной путь:

Оценить данные таблицы до GroupBy. Следующий код загружает все MetricEntities и группирует их в код c#:

var i2 = _tenantDbContext.MetricEntities
.AsEnumerable()
.GroupBy(e =>
    e.AdditionalData!.RootElement.GetProperty(groupByProperty).GetString())
.Select(entities => new
{
    Count = entities.Count(), MetType = entities.Key, ent = entities,
}).ToList();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...