我有以下物件:
public class Item
{
public int Id {get; set;}
public Process Process {get; set;}
}
public class Process
{
public bool Alive {get; set;}
}
我正在嘗試這樣做:
context.DB.Items
.Include(x => x.Process)
.Where(x => x.Process.Alive);
但是過濾總是讓我得到 Process.Alive 為假的專案。
按包含在作為主要專案屬性的物件中的屬性進行過濾的最佳方法是什么?
uj5u.com熱心網友回復:
使用 EF Core,您可以將過濾Include用于一次性查詢:
context.DB.Items
.Include(x => x.Process
.Where(x => x.Process.Alive));
或使用全域查詢過濾器告訴 EF 只獲取“活動”記錄:
https://docs.microsoft.com/en-us/ef/core/querying/filters
對于 EF6,預先加載集合使用Include表示該物體的完整資料狀態。過濾的包含可能會產生誤導,因為它們不一定代表任何給定時間點的資料域狀態的完整圖片。
如果您通常只想處理活動行,例如查看結果等,則可以通過投影進行管理。例如,如果我有一個要顯示專案及其行程的視圖,我將有一個 ItemViewModel,其中包含 ProcessViewModel 的集合,僅顯示我的視圖關心的資料。當我投影該視圖模型時:
var item = context.Items
.Select(x => new ItemViewModel
{
ItemId = x.ItemId,
// ....
Processes = x.Processes
.Where(x => x.Alive)
.Select(p => new ProcessViewModel
{
ProcessId = p.ProcessId,
// ...
}).ToList()
}).Single(x => x.ItemId == itemId);
這可以使用 Automapper 及其ProjectTo方法進行簡化和集中化,以便您配置 Automapper 映射以尊重“活動”活動狀態,然后您的查詢看起來像:
var item = context.Items
.ProjectTo<ItemViewModel>(config)
.Single(x => x.ItemId == itemId);
其中“config”是一個 MapperConfiguration,詳細說明了如何將 Item 映射到 ItemViewModel 和 Process 到 ProcessViewModel。Automapper 負責其余的作業,將必要的細節投射到 EF 中以生成合適的 SQL 陳述句。
如果您確實想與物體一起執行更新和參考詳細資訊,那么您可以投影一個匿名型別:
var itemsAndAliveProcesses = context.Db.Items
.Select(x => new
{
Item = x,
AliveProcesses = x.Processes.Where(p => p.Alive).ToList()
}).Single(x => x.ItemId == itemId);
在這里,您將使用 itemsAndAliveProcesses.AliveProcesses 來訪問專案的活動行程,而不是 .Item.Processes 如果您確實想訪問整個集合,則可以留給延遲加載或急切加載。
我會推薦投影而不是過濾Include,因為利用投影將導致比加載整個物體圖更有效的查詢,并且它有助于確保當您使用物體圖時,這些方法可以始終如一地期望接收到完整或完整的資料表示狀態。(而不是可能的過濾子集,因為您可以過濾Include任何東西)
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/441673.html
