2014-03-02 26 views
0

我正在學習良好的設計實踐,並加入了工作單元設計模式以及知識庫。這允許我讓應用程序邏輯不知道持久性細節,但是有一些我遇到了一些困難的情況。如何保持工作單元抽象不被泄漏

首先,在IUnitOfWork界面後面我使用了一個使用EF訪問我的數據的實現。對於我的查詢,我使用規範設計模式來創建客戶端可以使用的查詢對象。

因此,從數據源到現在爲止,這個東西已經非常抽象了,但是這裏有一筆交易: 想象我想用AsNoTracking選項檢索一些數據。我該如何告訴我的IUnitOfWork實現,我不需要跟蹤結果對象?此外,EF並不真正支持批量CUD,也不支持未來查詢,但有一個支持的擴展。我如何以客戶端代碼完全不知道我堅持對象的方式來支持它?對於所有的代碼關心,我可能想使用平面文件。

TL; DR; 如何讓我的UnitOfWork抽象漏入客戶端?有沒有人處理過這個問題?

回答

0

其中大部分將通過注入一個存儲庫來實現,該存儲庫的實現可以提供那些未被跟蹤的對象,或者對平面文件進行讀/寫操作。

很多概念知識庫與UoW交叉使用。回購實施結束有很多這樣的:

public class MyRepository : IWhateverRepository 
{ 
    // ... 
    public Customer GetCustomerByName(string customerName) 
    { 
     using (var db = new MyContext()) 
     { 
      var customer = db.Customers.Where(cust => cust.Name == customerName).SingleOrDefault(); 
      return customer; 
     } 
    } 

    public Customer StoreCustomer(Customer customer) 
    { 
     using (var db = new MyContext()) 
     { 
      db.Entry(customer).State = customer.ID == 0 ? EntityState.Added : EntityState.Modified; 
      db.SaveChanges(); 
     } 
    } 
} 

正如你所看到的,沒有一大堆的UOW的使用。我認爲在使用存儲庫時,EF的大部分用處是無需手動編寫SQL。

但是,當沒有存儲庫抽象並且業務邏輯直接與實體和上下文一起工作時,UoW運行良好。例如在UI < - > MVC < - >服務層情況下,您可能具有MVC控制器指示服務層來創建一個新的發票:

IMyService svc = new MyServiceLayer(); 
IInvoice invoice = svc.CreateInvoiceForCustomer(customer, items, paymentInfo); 
InvoiceViewModel invoiceVm = Map(invoice); 
return RedirectToAction("Display", "Invoice", invoiceVm); 

你能想象的是,服務層不妨做到以下幾點:

public ServiceResponse<Invoice> CreateInvoiceForCustomer(Customer customer, IEnumerable<InvoiceItem> items, PaymentInfo paymentInfo) 
{ 
    using (var db = new MyContext()) 
    { 
     db.Entry(customer).State = customer.ID == 0 : EntityState.Added : EntityState.Modified; 

     var invoice = new Invoice 
      { 
       Customer = customer, 
       InvoiceDate = _timeService.Now(), 
       PaymentInfo = paymentInfo 
      }; 
     foreach (var item in items) 
      invoice.Items.Add(items); 

     db.Invoices.Add(invoice); 
     db.SaveChanges(); 

     return new SeviceResponse<Invoice> 
      { 
       IsSuccess = true, 
       Data = invoice 
      }; 
    } 

} 

在這個例子中,UoW模式充當事務的替代。你得到Atomicity而不會弄髒你的手。

UoW的真正威力在於一個有狀態的系統,就像WPF一樣,你可以擁有一個長期的上下文,用於處理在另一個線程上異步執行的大隊列命令。

+0

在我的情況我使用Winforms,我需要訪問多個存儲庫,並保持它們之間的數據同步,所以我可以查詢多個存儲庫並同步我的Presenter上的保存。你所說的是我可以在存儲庫中完成這個「NoTracking」部分,我認爲這是正確的。雖然這並沒有給我一個直接的方式來實現問題的「批處理」部分,但我想我可以從該存儲庫返回一個DTO值(甚至是一個元組)。只是想知道世界其他地方如何處理它。 – mbetting2011

+0

如果您想讓存儲庫參與UnitOfWork,那麼您必須在該抽象級別使用您自己的UoW實現。另一種方法是將存儲庫置於等式之外(或者你在進行域驅動設計嗎?)。如果您沒有將實體存儲在平面文件中的要求,那麼在您的設計中沒有太多理由對其進行補償。事實上,這是編碼的另一個「規則」 - Y.A.G.N.I. - 你不需要它(所以不要寫它)。 –

+0

我確實有一個工作單元的抽象。現在唯一的實現隱藏EF的DBContext對象。無論如何,我想你是對的。我不需要它。我只需要保持持久層的細節不會泄漏到其他層。無論如何,這是一個寵物項目,學習TDD的概念,與MVP,EF等適當的分層。謝謝你的幫助:) – mbetting2011