Сумма EF Core на свойствах вложенной коллекции не работает - PullRequest
2 голосов
/ 29 марта 2020

Моя база данных имеет следующую структуру: один пользователь может иметь несколько учетных записей. Одна учетная запись может иметь несколько переводов.

Это конфигурация карты. Я хочу хранить в моем DTO информацию о каждом пользователе и его общей экономии в каждом аккаунте. (код ниже представляет одну часть всей конфигурации).

this.CreateMap<User, UserTestModel>()
    .ForMember(
        utm => utm.AccountsSavings, 
        options => options.MapFrom(u => u.Accounts
            .Select(a => a.Transfers.Sum(t => t.Amount))
            .ToList()));

Мой запрос к базе данных (я использую EF Core 3.1.3 с базой данных Sqlite) выглядит следующим образом:

var resultSet = await this._dbContext.Users
    .ProjectTo<UserTestModel>(this.Mapper.ConfigurationProvider)
    .ToListAsync(cancellationToken)
    .ConfigureAwait(false);

Однако выдается следующее исключение.

*

System.InvalidOperationException: выражение LINQ 'DbSet .Where (t => EF.Property> (( EntityShaperExpression: EntityType: Account ValueBufferExpression: (ProjectionBindingExpression: EmptyProjectionMember) IsNullable: False), "Id")! = Null && EF. ") == EF.Property> (t," AccountId ")) .Sum (t => t.Amount) 'не удалось перевести. Либо переписать запрос в форме, которую можно перевести, либо переключиться на оценку клиента явно, вставив вызов либо AsEnumerable (), AsAsyncEnumerable (), ToList (), либо ToListAsyn c ().

*

Это проблема с моим кодом, или, скорее, с некоторыми из платформ, которые я использую в настоящее время (AutoMapper или EF Core)?

Изменить 1:

Я решил попытаться вручную собрать эту информацию из User сущностей, но этот код приводит к тому же исключению, которое означает, что это не ошибка Automapper:

var resultSet = await this._dbContext.Users
    .Select(u => u.Accounts.Select(a => a.Transfers.Sum(t => t.Amount)).ToList())
    .ToListAsync(cancellationToken)
    .ConfigureAwait(false);

Редактировать 2:

Создана проблема на GitHub EntityFrameworkCore: https://github.com/dotnet/efcore/issues/20455

1 Ответ

2 голосов
/ 29 марта 2020

Мне удалось воспроизвести его с провайдером SQLite и Amount типом является decimal (отлично работает с провайдером SqlServer).

Таким образом, вы, похоже, нажимаете следующий SQLite Ограничения запроса из документации EF Core:

SQLite изначально не поддерживает следующие типы данных. EF Core может читать и записывать значения этих типов, также поддерживается запрос на равенство (где e.Property == value). Однако другие операции, такие как сравнение и упорядочение, потребуют оценки на клиенте .

  • DateTimeOffset
  • Десятичное число
  • TimeSpan
  • UInt64

В качестве обходного пути рассмотрите возможность использования совета из документов:

Тип Decimal обеспечивает высокий уровень точности. Однако если вам не нужен такой уровень точности, мы рекомендуем вместо этого использовать double. Вы можете использовать конвертер значений, чтобы продолжить использование десятичных чисел в ваших классах.

с примером

modelBuilder.Entity<MyEntity>()
    .Property(e => e.DecimalProperty)
    .HasConversion<double>();           
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...