使用存根實體
假設我們在多對多關係中有 Product
s 和 Category
s:
public class Product
{
public Product()
{
Categories = new HashSet<Category>();
}
public int ProductId { get; set; }
public string ProductName { get; set; }
public virtual ICollection<Category> Categories { get; private set; }
}
public class Category
{
public Category()
{
Products = new HashSet<Product>();
}
public int CategoryId { get; set; }
public string CategoryName { get; set; }
public virtual ICollection<Product> Products { get; set; }
}
如果我們想要將 Category
新增到 Product
,我們必須載入產品並將類別新增到其 Categories
,例如:
不好的例子:
var product = db.Products.Find(1);
var category = db.Categories.Find(2);
product.Categories.Add(category);
db.SaveChanges();
(其中 db
是 DbContext
的子類)。
這會在 Product
和 Category
之間的聯結表中建立一條記錄。但是,此表僅包含兩個 Id
值。載入兩個完整實體以建立一個小記錄是浪費資源。
更有效的方法是使用在記憶體中建立的存根實體,即實體物件,僅包含最少的資料,通常只包含 Id
值。這就是它的樣子:
好例子:
// Create two stub entities
var product = new Product { ProductId = 1 };
var category = new Category { CategoryId = 2 };
// Attach the stub entities to the context
db.Entry(product).State = System.Data.Entity.EntityState.Unchanged;
db.Entry(category).State = System.Data.Entity.EntityState.Unchanged;
product.Categories.Add(category);
db.SaveChanges();
最終結果是相同的,但它避免了兩次到資料庫的往返。
防止重複
你要檢查關聯是否已存在,便宜的查詢就足夠了。例如:
var exists = db.Categories.Any(c => c.Id == 1 && c.Products.Any(p => p.Id == 14));
同樣,這不會將完整實體載入到記憶體中。它有效地查詢聯結表,只返回一個布林值。