[英]Filtering on Include reverted if I perform Select afterwards in EF Core
我正在嘗試在 EF Core 中使用過濾的包含,但遇到了一個我似乎無法確定具體原因的問題。
我的查詢看起來像這樣:
context.Users.Include(u=>u.UserRoles.Where(r => r.Role.Category == 3))
.ThenInclude(r=>r.Role).Where(u => u.userId == currentUserId)
.Select(u=> new UserDTO()
{
UserDisplayName= u.Name,
ListOfRoles = String.Join(",", u.UserRoles.Select(u => u.Role.DisplayName))
}).FirstOrDefaultAsync();
如果我從查詢中省略 Select 部分並檢查對象,它只填充了適當的 UserRoles,屬於類別 3 的用戶角色,但在檢查此 Select 的結果時,它還包含屬於不同的角色類別,連接到 ListOfRoles。
如果有人知道可能導致這種情況的原因,我將不勝感激。
謝謝
Include
僅適用於您返回實體的情況。 當您將投影與Select
一起使用時,您需要過濾Select
表達式中的數據:
context.Users
.Where(u => u.userId == currentUserId)
.Select(u=> new UserDTO()
{
UserDisplayName= u.Name,
ListOfRoles = String.Join(",", u.UserRoles
.Where(ur => ur.Role.Catecory == 3)
.Select(ur => ur.Role.DisplayName))
}).SingleOrDefaultAsync();
我相信 String.Join 需要在 EF Core 中進行客戶端評估。 這可能會導致加載意外數據。 避免這種情況的建議是在 DTO 內執行串聯,以便 Linq 查詢加載原始數據並可以有效地將其轉換為 SQL:
context.Users
.Where(u => u.userId == currentUserId)
.Select(u=> new UserDTO()
{
UserDisplayName= u.Name,
Roles = u.UserRoles
.Where(ur => ur.Role.Catecory == 3)
.Select(ur => ur.Role.DisplayName))
.ToList();
}).SingleOrDefaultAsync();
在 DTO 中,您將擁有:
[Serializable]
public class UserDTO
{
public string UserDisplayName { get; set; }
public IList<string> Roles { get; set; } = new List<string>();
public string ListOfRoles
{
get { return string.Join(",", Roles); }
}
}
這確保查詢可以高效運行並完全轉換為 SQL,然后將格式移動到 DTO。
僅當您直接選擇實體時, Include
才會起作用。 進行投影(例如Select
)后, Include
被忽略。 您可以嘗試在串聯部分應用類別過濾:
context.Users
.Where(u => u.userId == currentUserId)
.Select(u=> new UserDTO()
{
UserDisplayName= u.Name,
ListOfRoles = String.Join(",", u.UserRoles.Where(r => r.Role.Category == 3).Select(u => u.Role.DisplayName))
})
.FirstOrDefaultAsync();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.