先了解一下 EF 框架的 EntityState
在使用EF框架時,
我們通常都是通過調用 SaveChanges() 方法把增加/修改/刪除的數據提交到數據庫,但是上下文是如何知道實體對象是增加、修改還是刪除呢?
答案是通過EntityState的枚舉值來判斷的。也就是說在操作數據庫時,EF會根據EntityState這個枚舉檢測到實體的狀態,然后執行相應的增/刪/改操作。
該狀態對應的值為以下五種:
Detached:對象存在,但未由對象服務跟蹤。在創建實體之后、但將其添加到對象上下文之前,該實體處於此狀態;
Unchanged:自對象加載到上下文中后,或自上次調用 System.Data.Objects.ObjectContext.SaveChanges() 方法后,此對象尚未經過修改;
Added:對象已添加到對象上下文,但尚未調用 System.Data.Objects.ObjectContext.SaveChanges() 方法;
Deleted:使用 System.Data.Objects.ObjectContext.DeleteObject(System.Object) 方法從對象上下文中刪除了對象;
Modified:對象已更改,但尚未調用 System.Data.Objects.ObjectContext.SaveChanges() 方法。
Attach() :將給定實體以 System.Data.EntityState.Unchanged 狀態附加到上下文中。
從解釋可以看出Attach方法主要目的就是把一個沒有被 dbContext 跟蹤的對象附加到 dbCotext 中使其被 dbContext 跟蹤。
Attach執行成功的前提:
1. 如果上下文中已經存在與實體對象鍵值相同的對象A,則要求實體對象的內存地址必須與對象A相同,否則報錯:“已有相同鍵值的對象存在上下文中......”。
2. 如果上下文中不存在與實體對象鍵值相同的對象,則要求實體對象的內存地址必須不在上下文中,否則會報錯,系統認為在修改鍵值,這是不允許的。
例如,在刪除中使用
public int Delete(T entity) { DB.Set<T>().Attach(entity); DB.Set<T>().Remove(entity); return DB.SaveChanges(); }
Entry() :獲取實體對象的代理類
如果實體對象不在當前上下文中(指內存地址),則代理類對象的State為Detached,否則,為上下文中相應所處狀態。
例如:在更新中使用
public int Updata(T entity,params string[] propNames) { var oldEntity = DB.Entry(entity); oldEntity.State = EntityState.Unchanged; foreach (var prop in propNames) { oldEntity.Property(prop).IsModified = true; } return DB.SaveChanges(); }
