ADO.Net Entity Framework传递,以及EntityKey、EntityState

来源:互联网 发布:牛牛财务机器人源码 编辑:程序博客网 时间:2024/05/22 04:50

最近项目用到EF,开发遇到了很多问题,这篇文章深入探讨。本文虽是繁体,但是基本勉强看懂,相信代码和图大伙都懂的

原文如下:

在這邊分享跟介紹,使用ADO.Net Entity Framework時,一定會碰到的問題, 
如何在ObjectContext間傳遞EntityObject並進行資料庫操作, 
簡單說就是當你從一個ObjectContext取得一筆資料(EntityObject)後, 
跨越另一個類別(Class)要再利用ObjectContext去操作剛剛取得的EntityObject, 
例如要新增、修改、刪除、查詢等,要如何實做, 
適用的情境像是在WebService、多層式架構、利用ObjectDataSource存取資料時等等, 
都會遇到此問題。
 

在實作範例之前,有幾個重要觀念與名詞必須先介紹一下 
不知道大家在使用ADO.Net Entity Framework取得一筆資料的時候, 
有沒有發現除了欄位名稱轉換成屬性,還自動產生了多了兩個很重要的屬性【EntityKey】、【EntityState】, 
因為EntityObject實作了IEntityWithChangeTracker介面,讓這些物件能夠報告變更, 
2009-10-12_170318

簡單說明一下這些屬性

名稱

說明

EntityKey

EntitySet=User;User_id=3 
(此為範例)

提供實體 (Entity) 類型執行個體 (Instance) 之物件的持久參考。

EntityKey. 
EntityContainerName

TestEntities

(此為範例)

取得實體容器的名稱。

EntityState

Detached

雖然此物件存在,但是物件服務沒有追蹤此物件。在已經建立實體之後而在實體加入至物件內容之前,實體就會處於這種狀態中。在已經透過呼叫 Detach 方法從內容中移除實體,或者使用 NoTrackingMergeOption 載入實體時,實體也會處於這種狀態中。

 

Unchanged

自從此物件載入內容中,或者自從上一次呼叫 SaveChanges 方法以來,此物件就沒有修改過。

 

Added

此物件已加入至物件內容,而且尚未呼叫 SaveChanges 方法。物件是透過呼叫 AddObject 方法加入至物件內容。

 

Deleted

已經使用 DeleteObject 方法,從物件內容中刪除此物件。

 

Modified

此物件已變更,但是尚未呼叫 SaveChanges 方法。

以上資料部分擷轉自MSDN 

EntityKey

簡單說【EntityKey】內會儲存幾個很重要的值

  • EntitySet   Table名稱
  • EntityKeyValues   此筆資料的主鍵值
  • EntityContainerName  實體容器的名稱

因為有Table名稱又有此筆資料的主鍵值,因此一個【EntityKey】就可以定義一筆資料, 
ADO.Net EntityFramework去資料庫進行刪除、更新等操作時,會依靠【EntityKey】來辦別是哪一筆資料
 

EntityState

另一個重要的屬性是【EntityState】,會用來記錄此筆資料目前的狀態 
下面利用圖示,希望讓大家了解【EntityState】內容的變化, 
圖式中方框內的Detached、Add、Unchanged等,代表的是該EntityObject的EntityState內容

 2009-10-13_004035  
2009-10-13_004045 
當下達SaveChanges方法時,ObjectContext會依照EntityStatus的值,來判斷此筆資料是要被新增、刪除、修改等
 

物件間傳遞 Attech、Detech

上面介紹了兩個重要的屬性,接下來再繼續介紹ObjectContext兩個重要的Method【Attech】、【Detech】, 
用在兩個ObjectContext間的Entity Object傳遞, 
當Entity Object要由ObjectContext A 傳到ObjectContext B時, 
必須先將其以Detach函式把與ObjectContext A的連線切斷, 
在以Attach函式與ObjectContext B建立關係, 
換句話說,如果在ObjectContext A取得資料,沒有透過 【Attech】、【Detech】方法, 
直接到ObjectContext B中去使用的話,會發生問題

在這邊我採用漸進式的方式,來讓大家理解為什麼語法要這樣寫。

範例一

1User u;       
2using (TestEntities te = new TestEntities())
3{
4    ////取得 某使用者 資料
5    u = te.User.Where(a => a.User_name == "David").First();                      
6}
7 
8u.Group.Load();  ////必須在 ObjectContext 存在下,才可以進行資料庫存取

 這段語法執行的話,會產生以下錯誤
 

ObjectContext 執行個體已被處置,無法再使用於需要連接的作業。

描述: 在執行目前 Web 要求的過程中發生未處理的例外情形。請檢閱堆疊追蹤以取得錯誤的詳細資訊,以及在程式碼中產生的位置。 
例外詳細資訊: System.ObjectDisposedException: ObjectContext 執行個體已被處置,無法再使用於需要連接的作業。


原因是 在執行 u.Group.Load() 時,ObjectContext已經不存在了,所以當然沒有辦法對資料庫進行存取, 
此範例是讓大家知道進行資料庫存取時必須在 ObjectContext存在下執行, 
當然如果只是要操作取得後的資料,沒有此限制。

那如果我真的需要在ObjectContext結束後,再繼續對資料庫進行操作的話怎辦? 
例如當EntityObject在WebService間傳遞的時候就會遇到這問題, 
情境如下,先取得資料,然後透過WebService傳遞到另一端,在建立一個新的ObjectContext, 
將此資料利用【Attech】方法附加到ObjectContext,就可以對此資料在資料庫進行操作

範例二

01////範例 利用Attach、Detach在ObjectContext中傳遞
02User u;      
03using (TestEntities te = new TestEntities())
04{
05    ////取得 某使用者 資料
06    u = te.User.Where(a => a.User_name == "David").First();
07    
08    ////從物件內容中斷物件的連結
09    te.Detach(u);           
10}
11 
12////為了示範方便,請將此想像模擬成另一個執行環境
13using (TestEntities te2 = new TestEntities())
14{
15    ////附加相關的物件
16    te2.Attach(u);
17    
18    u.Group.Load();
19    var groups = u.Group.Select(a => a).ToList();
20}

這段語法就可以順利執行, 
利用圖示來觀察一下其中EntityState變化,

2009-10-13_132148

  
其中重點在利用【Attech】、【Detech】方法,讓 EntityObject可以在ObjectContext中傳遞, 
也順便介紹了一下【EntityKey】、【EntityState】這兩個重要的屬性, 
如果要學好ADO.Net Entity Framework並活用,這篇介紹的範圍一定要理解。
 

转:http://www.dotblogs.com.tw/asdtey/archive/2009/10/13/11037.aspx

原创粉丝点击