Почему мой метод расширения C# используется в запросе linq-to-entity, загружающем элементы базы данных в память вместо запуска на сервере БД? - PullRequest
3 голосов
/ 27 февраля 2020

Я создал следующий простой метод расширения:

public static IQueryable<TSource> DistinctBy<TSource, TKey>(this IQueryable<TSource> source, Expression<Func<TSource, TKey>> keySelector)
{
    return source.GroupBy(keySelector)
                 .Select(g => g.FirstOrDefault())
                 .AsQueryable();
}

Кажется, моя проблема в том, что код загружает строки базы данных в память и пытается выполнить операции в памяти вместо того, чтобы выполнять то, что Linq-To -Entities должен делать и переводить запрос в SQL.

. Выше видно, что мой метод расширения не делает ничего, что не может быть переведено в SQL, поэтому почему он этого не делает ?

Следующие две строки кода должны быть эквивалентны, но первая выполняется за <200 мс, а другая выполняется около 20 минут, прежде чем выдается исключение из нехватки памяти: </p>

// Executes in less than 200ms.
var test_1 = dbContext.SomeTable.GroupBy(row => new { row.SomeColumn, row.SomeOtherColumn })
                                .Select(g => g.FirstOrDefault())
                                .Tolist();
// The line below takes some 20 minutes to eventually throw an out of memory exception.
// Notice I'm not even calling ToList().
var test_2 = dbContext.SomeTable.DistinctBy(row => new { row.SomeColumn, row.SomeOtherColumn });

Обратите внимание, что этот метод расширения является лишь примером. Относительно легко просто не использовать его, а вместо этого использовать код, определенный внутри метода напрямую. Я говорю это, потому что я не спрашиваю, как создать метод «DistinctBy». Вместо этого я спрашиваю, как кодировать метод расширения, который использует только другие «переводимые» методы, чтобы избежать повторения кода.

Я понимаю, что могу использовать только методы расширения, предоставленные поставщиком EF, но это это, по сути, то, что я делаю. Не могу ли я сообщить, что мой метод может быть напрямую переведен на SQL, как метод GroupBy может это сделать?

...