EF Core запрос выборки "многие ко многим"
У меня смоделировано следующее отношение "многие ко многим"
public class Profile
{
ICollection<Category> Categories { get; set;}
// One-To-Many
ICollection<Platform> Platforms { get; set; }
}
public class Category
{
ICollection<Profile> Profiles { get; set; }
}
public class ProfileCategory
{
public int ProfileId { get; set; }
public Profile Profile { get; set; }
public int CategoryId { get; set; }
public Category Category { get; set;}
}
Я использую ASP.NET ядро MVC и есть модель представления фильтра, где фильтр по некоторым атрибутам на имя профиля и работает.
Попытка фильтровать на основе категории оказалась намного сложнее реализовать (по крайней мере, решение для меня не очевидно :)
Из интернета пользователь может выбрать ноль, одну или несколько категорий для фильтрации, поэтому в основном то, что отправляется на мой контроллер, - это список категорий идентификационная карточка.
IQueryable<Profile> query = _context.Profiles.Include(p => p.Categories).Include(p => p.Platforms);
if(string.IsNullOrEmpty(search.Name))
{
query = query.Where(p => p.Name.IndexOf(search.Name StringComparison.OrdinalIgnoreCase) > 0);
}
if(search.Categories?.Any() != null)
{
query = query.SelectMany(p => p.ProfileCategories)
.Join(search.Categories, pc => pc.CategoryId, cId => cId, (pc,_) => pc.Profile);
}
С этой точки объект профиля отличается, и другие навигационные свойства, такие как платформы, равны нулю, следовательно, нарушая другие части.
Как я могу выполнить соединение, сохраняя исходный экземпляр объекта Profile. Сначала я думал, что они будут такими же, но ошибся.
1 ответ:
В настоящее время соединения ядра EF не идеальны, и я рекомендую сделать два запроса:
1) Выберите список
ProfileId(на основе списка категорий):var profileIds = await _context.ProfileCategory .Where(x => categoryIds.Contains(x.CategoryId)) // filtering goes here .Select(x => x.ProfileId) .Distinct() .ToListAsync();2) выберите необходимые данные на основе известных идентификаторов:
var result = await _context.Profiles .Include(p => p.Categories).Include(p => p.Platforms) .Where(x => profileIds.Contains(x.ProfileId)) .ToListAsync();Да, это два запроса вместо одного, но два простых запроса, легко оптимизируемых с помощью индексов.
Comments