使用 LINQ To SQL 和Entity Framework實現靈活的資料訪問

來源:互聯網
上載者:User
迄今為止,Microsoft 已面向開發人員發布了兩種旨在減少關係資料領域和物件導向的編程之間的阻抗失諧的產品:LINQ to SQL 和 ADO.NET Entity Framework。藉助其中任何一種產品,您不必編寫大部分探測代碼,即可實現對象持久性。但是,將這些對象關係映射 (ORM) 技術應用到面向服務的應用程式體繫結構為應用程式開發人員帶來了全新的挑戰。例如,如何建立將對象持久性與應用程式其他部分分離的資料訪問層 (DAL),以便在需要時使用一個 ORM 提供者換出另一個提供者。如何在用戶端沒有安裝 LINQ to SQL 或Entity Framework的情況下跟蹤對實體的更改?如何通過僅調用服務一次即可在單個事務中插入、更新和刪除多個實體?在本文中,我將進行簡要介紹並提供一些有關如何解決上述問題的建議。首先,我將基於 Northwind 樣本資料庫建立一個用於處理訂單的 DAL。DAL 的兩種實現(一種使用 LINQ to SQL,一種使用Entity Framework)依賴於一個介面(請參見圖 1)。LINQ to SQL 和Entity Framework都具有基於資料庫結構描述產生實體的工具,但是 DAL 並不使用這些實體,而是僅公開涉及到自身持久性時通常忽略的資料轉送對象 (DTO)。
 
圖 1 適用於訂單處理應用程式的服務導向架構(單擊映像可查看大圖)
LINQ to SQL 和Entity Framework使用不同的方法持久化中斷連線的實體,具體取決於要建立新實體還是更新現有的實體。因此,為了調用合適的 API,您必須事先瞭解實體的狀態。例如,如果您具有 UpdateOrder 方法接受帶有訂單明細的訂單,可以為 UpdateOrder 方法添加三個參數,以接受建立、更新和刪除的訂單明細。但這很容易因探測訂單明細而使方法簽名變得混亂。
此外,您可以帶外傳遞更改狀態資訊(例如在 SOAP 或 HTTP 標題中傳遞),但這樣做會使變更追蹤與通訊協定相結合。下面我將介紹另一種方法 — 將更改狀態作為每個實體的資料約定的一部分,我建議使用這種方法:
[DataContract]
public enum TrackingInfo
{
  [EnumMember]
  Unchanged,
  [EnumMember]
  Created,
  [EnumMember]
  Updated,
  [EnumMember]
  Deleted
}
除了其他屬性之外,每個 DTO 都有一個使用 TrackingInfo 枚舉的 TrackingState 屬性。雙方只需同意此資料約定即可。
雖然我為每個 DTO 添加了 TrackingState 屬性,但我還必須依賴沒有安裝 LINQ to SQL 或Entity Framework的用戶端來跟蹤建立、更新或刪除的對象,以及將 TrackingState 屬性設定為相應的值(請參見圖 1)。我建立了一個通用變更追蹤集合來執行此任務。此集合有兩種類型:一種擴充 ObservableCollection<T> 以用於 Windows Presentation Foundation (WPF) 應用程式;一種擴充 BindingList<T> 以用於 Windows 表單應用程式。每種集合都可在從集合中刪除項目之前緩衝刪除的項目,並且每種集合都具有 GetChanges 方法,該方法只返回插入、更新或刪除的項目。

建立資料訪問層
DAL 有助於將應用程式的其他部分與對象持久性的詳細資料隔離開。為此,通過 DAL 公開的對象必須排除任何特定資料訪問技術的其餘部分。LINQ to SQL 和Entity Framework允許您使用命令列工具和 Visual Studio 設計器建立實體,但是這些代碼產生的實體中的一些項目與它們的源相悖。
例如,為了支援關聯對象的消極式載入,LINQ to SQL 使用 EntityRef<T> 和 EntitySet<T> 集合類型表示資料關係,而Entity Framework使用 EntityReference<T> 和 EntityCollection<T> 表示導覽屬性。此外,這些實體添加了旨在支援用戶端伺服器方案(例如使用局部方法的驗證和使用 INotifyPropertyChanged 的資料繫結)的代碼元素,如果這些實體只用於與 Windows Communication Foundation (WCF) 服務進行通訊,則無需使用這些代碼元素。
由於 LINQ to SQL 和Entity Framework支援使用 DataContractSerializer 對實體進行序列化(使用 DataContract 和 DataMember 屬性進行標記),因此您可能希望將它們用於您的服務作業中,而無論這樣做會帶來多大的負擔。畢竟,當您設定 WCF 服務引用時,集合類型(如 LINQ to SQL 和Entity Framework使用的集合類型)在用戶端上顯示為簡單數組。
但是,如果您將 LINQ to SQL DataContext 的 SerializationMode 從“None”設定為“Unidirectional”,則只有一對多關聯性中的“多”方標有 DataMember 屬性。這表示如果您的 Order 實體有 Customer 和 Order_Details 兩個屬性,只有 Order_Details 標有 DataMember 並包含在資料約定中,而 Customer 則不能如此。另一方面,Entity Framework包含的欄位可能比您希望包含在資料約定中的要多,從而在用戶端上產生用以實現特定於Entity Framework的功能的類,例如,EntityKey、EntityKeyMember、EntityObject 或 EntityReference。
鑒於上述原因,您應該避免通過 DAL 公開 LINQ to SQL 或Entity Framework工具產生的實體,改為返回簡單的 DTO,它們存在的目的只是跨服務邊界傳送資料。例如,Order DTO(請參見圖 2)只包含屬性,不包括方法。所有的 DTO 均在 DataTransferObjects 命名空間中定義,以與工具產生的同名類進行區分。
 圖 2 表示 Northwind 中的訂單的 DTO
靈活的 DAL 應該可以使 Order Service 不受基礎持久性技術更改的影響。例如,假設您選擇使用 SQL Server 來儲存資料並且您的物件模型和資料庫結構描述極其類似,因此,您決定使用 LINQ to SQL 持久化對象。但是,當您編寫 LINQ to SQL 持久性邏輯後不久,您決定使用其他資料庫系統(如 Oracle)或希望使用Entity Framework的映射功能來分離概念架構和邏輯架構。或許一種新的資料訪問技術已推出,您希望使用該技術。如果您設計了基於外掛程式體繫結構的靈活 DAL,則應該可以根據 app.config 中的條目隨時切換提供者。
為實現此靈活性,我建立了 IDataProvider 介面,該介面具有用以檢索和更新客戶訂單,以及檢索支援的客戶和產品資訊的方法(請參見圖 3)。本應用程式範例包括兩個實現 IDataProvider 的類:使用 LINQ to SQL 的 SqlDataProvider;使用Entity Framework和 LINQ to Entities 的 EntityDataProvider(請參見圖 1)。您僅可以為 DAL 的 app.config 檔案中的“DataProvider”設定輸入完整類名稱,並使用 Assembly 類的 CreateInstance 方法建立此類的執行個體,從而將其轉換為 IDataProvider。Order Service 對實現 IDataProvider 而使用的類沒有特別要求,因此您可以選擇任何資料提供者:
IDataProvider provider =
  Assembly.GetExecutingAssembly()
  .CreateInstance(Settings.Default.DataProvider, true)
  as IDataProvider;
 圖 3 將 DAL 與介面分離
預設情況下,LINQ to SQL 和Entity Framework會在與項目相同的命名空間中產生實體。但是,如果將新的“LINQ to SQL Classes”項目置於 L2S 專案檔夾中,此工具會使用此檔案夾名作為嵌套的命名空間,這有助於區分 LINQ to SQL 實體和 DTO 實體。同樣,如果將新的“ADO.NET Entity Data Model”置於 L2E 專案檔夾中,Entity Framework實體也會存在於嵌套的 L2E 命名空間。另外,您可以在 LINQ to SQL 的屬性視窗和Entity Framework可視組件設計器中指定命名空間。
此處,我選擇為 LINQ to SQL 和Entity Framework兩者產生實體,並將查詢結果轉換為 DTO。此時還存在以下兩種可能性:完全消除工具產生的實體;使用 XML 檔案對應 DTO。Entity Framework 已使用了 XML 對應檔,但是在Entity Framework的第一個版本中,使用簡單的 C# 對象 (POCO) 根本無法實現完全的持久化透明 (PI)。在版本 1 中,您可以實現此目標,但實體必須首先實現兩個介面:IEntityWithRelationships 和 IEntityWithChangeTracking,因此這種情況需要使用 IPOCO(POCO + 介面)。.希望Entity Framework的將來版本能夠改進對 POCO 和持久化透明的支援。
LINQ to SQL 確實能夠很好地支援使用 XML 對應檔將 POCO 映射到資料庫結構描述。但是,從 L2S.Order 或 L2E.Order 投影到 DTO.Order 提供了更大程度的靈活性。例如,圖 4 顯示的 SqlDataProvider 的 GetOrder 方法,此方法根據 L2S.Order Customer 屬性的 ContactName 屬性填充 DTO.Order 的 CustomerName 屬性,實際上恰恰反映了 Customer 和 Order 之間的關係。同理,我也可以根據 L2S.Order_Detail 的 Product 屬性設定 DTO.OrderDetail 的 ProductName 屬性。在每一種情況下,我都必須將 DataContext 的 LoadOptions 屬性配置為積極式載入 LINQ to SQL 實體。
 圖 4 GetOrder 方法使用 LINQ to SQL 架構返回 DTO.Order
現在讓我們回到 EntityDataProvider 的 GetOrder 方法,該方法使用 LINQ to Entities 基於 L2E.Order 返回 DTO.Order(請參見圖 5)。注意,Include 運算子用於積極式載入 Order_Details 和 Order_Details.Product 屬性。(有關 LINQ 運算子的詳細資料,請參見資料點專欄“LINQ 的標準查詢運算子”)。Entity Framework和 LINQ to SQL 都沒有提供現成的消極式載入功能,因此您必須明確指出希望在查詢結果中包含哪些相關實體。檢索到指定的訂單之後,您可以直接使用它來建立新的 DTO.Order。
 圖 5 GetOrder 方法使用 LINQ to Entities 返回 DTO.Order
持久化各個對象
LINQ to SQL 和Entity Framework採用不同的方法持久化中斷連線的實體。例如,假設您希望建立具有一個或多個訂單明細的新訂單。 6 所示,LINQ to SQL 至少需要兩行代碼:一行代碼調用 InsertOnSubmit 以插入訂單,一行代碼使用 InsertAllOnSubmit 插入訂單的明細項目。而Entity Framework只需要您將訂單添加到 ObjectContext 的 OrderSet,它會自動添加完整的對象圖表(請參見圖 7)。LINQ to SQL 和Entity Framework都採用以下操作過程:首先插入父訂單、擷取 OrderID 值(資料庫中的識別欄位),然後插入子訂單明細。
 圖 6 使用 LINQ to SQL 建立訂單
 圖 7 使用 LINQ to Entities 建立訂單
在介紹刪除或更新實體之前,我需要首先介紹一下如何處理並發問題。LINQ to SQL 要求您附加一個中斷連線的實體才能調用 DeleteOnSubmit。這樣做系統會提示您使用 LINQ to SQL 執行最優的並發檢查,如果使用者嘗試刪除其他使用者已經更改的項目,則刪除將會失敗,並發出 ChangeConflictException。實際上確實沒有簡單方法可以關閉此行為,因為如果您嘗試在不調用 Attach 的情況下調用 DeleteOnSubmit,LINQ to SQL 將會引發 InvalidOperationException。但是,Entity Framework並不強制您在刪除實體時處理更改衝突(請參閱本文附帶的代碼下載)。
圖 8 顯示了使用 LINQ to SQL 更新訂單的代碼。請注意,Attach 方法接受 bool 類型的 asModified 參數。對 LINQ to SQL 來說,將此參數設定為“True”表示您希望將時間戳記列用於並發管理。這樣做會使 LINQ to SQL 將當前的時間戳記值包含到 SQL Update 語句的 WHERE 子句中。當其他使用者更新此記錄時,此更新不會影響任何行,並且 LINQ to SQL 將引發 ChangeConflictException。
 圖 8 使用 LINQ to SQL 更新訂單
使用此策略,用戶端既不需要保留原始值也不需要將其隨更新一起提交,而是將這些值傳遞到 Attach 方法的其他重載。系統對此列的命名方式沒有要求,只需包含時間戳記資料類型即可。當您將具有時間戳記列的表添加到 Visual Studio 的 LINQ to SQL 設計器之後,所有實體欄位的 UpdateCheck 屬性將設定為 Never,並且 LINQ to SQL 將使用時間戳來檢查更改衝突。
當前,相對於 LINQ to SQL 來說,使用Entity Framework更新實體和管理並發稍微有些複雜,因為即使在並發管理中使用時間戳列,它也需要實體的原始值(請參見圖 9)。(這一方面可能會在Entity Framework的下一版本中獲得改善。)由於用戶端未提供原始訂單,您需要從資料庫中檢索此訂單並將其 Updated 屬性設定為用戶端提供的值,此“原始”值才是您真正需要的值。請確保提交對 Updated 的更改,方法為:分離並重新將訂單附加到物件內容,或者調用 AcceptAllChanges。然後,調用 ApplyPropertyChanges 使用更新訂單所提供的值更新原始訂單。此外,還需要執行一個步驟,Entity Framework才能使用時間戳列進行並發檢查:即,在 Order 實體上將 Updated 屬性的 ConcurrencyMode 值從“None”設定為“Fixed”(請參見圖 10)。
 圖 9 使用 LINQ to Entities 更新訂單
 
圖 10 將 Updated 的 ConcurrencyMode 設定為“Fixed”

跨服務邊界跟蹤更改
如果您希望僅調用服務一次即可在同一事務中持久化多個實體的更改,您需要使用一種方法來確定每個實體的更改狀態。這就是應用程式範例中的每個 DTO 都包含 TrackingState 屬性的原因。如果用戶端已經設定了此屬性,DAL 即可以使用合適的 LINQ to SQL 或Entity Framework API 持久化對中斷連線的實體的插入、更新和刪除。這樣做允許將 DTO 數組傳遞到服務作業進行批次更新,以便使用簡單的 LINQ to Objects 查詢找到插入、更新或刪除的訂單明細。例如,要想只獲得添加到訂單的訂單明細,您可以使用 TrackingState Created 在集合中查詢此類項目:
List<Order_Detail> insertedDetails =
  (from od in order.OrderDetails
  where od.TrackingState == TrackingInfo.Created
  select new Order_Detail
  {
  OrderID = od.OrderID,
  ProductID = od.ProductID,
  Quantity = od.Quantity,
  UnitPrice = od.UnitPrice,
  Updated = od.Updated == null ? new byte[0] : od.Updated
  }).ToList();
您必須將 Updated 的 null 值轉換為空白位元組數組,因為資料庫表中的時間戳記列通常不可為空。獲得插入的訂單明細的列表後,您可以使用合適的 LINQ to SQL API 通過傳遞訂單明細集合來添加新實體:
db.Order_Details.InsertAllOnSubmit(insertedDetails);
和您預想的一樣,有 AttachAllOnSubmit 和 DeleteAllOnSubmit 方法可滿足您的需要。當對 DataContext 調用 SubmitChanges 時,LINQ to SQL 會確保按正確的順序提交這些更改(對插入項目使用父子順序,對刪除項目使用子父順序),並且將所有的操作包含在一個事務中。您可以藉助相同的方法使用 LINQ to Entities 持久化訂單明細。有關適用於 LINQ to SQL 和Entity Framework的 UpdateOrder 的完整代碼清單,請參閱下載內容。
現在,很明顯就可以看出 DAL 依靠用戶端跟蹤每個 DTO 的更改狀態。用戶端上跟蹤對象更改的最方便機制是泛型集合。為了使集合能夠更新 TrackingState 屬性,應該約束型別參數以實現介面。(您還可以使用 Reflection 獲得和設定 TrackingState 屬性,但泛型型別約束可提供型別安全和更好的效能。)輸入只包含 TrackingState 屬性的 ITrackable 介面:

public interface ITrackable
  {
  TrackingInfo TrackingState { get; set; }
  }
 
正如我前面提及到的,跟蹤更改集合有兩種類型:一種用於 Windows 表單,擴充 BindingList<T>;一種用於 WPF 應用程式,擴充 ObservableCollection<T>。我並沒有在這兩個集合中重複變更追蹤邏輯,而是將此邏輯集中到 ChangeTrackingHelper<T> 類中,此類從 Collection<T> 派生並約束 T 以實現 ITrackable(請參見圖 11)。此外,它還約束 T 以實現 INotifyPropertyChanged,以便處理每個項目的 PropertyChanged 事件以及將 TrackingState 屬性設定為 Updated。
 圖 11 變更追蹤協助程式類
將項目添加到集合後,其 TrackingState 將設定為 Created。項目刪除後,其 TrackingState 將設定為 Deleted,並緩衝在已刪除項目的集合中。在進行跟蹤之前,使用者應該首先將集合的 Tracking 屬性設定為 True,以便集合訂閱每個項目的 PropertyChanged 事件。GetChanges 方法會建立一個新的 ChangeTrackingHelper 集合,其中僅包含標記為建立、更新或刪除的項目。

配置用戶端
我們已經瞭解了一組通用的跟蹤更改集合,現在可以派上用場了!我已將這些集合放置在一個單獨類庫中,因此您只需從用戶端應用程式中引用即可。但是,當您向用戶端項目加入服務參考時,您必須執行一些其他步驟,集合才能使用 svcutil.exe 產生的類。雖然 Customer、Product、Order 和 OrderDetails 等類已經具有了 TrackingState 屬性,但它們不會實現 ChangeTrackingHelper<T> 所需的 ITrackable 介面。
另外,必須將 TrackingInfo 枚舉放置在跟蹤更改集合可以找到的命名空間,但不是嵌套命名空間,因為 svcutil.exe 會在您加入服務參考時將其置於此處。最後,如果服務作業返回的對象數組在用戶端應用程式中顯示為跟蹤更改集合,那就更好了。因為這樣會使 Order.OrderDetails 的資料類型設定為 ChangeTrackingCollection<T> 或 ChangeTrackingList<T>(而非 OrderDetail 數組),從而減少向服務發送已更改的訂單明細的工作量。
要設定 Windows 表單或 WPF 用戶端應用程式,使其使用跟蹤更改集合跟蹤實體更改並將這些更改發送至服務,需要遵循以下步驟。務必按照給定順序執行以下步驟:
在 Windows 表單或 WPF 用戶端應用程式中,設定對 ClientChangeTracker 類庫項目或程式集(ITrackable 介面和跟蹤更改集合置放位置)的引用。
在 WCF 服務應用程式啟動並執行過程中,添加指向中繼資料終點或 Web 服務描述語言 (WSDL) URL 的服務引用。在加入服務參考之前,引用 ClientChangeTracker 程式集非常重要。預設情況下,服務引用將重用所有引用程式集中的類型,並且由於 ClientChangeTracker 包含的 TrackingInfo 枚舉具有 DataContract 和 EnumMember 序列化屬性,svcutil.exe 會重用此枚舉而不會將其複製到服務引用建立的 Reference.cs 代碼檔案中。
設定服務引用之後,為服務引用建立的每個 DTO 類添加局部類。例如,如果您的服務作業公開了 Customer、Product、Order 和 OrderDetail 對象,它們都將包含在服務引用中。如果顯示項目的所有檔案並展開服務引用和 Reference.svcmap 節點,您會在 Reference.cs 中看到這些類。記下它們所屬的命名空間(應該與您加入服務參考時指定的位置一致)。現在將類檔案添加到項目中並更改命名空間,以在 Reference.cs 中反映此命名空間。在此命名空間中,為每個 DTO 類添加公用局部類並實現 ITrackable 介面:
namespace WpfClient.OrderService
{
  public partial class Customer : ITrackable { }

  public partial class Product : ITrackable { }

  public partial class Order : ITrackable { }

  public partial class OrderDetail : ITrackable { }
}
注意 TrackingState 屬性缺失的情況。由於此屬性作為每個 DTO 資料約定的一部分包含在代碼產生的類中,因此您無需在此處插入該屬性。為了在應用程式中更加輕鬆地使用這些類,您還可以在這些類中插入其他代碼,例如,初始化類的建構函式(使用 new 建立類時調用;WCF 建立類時不調用)。有關樣本,請參閱代碼下載。
最後,您可能希望將服務引用配置為使用 ChangeTrackingCollection<T> 或 ChangeTrackingList<T> 作為集合類型,而不是 System.Array。這表示當服務作業返回 Order 數組時,將在用戶端上具體化為 ChangeTrackingCollection<Order> 或 ChangeTrackingList<Order>。每個 Order 的 OrderDetails 屬性都有可能顯示為跟蹤更改集合類型。知道這有多酷了吧?要想實現這種奇妙的轉變,您必須開啟 Reference.svcmap 檔案(顯示所有專案檔並開啟服務引用進行查看)然後深入研究 XML。對於 WPF 用戶端,按如下所示配置 CollectionMappings 元素:
<CollectionMappings>
  <CollectionMapping TypeName="ChangeTracker.ChangeTrackingCollection'1" Category="List" />
</CollectionMappings>
對於 Windows 表單用戶端,您應該將 ChangeTracker.ChangeTrackingCollection`1 替換為 ChangeTracker.ChangeTrackingList`1。
現在,在服務應用程式運行過程中,按右鍵服務引用並選擇“更新服務引用”,然後重新編譯用戶端應用程式。如果一切順利,則會成功構建項目,您將可以繼續執行操作。
完成這些步驟之後,剩下的就是為用戶端應用程式編寫代碼以檢索某些 DTO 並將它們綁定到 UI(使用者可以在此處更新 DTO 並將其發送回服務以儲存到資料庫中)。從服務中檢索對象只需要建立一個服務代理執行個體並叫用作業來擷取 Customer、Product 和 Order 即可。例如,如果服務包含的 GetOrder 方法接受 Int 類型的 OrderId,那麼您的用戶端代碼可能如下所示:
using (OrderServiceClient proxy = new OrderServiceClient())
{
  CurrentOrder = proxy.GetOrder(orderId);
}
如果您的資料繫結設定正確,訂單和訂單明細都應該顯示在使用者介面上。圖 12 顯示了應用程式範例在 WPF 用戶端中的顯示。單擊“Get Order”按鈕,使用者可以檢索某個現有訂單,以及從客戶訂單列表中進行選擇;單擊“New Order”按鈕可直接建立新訂單;單擊“Delete Order”按鈕,使用者可對伺服器代理調用 DeleteOrder,從而刪除當前訂單。
 
圖 12 樣本 WPF 用戶端應用程式 
單擊“Save Order”按鈕,可以調用服務 CreateOrder 操作以持久化最新建立的訂單,或調用 UpdateOrder 操作儲存對現有訂單的更改。這兩種操作都會返回一個訂單對象,其中包含用於並發管理的當前 Updated 屬性和用於插入訂單的新 OrderId 屬性(Northwind 中 Order 表使用識別欄位)。獲得更新訂單後,您即可以啟動變更追蹤並將資料繫結設定為使用訂單。
但是,在儲存現有的訂單之前,您還需要執行一些操作。我們只希望傳遞建立、更新或刪除的訂單明細,而不想浪費網路頻寬來發送未發生更改的訂單明細。藉助 ChangeTrackingCollection<T> 和 ChangeTrackingList<T> 可以比較輕鬆地實現此目的,因為它們公開的 GetChanges 方法只返回插入、修改或刪除的訂單明細。調用 UpdateOrder 的代碼 13 所示。
 圖 13 調用 UpdateOrder
由於我已經將服務引用配置為使用 ChangeTrackingCollection<T> 作為集合類型,因此 Order 類的 OrderDetails 屬性應該屬於類型 ChangeTrackingCollection<OrderDetail>,並且我可以直接對其調用 GetChanges 只獲得添加、修改或刪除的訂單細節,以傳遞給 UpdateOrder 操作。另外,由於 ChangeTrackingCollection<T> 可擴充 ObservableCollection<T>,因此它支援的資料繫結功能非常適用於 WPF 應用程式(例如,實現 INotifyCollectionChanged 以便在向集合添加或從集合刪除項目時 UI 可以更新項目集合控制項)。同理,由於 ChangeTrackingList<T> 可擴充 BindingList<T>,它可以作為 Windows 表單 DataGridView 的有效資料來源,以利用 BindingList<T> 實現的介面增強使用者體驗。

總結
現在您已經擁有了一個面向服務的靈活應用程式體繫結構,在此體繫結構中,用戶端可以完全不考慮對象的持久化方法。我們知道,DTO 允許對物件模型的結構和形狀進行更多的控制,這與允許跨服務邊界傳遞工具產生的實體一樣具有吸引力。此外,構建資料訪問層可將應用程式從您使用的任何持久性技術中分離出來,從而允許您在不影響應用程式的其他部分的情況下更換資料訪問實現。
LINQ to SQL 和 ADO.NET Entity Framework的出現代表了 ORM 領域的一次巨大飛躍,有效地減少了對象和關係資料之間的阻抗失諧。它們支援各種方案,包括傳統用戶端伺服器和服務導向架構。但是,對於開發人員來說,使用 DTO 更新資料庫需要進行更多的工作,尤其是在使用時間戳值檢測並發使用者之間的衝突時。但是,通過將更改狀態添加到用戶端和服務之間的資料約定,您可以附加與源上下文中斷連線的實體。最後,我們介紹了通用的跟蹤更改集合如何不負眾望地管理用戶端上的更改狀態,使您訪問服務一次即可處理批更新。
有關Entity Framework的詳細資料,請參閱“ADO.NET:使用Entity Framework靈活地為資料建模”(由 Elisa Flasko 編寫)。

Anthony Sneed 是開發人員培訓公司 DevelopMentor 的一名講師,他撰寫並教授 .NET Framework 3.5、LINQ 和Entity Framework的相關課程。在他的業餘時間裡,他喜歡烹飪和錄製家庭視頻,其烹調的紅辣椒很有名。您可以通過 tony@tonysneed.com 或訪問部落格 blog.tonysneed.com 與 Anthony Sneed 聯絡。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.