Проблема оценки EF Core 3.1 на стороне клиента с логическим вызовом Asyn c - PullRequest
0 голосов
/ 26 марта 2020

Я мигрирую форму. Net 2,1 до 3,1, и это включает в себя обновление EF Core.

Теперь у меня был следующий запрос LINQ, который работал без проблем:

var application = await _db.CustomerApplications
                .AsNoTracking()
                .Include(i => i.CustomerApplicationFields)
                .Include(i => i.Customer)
                .Where(x => x.Customer.PublicId == formId && x.IsPublished) // Also tried with &
                .OrderByDescending(o => o.Version)
                .FirstOrDefaultAsync();

С EF Core 3.1 я получаю ошибку:

The LINQ expression 'DbSet<CustomerApplication>
    .Where(c => !(c.Deleted))
    .Join(
        outer: DbSet<Customer>
            .Where(c0 => !(c0.Deleted)), 
        inner: c => EF.Property<Nullable<long>>(c, "CustomerId"), 
        outerKeySelector: c0 => EF.Property<Nullable<long>>(c0, "Id"), 
        innerKeySelector: (o, i) => new TransparentIdentifier<CustomerApplication, Customer>(
            Outer = o, 
            Inner = i
        ))
    .Where(c => c.Inner.PublicId == __formId_0 && c.Outer.IsPublished)' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync(). See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.

Когда я конвертирую этот запрос следующим образом, он работает (перемещение bool оценка за пределы):

var application = await _db.CustomerApplications
                .AsNoTracking()
                .Include(i => i.CustomerApplicationFields)
                .Include(i => i.Customer)
                .Where(x => x.Customer.PublicId == formId)
                .OrderByDescending(o => o.Version)
                .ToListAsync();

var result = application.FirstOrDefault(x => x.IsPublished);

Может кто-нибудь объяснить для меня, почему это проблема? Я также попробовал x.IsPublished == true, но безрезультатно. Это кажется довольно случайным.

Я также пытался с AsTracking().

Ответы [ 2 ]

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

До EF Core 3.0 запросы, которые не могли быть переведены в SQL запросы, оценивались на стороне клиента. Это поведение было отклонено, и теперь вместо оценки непереводимых запросов на стороне клиента выдается исключение.

Также я думаю, что новое поведение не должно приводить к большим проблемам производительности, когда вы пишете var result = application.FirstOrDefault (x => x.IsPublished); отдельно, потому что то же самое происходило и раньше. Это было просто не видно раньше. (Пожалуйста, исправьте меня, если это предположение неверно!)

Также вы можете попробовать выполнить следующее, если хотите получить один запрос (не проверял это):

var application = await _db.CustomerApplications
            .AsNoTracking()
            .Include(i => i.CustomerApplicationFields)
            .Include(i => i.Customer)
            .Where(x => x.Customer.PublicId == formId)
            .OrderByDescending(o => o.Version)
            .FirstOrDefaultAsync(x => x.IsPublished);

Вы можете прочитать об этом подробно здесь: https://docs.microsoft.com/en-us/ef/core/what-is-new/ef-core-3.0/breaking-changes#linq -сопросы-больше-не-оцениваются-на-клиенте

0 голосов
/ 26 марта 2020

Вы должны использовать && вместо &, или вы можете добавить другое предложение where.

...