EntityFramework是一個很不錯的ORM框架,一直都在使用。今天想跟大家分享以下EntityFramework數據更新方面的幾個技巧:
1:如何new一個新實體去更新記錄,而不是從數據庫中查詢一條記錄來更新。
2:如何在更新實體的同時,對導航屬性的實體進行一系列的操作。
3:如何用最簡單的代碼實現實體的部分更新。
1 new一個新實體去更新記錄
EntityFramework有一個特點,你無須查詢出一個記錄,而是new一個新實體,然后對其進行刪除或更新操作,只須提供實體的ID即可,如果ID不存在將會拋出異常。這樣有助於提高性能,畢竟減少了一次數據庫訪問。要實現用一個新實體去更新記錄,你得讓EF的Change Tracker跟蹤該實體,讓它認為該實體就是從數據庫中取出來的,只要讓改該實體處於修改狀態就行了,代碼如下:
1 context.Entry<TEntity>(entity).State = EntityState.Modified; 2 context.SaveChanges();
2 更新實體時操作導航屬性
用一個例子來說明在更新實體同時如何對導航屬性進行操作吧。假設有兩個類型
public class Customer
{
public string ID { get; set; }
public string Name { get; set; }
public IList<CustomerAddress> CustomerAddresses { get; set; }
}
public class CustomerAddress
{
public string City { get; set; }
public string ZipCode { get; set; }
public string CustomerId { get; set; }
public Customer Customer { get; set; }
}
那如何在更新Customer的同時Add一個CustomerAddress並且Delete一個CustomerAddress呢?關鍵一點就是要讓EntityFramework的Change Tracker知道有CustomerAddress的存在,只需對Customer增加一個Add操作就行了,代碼如下:

1 public void Modify(Customer entity,CustomerAddress address) 2 { 3 context.Customer.Add(entity); 4 5 //修改Customer 6 context.Entry(entity).State = EntityState.Modified; 7 8 //新增CustomerAddress 9 if (......) 10 { 11 entity.CustomerAdresses.Add(address); 12 } 13 14 //刪除CustomerAddress 15 if (.......) 16 { 17 context.Entry(address).State = EntityState.Deleted; 18 } 19 context.SaveChanges(); 20 }
如果注釋掉context.Customer.Add(entity)這行代碼,將會拋出異常,這個是值得注意的地方。
3 實現實體的部分更新
以前好像在園子里有朋友講過Entityframework實體部分更新的問題,就是用反射去遍歷實體的屬性,把需要修改的實體屬性狀態設置為Modified,這樣也可以達到目的,但是這樣寫的代碼有點多,而且對Entityframework的特性沒有充分的利用,其實很簡單兩行代碼就搞定:
1 /// <summary> 2 /// 實體部分更新 3 /// </summary> 4 /// <param name="originalEmployee">需修改的實體</param> 5 /// <param name="newEmployee">新的實體</param> 6 public void Modify(Employee originalEmployee, Employee newEmployee) 7 { 8 context.Entry(originalEmployee).CurrentValues.SetValues(newEmployee); 9 context.SaveChanges(); 10 }
關鍵是第一行代碼,意思就是把原來實體的值設置為新實體的值,大家可以查看CurrentValues.SetValues()這個方法的源代碼,就能明白其中的道理。在執行查詢的時候大家 可以打開SQLServer Profiler查看是否真的是部分更新了。如果該實體是一個新實體,該如何更新呢?還是老辦法讓EntityFramework知道它的存在,把它的狀態設置為UnChanged即可,綜合兩種情況,合並的代碼如下:
public void Modify(Employee originalEmployee, Employee newEmployee) { if (context.Entry(originalEmployee).State != EntityState.Unchanged) context.Entry(originalEmployee).State = EntityState.Unchanged; context.Entry(originalEmployee).CurrentValues.SetValues(newEmployee); context.SaveChanges(); }
其實今天講的都是new一新實體去更新數據庫,關鍵是讓EF 的Change Tracker跟蹤新實體這樣才能達到修改的目的,而這一切都是設置EntityState才行。
順便提一下EntityState,它是一枚舉類型,有Detached,Unchanged,Added,Deleted,Modified五個值分別代表:實體沒被跟蹤,啥操作對它無效;實體存在於數據庫但還沒被修改;實體被跟蹤但不存在於數據庫,實體存在於數據庫並且標記為刪除,SaveChanges操作將刪除該實體;實體存在於數據庫並且標記為修改,SaveChanges操作將修改該實體。