EF Core 3.1 не переводит запрос должным образом - PullRequest
1 голос
/ 07 августа 2020

У меня есть запрос, который я написал, в котором говорится, что он неправильно переводится. Запрос выглядит следующим образом:

var query = from a in context.PlaceSyncs
                            join b in (
                                from aa in context.PlaceIdentifiers
                                join bb in context.PlaceSources on aa.PlaceSourceId equals bb.PlaceSourceId
                                select new { Id = aa.PlaceIdentifierId, PlaceKey = aa.PlaceIdentifierKey, PlaceSource = bb.PlaceSourceName }
                            ) on new { a.PlaceKey, PlaceSource = a.PlaceSource.ToLower() } equals new { b.PlaceKey, PlaceSource = b.PlaceSource.ToLower() } into temp
                            from c in temp.DefaultIfEmpty()
                            where c == null
                            select new PlaceSync()
                            {
                                PlaceActive = a.PlaceActive,
                                PlaceAddress = a.PlaceAddress,
                                PlaceInformation = a.PlaceInformation,
                                PlaceKey = a.PlaceKey,
                                PlaceName = ((a.PlaceName.Contains("#") == false) ? a.PlaceName : a.PlaceName.Substring(0, a.PlaceName.IndexOf("#"))).TrimEnd().TrimStart(),
                                PlaceSource = a.PlaceSource,
                                PlaceSyncId = a.PlaceSyncId
                            };

var test = query.Count();

Когда я запускаю это в linqpad, все проверяется. Когда я запускаю это в своем приложении, я получаю следующую ошибку:

The LINQ expression 'DbSet<PlaceSync>
    .LeftJoin(
        outer: DbSet<PlaceIdentifier>
            .Join(
                outer: DbSet<PlaceSource>, 
                inner: p0 => p0.PlaceSourceId, 
                outerKeySelector: p1 => p1.PlaceSourceId, 
                innerKeySelector: (p0, p1) => new TransparentIdentifier<PlaceIdentifier, PlaceSource>(
                    Outer = p0, 
                    Inner = p1
                )), 
        inner: p => new { 
            PlaceKey = p.PlaceKey, 
            PlaceSource = p.PlaceSource.ToLower()
         }, 
        outerKeySelector: ti => new { 
            PlaceKey = ti.Outer.PlaceIdentifierKey, 
            PlaceSource = ti.Inner.PlaceSourceName.ToLower()
         }, 
        innerKeySelector: (p, ti) => new TransparentIdentifier<PlaceSync, TransparentIdentifier<PlaceIdentifier, PlaceSource>>(
            Outer = p, 
            Inner = ti
        ))
    .Where(ti0 => new { 
        Id = ti0.Inner.Outer.PlaceIdentifierId, 
        PlaceKey = ti0.Inner.Outer.PlaceIdentifierKey, 
        PlaceSource = ti0.Inner.Inner.PlaceSourceName
     } == null)' 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.

Я использую .netcore с Micrisoft.EntityFrameworkCore версии 3.1.5. Есть ли что-то, чего не хватает в этой версии ef, что могло бы помешать правильному переводу запроса?

Если вы можете предоставить пример того же запроса, который работает в структуре, это было бы здорово.

Ответы [ 2 ]

0 голосов
/ 17 августа 2020

В итоге я просто выбрал .FromSqlRaw ...

0 голосов
/ 07 августа 2020

Выражение, которое транслятор запросов EG Core 3.x не может преобразовать, является условием антисоединения. в SQL можно использовать какой-либо столбец с правой стороны, который обычно не допускает значения NULL (обычно PK) для IS NULL проверки.

То же самое можно использовать в качестве обходного пути в запросе LINQ, но в отличие от SQL, где NULL поддерживаются естественным образом для любого выражения (даже для столбцов, не допускающих значения NULL), выражение C# потребует явного приведения к соответствующему типу, допускающему значение NULL (и игнорируя соответствующее предупреждение).

Например, если тип aa.PlaceIdentifierId - int, тогда критерии будут

where (int?)c.Id == null
...