【发布时间】:2011-10-11 16:15:14
【问题描述】:
我最近遇到了 EF4 令人惊讶的行为,在将实体添加到上下文后,它无法用于查询(嗯,您需要让您的查询知道,您可能正在内存中搜索),除非 SaveChanges( ) 被调用。
让我解释一下我们的场景: 我们将 UnitOfWork pattern 与 EF 4.0 和 POCO 对象一起使用。我们最近决定实现Message Bus,我们将在消息处理程序中实现大部分应用程序逻辑。
我遇到的问题是当我在消息中传递我的 UnitOfWork(在我们的例子中是上下文包装器)时。例如,我有打印条形码的逻辑,当我这样做时,它应该更改数据库中的打印计数器。打印可以针对现有包临时进行,也可以在创建特殊类型的包时自动完成。我通过了 UnitOfWork,然后寻找带有以下内容的条形码:
public void Handle(IBarCodePrintMessage message)
{
if (message.UnitOfWork == null)
using (var uow = factory.Create<IUnitOfWork>)
{
Handle(message, uow);
uow.Commit();
}
else
Handle(message, message.UnitOfWork);
}
void Handle(IBarCodePrintMessage message, IUnitOfWork uow)
{
// the barcode with the PackageID is in the context or in the db
var barCode = uow.BarCodes.Where(b => b.PackageID == message.PackageID).SingleOrDefault();
barCode.IncreasePrintCount(); // this might be actually quite complex, and sometimes fail
printingServices.PrintBarCode(barCode);
}
我的问题是,如果条形码是在同一个 uow 中添加的,并且还没有提交,那么它就找不到了。
这是最简单的例子,我们有大量代码在进行自己的提交,现在所有这些都需要在一个事务下进行。
其实我有几个问题:
1) 我正在考虑以某种方式破解我的 IUnitOfWork,以返回一组对象,这些对象可能在内存中(未提交的更改)或数据库中(如果尚未检索)。这实际上是我希望我的 UnitOfWork 的一种行为,告诉我我处于的最后一个状态是什么,即使我还没有提交,也不要给我 db 状态。对于 db 状态,我可以创建另一个上下文。
无论如何这似乎很棘手,因为我需要实现我自己类型的实体集合,它上面的所有扩展方法(where、select、first、groupby 等),然后让它工作 IQueryable方式(意味着它不会立即列出表),然后找到一种方法来匹配本地缓存的实体和检索到的实体。 对我来说,这似乎是一个普遍的问题,我相信已经有一个实现,只是不确定在哪里。
2) 另一种选择是引入手动交易。我对 SQLCE4.0 进行了尝试,它可能会解决问题(经常调用 savecontext,因此可以从数据库中查询实体,然后如果发生任何错误,则回滚事务),但我有很大的疑问。可能有不同的线程同时运行不同的事务,不确定如果一个回滚它们将如何交互。
我们还使用 SQL CE 4.0 和 SQL Express 2008(两者都可以动态切换)。开始以这种方式处理交易似乎会带来 DTC,我到处都读到它是一件相当沉重的事情,我宁愿避免。有没有一种方法可以轻松地使用交易,而不会将交易用于 DTC?
3) 是否有人对如何解决此问题有任何其他选择或想法?
【问题讨论】:
标签: c# entity-framework transactions poco unit-of-work