Фильтрация включения с помощью методов расширения EF CoreC#

Место общения программистов C#
Ответить
Anonymous
 Фильтрация включения с помощью методов расширения EF Core

Сообщение Anonymous »

Я пытаюсь ограничить количество элементов свойства навигации.
Согласно документации EF Core, я мог бы добавить Where, OrderBy, OrderByDescending, thenBy, thenByDescending, Пропустить или выполнить операцию с навигационной коллекцией.
У меня есть этот код:

Код: Выделить всё

public async Task GetCategories(int recipeCount)
{
var categories = _context.Categories
.Include(cat => cat.Recipes.Take(recipeCount));

var dtos = await categories
.Select(cat => _mapper.Map(cat))
.ToListAsync();

return dtos;
}
Это отлично работает. Однако я пытаюсь сделать аргумент рецептаCount необязательным, сделав его обнуляемым. Прежде чем я смогу его использовать, требуется проверка рецепта.HasValue, поэтому я создал метод расширения именно для этого:

Код: Выделить всё

public static IEnumerable TakeMaybe(this IEnumerable enumerable, int? count)
{
if (count.HasValue)
return enumerable.Take(count.Value);

return enumerable;
}

// And changing GetCategories as follows:
public async Task GetCategories(int? recipeCount)
{
var categories = _context.Categories
.Include(cat => cat.Recipes.TakeMaybe(recipeCount));

var dtos = await categories
.Select(cat => _mapper.Map(cat))
.ToListAsync();

return dtos;
}
Однако при этом я получаю следующее исключение:

System.InvalidOperationException:
Выражение 'cat.Recetas.TakeMaybe(__queryParameters_CantRecetas_0)' недействителен внутри операции 'Include', поскольку он не представляет доступ к свойству: 't => t.MyProperty'.

Для целевой навигации, объявленной на производные типы, используйте приведение ('t => ((Derived)t).MyProperty') или оператор 'as' ('t => (t as Derived).MyProperty').

Collection доступ к навигации можно отфильтровать, составив операции Where, OrderBy(Descending), thenBy(Descending), Skip или Take.
Для получения дополнительной информации о включении связанных данных см. https://go.microsoft.com/fwlink/? LinkID=746393.

Я не уверен, почему это происходит, поскольку я либо вызываю оператор Take внутри метода, либо просто возвращаю перечисляемое как есть.
В документации прямо указано, что единственными разрешенными методами являются Where, OrderBy, OrderByDescending, thenBy, thenByDescending, Skip и Take, но я не совсем понимаю, почему я не могу сделать то, что пытаюсь сделать. Я думаю, что это может быть как-то связано с магией перевода запросов, которую делает EF Core, но я не совсем ее понимаю, поэтому не уверен.
Я мог бы просто построить запрос условно, по частям:

Код: Выделить всё

public async Task GetCategories(int? recipeCount)
{
var categories = _context.Categories;

if (recipeCount.HasValue)
categories = categories.Include(cat => cat.Recipes.Take(recipeCount.Value));
else
categories = categories.Include(cat => cat.Recipes);

var dtos = await categories
.Select(cat => _mapper.Map(cat))
.ToListAsync();

return dtos;
}
Или даже сделайте что-нибудь хакерское, например, choiceCount.Value.GetValueOrDefault(int.MaxValue), но было бы очень удобно, если бы я мог повторно использовать методы расширения, которые я написал для обычных запросы:

Код: Выделить всё

public static IEnumerable Paginate(this IEnumerable enumerable, int? offset, int? length)
{
if (offset.HasValue)
enumerable = enumerable.Skip(offset.Value);

if (length.HasValue)
enumerable = enumerable.Take(length.Value);

return enumerable;
}

public static IEnumerable Order(this IEnumerable enumerable, Func keySelector, Ordering order)
{
return order switch
{
Ordering.Ascending => enumerable.OrderBy(keySelector),
Ordering.Descending => enumerable.OrderByDescending(keySelector),
_ => enumerable
};
}
Итак, мой вопрос: почему именно я не могу использовать свои собственные методы расширения внутри Include, даже если они либо вызывают разрешенные операции, либо ничего не делают?
А как еще можно реализовать подобное?
Спасибо!

Подробнее здесь: https://stackoverflow.com/questions/789 ... ds-ef-core
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»