我正在学习良好的设计实践,并获得了工作单元设计模式以及存储库。这允许我让应用程序逻辑不了解持久性细节,但是有一些极端情况我处理有些困难。
首先,在IUnitOfWork接口后面我正在使用一个使用EF访问我的数据的实现。对于我的查询,我使用规范设计模式来创建客户端可以使用的查询对象。
所以,到目前为止,这个东西几乎是从数据源中抽象出来的,但这是交易: 想象一下我想用AsNoTracking选项检索一些数据。我该如何告诉我的IUnitOfWork实现我不需要跟踪生成的对象?
此外,EF并不真正支持批量CUD,也不支持Future Queries,但有一个支持的扩展。我如何以客户端代码与持久对象的方式完全无关的方式支持这一点?我可能想要使用平面文件,以满足所有代码需求。
TL; DR; 如何让我的UnitOfWork抽象不泄漏到我的客户端?有没有人处理过这个问题?
答案 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一样,你可以拥有一个长期存在的上下文,用于处理在不同线程上异步执行的大型命令队列。