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. Сначала я думал, что они будут такими же, но ошибся.

494   1  

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

    Ничего не найдено.