2014-03-02 29 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