如何保持工作单元抽象不泄漏

时间:2014-03-02 17:03:01

标签: c# entity-framework data-access-layer

我正在学习良好的设计实践,并获得了工作单元设计模式以及存储库。这允许我让应用程序逻辑不了解持久性细节,但是有一些极端情况我处理有些困难。

首先,在IUnitOfWork接口后面我正在使用一个使用EF访问我的数据的实现。对于我的查询,我使用规范设计模式来创建客户端可以使用的查询对象。

所以,到目前为止,这个东西几乎是从数据源中抽象出来的,但这是交易: 想象一下我想用AsNoTracking选项检索一些数据。我该如何告诉我的IUnitOfWork实现我不需要跟踪生成的对象?

此外,EF并不真正支持批量CUD,也不支持Future Queries,但有一个支持的扩展。我如何以客户端代码与持久对象的方式完全无关的方式支持这一点?我可能想要使用平面文件,以满足所有代码需求。

TL; DR; 如何让我的UnitOfWork抽象不泄漏到我的客户端?有没有人处理过这个问题?

1 个答案:

答案 0 :(得分: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一样,你可以拥有一个长期存在的上下文,用于处理在不同线程上异步执行的大型命令队列。