日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

在Entity Framework 4.0中使用 Repository 和 Unit of Work 模式

發布時間:2023/11/30 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 在Entity Framework 4.0中使用 Repository 和 Unit of Work 模式 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

【原文地址】Using Repository and Unit of Work patterns with Entity Framework 4.0?
【原文發表日期】 16 June 09 04:08 PM

如果你一直在關注這個博客的話,你知道我最近在討論我們加到Entity Framework 4.0中的POCO功能的方方面面,新加的POCO支持促成了在Entity Framework中實現透明性持久的新方式,而該方式在Entity Framework 3.5中是無法實現的。

如果你錯過了我的POCO系列,為方便起見,我在下面列了出來,快速瀏覽一下也許是個不錯的主意。

POCO in Entity Framework : Part 1 – The Experience(【翻譯】實體框架中的POCO支持 - 第一部分 - 體驗?)

POCO in Entity Framework : Part 2 – Complex Types, Deferred Loading and Explicit Loading?(【翻譯】實體框架中的POCO支持 - 第二部分 - 復雜類型,延遲裝載和顯式裝載?)

POCO in Entity Framework : Part 3 – Change Tracking with POCO?(【翻譯】實體框架中的POCO支持 - 第三部分 - POCO的變動跟蹤)

在這個貼子里,我想要看一下如何將我們的例子做進一步擴充,使用一些諸如Repository?和?Unit Of Work這樣常見的模式,這樣我們可以在我們的例子中實現一些特定于持久性的關注。

將我們基于Northwind的例子做一下擴充,譬如說,我有興趣支持下列與Customer(客戶)實體相關的操作:

  • 通過ID來查詢客戶
  • 通過名字來查詢客戶
  • 往數據庫中加一個新客戶

我還想能夠基于ID來查詢產品。

最后,給定一個客戶,我想要能夠往數據庫中加一個Order(訂單)。

在進入細節之前,我想先說明兩件事情:

  • 處理這個問題,“正確”的方式不止一個。在過程中,我會做許多簡化的假設,其目的是展示一幅非常高層次的草圖,示范如何實現這2個模式來解決手上的問題。
  • 通常來說,在使用TDD時,我會從測試開始,使用我的測試來逐步展開我的設計。因為在這個例子中我沒有按TDD做,請耐心點,如果你看到我在做象預先定義接口這樣的事情,而不是讓測試和共用的東西來主宰接口的必要性,等等。

實現 Repository 模式

讓我們先開始實現針對Customer實體的操作,看一下Customer的repository的樣子:

public interface ICustomerRepository { Customer GetCustomerById(string id);IEnumerable<Customer> FindByName(string name);void AddCustomer(Customer customer); }

?

這個repository接口看上去滿足有關Customer的所有需求:

  • GetCustomerById?應該允許我通過主鍵來得單個客戶實體
  • FindByName?應該允許我查詢客戶
  • AddCustomer?應該允許我往數據庫中加一個客戶

這暫時聽上去不錯,象這樣,為你的repository定義一個接口是個好主意,特別是你對使用mocks(模擬對象) 或 fakes (假冒對象)來編寫測試感興趣的話,接口允許你完全不用考慮數據庫,促成更好的單元測試。在將來會有更多的博客貼子討論可測試性,mocks 和 fakes,等等。

你也許可以進一步擴展這個接口定義,定義一個共用的IRepository,來處理多個repository類型中共有的關注。如果對你有用的話,這是件值得做的事。在這個特定的例子中,我沒看到其必要性,所以我就免了。但在你添加更多的repository以及重構時,這完全有可能會變得非常重要。

讓我們拿這個repository來看一下如何利用Entity Framework來做一個實現,允許數據訪問:

首先,我需要一個可以用來查詢數據的ObjectContext。你也許想作為repository構造器的一部分生成一個ObjectContext,但最好還是把那個關注從repository中去除,在別的地方處理為好。

這是我的構造器:

public CustomerRepository(NorthwindContext context) {if (context == null)throw new ArgumentNullException("context");_context = context; }

?

在上面的代碼片段中,NorthwindContext是個我自己的ObjectContext類型。

讓我們來提供?ICustomerRepository?接口所需的方法的實現。

GetCustomerById?非常容易實現,多虧了LINQ。使用標準的LINQ運算符,我們可以象這樣實現?GetCustomerById?:

public Customer GetCustomerById(string id) {return _context.Customers.Where(c => c.CustomerID == id).Single(); }

?

類似地,FindByName?可以象這樣。 再一次,LINQ支持使得其實現非常容易:

public IEnumerable<Customer> FindByName(string name) {return _context.Customers.Where( c => c.ContactName.StartsWith(name)).ToList(); }

?

注意,我選擇將結果呈示為IEnumerable<T>,你也許會選擇將這呈示為IQueryable<T>。這么做有其含意,在這個情形下,我對呈示建立在repository返回結果之上的基于IQueryable的另外的查詢組合,不是很感興趣。

最后,讓我們來看一下可以如何實現AddCustomer

public void AddCustomer(Customer customer) {_context.Customers.AddObject(customer); }

?

你也許想把保存功能作為AddCustomer方法的一部分來實現。那么做也許對這個簡單的例子沒問題,但一般來說,這不是個好主意,這正是Unit of Work出場的地方,過一會兒,我們會看到如何使用這個模式來允許我們實現和協調Save行為。

這里是使用Entity Framework來處理持久性的CustomerRepository的完整實現:

public class CustomerRepository : ICustomerRepository {private NorthwindContext _context;public CustomerRepository(NorthwindContext context){if (context == null)throw new ArgumentNullException("context");_context = context;}public Customer GetCustomerById(string id){return _context.Customers.Where(c => c.CustomerID == id).Single();}public IEnumerable<Customer> FindByName(string name){return _context.Customers.Where(c => c.ContactName.StartsWith(name)).AsEnumerable<Customer>(); }public void AddCustomer(Customercustomer){_context.Customers.AddObject(customer);} }

?

這里是我們可以如何在客戶端代碼中使用該repository:

CustomerRepository repository = new CustomerRepository(context); Customer c = new Customer( ... ); repository.AddCustomer(c); context.SaveChanges();

?

在處理與ProductOrder相關的需求時,我可以定義下列接口(建造類似CustomerRepository一樣的實現)。為簡便起見,我把其細節省略了。

public interface IProductRepository {Product GetProductById(int id); }public interface IOrderRepository {void AddOrder(Order order); }

?

使用ObjectContext實現 Unit of Work (工作單元) 模式

你也許已經注意到了,盡管我們沒有實現任何特定的模式來明確地地允許我們將相關操作聚合進一個工作單元(unit of work),但我們已經通過NorthwindContext(我們的ObjectContext類)免費獲取了Unit of Work功能。

其想法是,我可以使用Unit of Work將一套相關的操作聚合在一起,Unit of Work記錄我感興趣的變動,直到我準備將它們保存到數據庫為止。最終,當我準備保存時,我可以那么做。

我可以象這樣定義一個“Unit of Work”接口:

public interface IUnitOfWork { void Save(); }

?

注意,在Unit of Work中,你也許還會選擇實現Undo / Rollback功能。在使用Entity Framework時,推薦的undo做法是,丟棄你的上下文以及你想undo的變動。

我已經提到,我們的ObjectContext類型(NorthwindContext)在極大程度上支持Unit of Work模式。 基于我剛定義的契約,為了使得事情更為明確一點,我可以將NorthwindContext類改成實現IUnitOfWork接口:

public class NorthwindContext : ObjectContext, IUnitOfWork { public void Save(){SaveChanges();}. . . }

?

在做了這個變動之后,我需要對我們的repository實現做個小的調整:

public class CustomerRepository : ICustomerRepository {private NorthwindContext _context;public CustomerRepository(IUnitOfWork unitOfWork){if (unitOfWork == null)throw new ArgumentNullException("unitOfWork");_context = unitOfWork as NorthwindContext;}public Customer GetCustomerById(string id){return _context.Customers.Where(c => c.CustomerID == id).Single();}public IEnumerable<Customer> FindByName(string name){return _context.Customers.Where(c => c.ContactName.StartsWith(name)).AsEnumerable<Customer>();}public void AddCustomer(Customer customer){_context.Customers.AddObject(customer);} }

?

?

就這么簡單!現在,我們有了一個對IUnitOfWork友好的repository,你甚至可以使用基于IUnitOfWork的上下文來協調跨越多個repository的工作。下面是一個將訂單加到數據庫的例子,需要多個repository的工作來查詢數據,最終將記錄保存回數據庫中去:

IUnitOfWork unitOfWork = new NorthwindContext();CustomerRepository customerRepository = new CustomerRepository(unitOfWork); Customer customer = customerRepository.GetCustomerById("ALFKI");ProductRepository productRepository = new ProductRepository(unitOfWork); Product product = productRepository.GetById(1);OrderRepository orderRepository = new OrderRepository(unitOfWork);Order order = new Order(customer); order.AddNewOrderDetail(product, 1);orderRepository.AddOrder(order);unitOfWork.Save();

?

非常有趣地看到,為了在Entity Framework之上使用Repository 和 Unit of Work模式來訪問數據,我們要編寫的代碼是如此地少。Entity Framework的LINQ支持以及原裝的Unit of Work功能使得在Entity Framework之上建立repository簡單之極。

另一個要注意的事情是,我在這個貼子里討論的很多東西,都不是與Entity Framework 4.0特別有關,所有這些一般原理在Entity Framework 3.5下也適用。但要能夠象上面展示的那樣,在POCO支持的基礎之上,使用Repository?和Unit of Work,確實顯示了Entity Framework 4.0中的威力。我希望你會發現這非常有用。

最后,我要重申一下,有很多方式可以處理這個題目,在應用Entity Framework, Repository 和 Unit of Work時,還有許多變種方案可以符合你的需求。你也許會選擇實現公共的IRepository接口,你也許還會選擇實現Repository<TEntity>基類,來給予你一些跨越所有repository的常用repository功能。

嘗試一些方法,看哪個最適用于你。我在這里討論的只是一般的指南而已,但我希望這足夠讓你起步。更重要的是,我希望這示范了如何可以使用我們在Entity Framework 4.0中引進的POCO支持,來幫助你建造Entity Framework友好的領域模型,而不必違背透明持久性方面的基本原則。

包含我上面一些示范代碼的項目附在本貼之后。在我們的將來貼子中討論單元測試,TDD和可測試性時,我們還將對這個題目做更多的討論,敬請期待。

轉載于:https://www.cnblogs.com/colder/p/4194846.html

總結

以上是生活随笔為你收集整理的在Entity Framework 4.0中使用 Repository 和 Unit of Work 模式的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。