EF Core多對多提取查詢

asp.net-core-mvc entity-framework-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 Core MVC並且有一個過濾器視圖模型,其中對配置文件名稱上的某些屬性進行過濾並且它可以正常工作。

試圖基於類別進行過濾被證明更難實現(至少解決方案對我來說並不明顯:)

用戶可以從網絡上選擇零,一個或多個類別進行過濾,因此基本上發送給我的控制器的是類別ID列表。

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對像是不同的,其他導航屬性(如Platforms)為null,因此會破壞其他部分。

如何在保留Profile對象的原始實例的同時執行連接。我首先想到他們會是一樣的,但我錯了。

一般承認的答案

目前,EF Core JOIN並不完美,我建議兩個查詢:

1)選擇ProfileId列表(基於類別列表):

var profileIds = await _context.ProfileCategory
    .Where(x => categoryIds.Contains(x.CategoryId)) // filtering goes here
    .Select(x => x.ProfileId)
    .Distinct()
    .ToListAsync();

2)根據已知ID選擇所需數據:

var result = await _context.Profiles
    .Include(p => p.Categories).Include(p => p.Platforms)
    .Where(x => profileIds.Contains(x.ProfileId))
    .ToListAsync();

是的,這是兩個查詢而不是一個,但是兩個簡單的查詢,可以使用索引輕鬆優化。



Related

許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow