我試圖使用 LINQ 選擇資料,我有一個名為“產品”的串列,我只想要產品串列中存在的這些專案
var Owner = db.Owners
.Where(m => m.ID == id)
.Include(m => m.Products.Where(item1 => products.Any(item2 => item2.ProductID == item1.ProductID)).ToList())
.FirstOrDefault();
但我收到此錯誤:
System.ArgumentException: '包含路徑運算式必須參考型別上定義的導航屬性。對參考導航屬性使用虛線路徑,對集合導航屬性使用 Select 運算子。引數名稱:路徑'
uj5u.com熱心網友回復:
Include 旨在獲取表的完整行,包括主鍵和外鍵。
通常,獲取表的完整行效率不高。例如,假設您有一個包含 Schools 和 Students 的資料庫。學校和學生之間是一對多的關系:每個學校有零個或多個學生,每個學生就讀于一所學校,即外鍵所指的學校。
如果您獲取 School [10] 及其 2000 個學生,那么每個學生將有一個值為 10 的外鍵 SchoolId。如果您使用 Include 并獲取完整的 Student 行,您將傳輸該值 10 次超過 2000 次。多么浪費處理能力。
DbContext 有一個 ChangeTracker 物件。每當您在不使用 Select 的情況下獲取資料時,如果您獲取完整的行,那么獲取的行將與 ChangeTracker 一起存盤在 ChangeTracker 中。您將獲得對克隆(或原始版本,無關緊要)的參考。當您更改所獲取資料的屬性時,您會更改 Clone 中的值。當您呼叫 時SaveChanges,ChangeTracker 中所有原件的所有屬性值都與 Clones 中的值進行比較。更改的專案在資料庫中更新。
因此,如果您獲取 School [10] 及其學生,您不僅獲取的資料遠多于您將使用的資料,而且您還將所有這些學生與克隆學生一起存盤在 ChangeTracker 中。如果您為完全不同的東西(例如學校的電話號碼)呼叫 SaveChanges,那么所有學生都將與他們的克隆財產逐個進行價值比較。
每當您使用物體框架獲取資料時,請始終使用
Select和 僅選擇您實際計劃使用的屬性。僅獲取完整的行,如果您計劃更新獲取的資料,則僅使用 Include。
使用 Select 也可以解決您的問題:
int ownerId = ...
IEnumerable<Product> products = ...
var Owner = db.Owners.Where(owner => owner.ID == ownerId)
.Select(owner => new
{
// Select only the Owner properties that you actually plan to use
Id = owner.Id,
Name = owner.Name,
// get the Products of this Owner that are in variable products
Products = owner.Products
.Where(product => products.Any(p => p.ProductId == product.ProductId)
.Select(product => new
{
// Select only the Product properties that you plan to use
Id = product.Id,
Price = product.Price,
...
// No need to fetch the foreign key, you already fetched the value
// OwnerId = product.OwnerId,
})
.ToList(),
...
})
.FirstOrDefault();
我使用了自動型別 ( new {...})。如果您真的想創建所有者和屬性,請使用:
var Owner = db.Owners.Where(...)
.Select(owner => new Owner
{
Id = owner.Id,
...
Products = owner.Products.Where(...).Select(product => new Product
{
Id = product.Id,
...
})
.ToList(),
})
.FirstOrDefault();
uj5u.com熱心網友回復:
這樣就行不通了,將您的查詢拆分為 2 個查詢。
var owner = db.Owners
.Include(m => m.Products)
.FirstOrDefault(m => m.ID == id);
if(owner != null)
{
var ownerProducts = owner.Products
.Where(item1 => products.Any(item2 => item2.ProductID == item1.ProductID)).ToList();
}
也許它是這樣作業的。
uj5u.com熱心網友回復:
請嘗試以下操作:
var productIds = products.Select(x => x.ProductID);
var Owner = db.Owners
.Where(m => m.ID == id)
.Include(m => m.Products.Where(product => productIds.Contains(product.ProductID))
.FirstOrDefault();
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/366471.html
標籤:C# asp.net-mvc 林克
下一篇:從另一個排序串列創建過濾串列
