一個偶然的機會,讓我注意了EF 的Attach方法,於是深入了解讓我大吃一驚
在我所參與的項目中所有的更新操作與刪除操作都是把原對象加載出來后,再做處理,然后再保存到數據庫,這樣的操作不缺點在於每一次的操作都要對數據庫進行兩次操作,性能上有很大的問題,
於是Attach方法出場
在介紹Attach方法前先介紹與它相關的知識點
Attach方法:將給定實體以 System.Data.EntityState.Unchanged 狀態附加到上下文中
從解釋可以看出Attach方法主要目的就是把一個沒有被dbContext跟蹤的對象附加到dbCotext中使其被dbContext跟蹤
1 對象上下文:DBContext 建一個新的上下文實例以創建將連接到的數據庫的名稱,默認狀態是沒有對任何對象跟蹤的
2 實體狀態: 在EF中對實體狀會有4種狀態:
2.1 Added:對象為新對象,並且已添加到對象上下文,但尚未調用
2.2 Deleted:對象已從對象上下文中刪除
2.3 Detached:對象存在,但沒有被跟蹤。 在創建實體之后、但將其添加到對象上下文之前,該實體處於此狀態
2.4 Modified:對象上的一個標量屬性已更改,但尚未調用
2.5 Unchanged: 此對象尚未經過修改自對象附加到上下文中后,或自上次調用 (調用了SaveChange方法后所有的對象都改為Unchanged狀態)
了解了相關的知識后就開始利用Attach方法改代碼了
以上為原來的方法
using(Entities ctx = new Entities()) { Product product = ctx.Product.First(); //更新屬性操作 ctx.SaveChange();
}
這種寫法會產生兩次對數據庫的操作,改成Attach方法后如下
public void Update(Product product) { using(Entities ctx = new Entities) { //product 已前台更新后 ctx.Attach(product); ctx.ObjectStateManager.ChangeObjectState(entity,EntityState.Modified) ctx.SaveChange(); } } //EF 的處理方式如下 // 1 把對象附加到上下文中,並把狀態改為Modified狀態 // 2 調用Savechange方法時生成一段Update的SQL語句且Where 條件
// 為對象的主鍵Id,因為EF更新和刪除都是根據主鍵ID來處理的
刪除操作也是一樣的,這里就只貼用Attach的處理方式了
public void Delete(Product product) { using(Entities ctx = new Entities) { Product entity = new Product{Id =1} ctx.Attach(entity); ctx.ObjectStateManager.ChangeObjectState(entity,EntityState.Deleted) ctx.SaveChange(); } } //前面說了EF是根據主鍵ID來處理的所以只要手動生成一個對象並把對應的ID賦值然后Attach到上下文中即可做到刪除
相比項目中原來的方法,用Attach后對數據庫的操作相應減少一次,性能上會有較大提升!