EF4,TransactionScope和Task<>

时间:2011-12-09 17:01:17

标签: .net entity-framework transactionscope task-parallel-library async-ctp

是否可以打开TransactionScope,运行在EF4 Task上运行的异步ObjectContext,然后提交结果?

EF4如何推断当前的交易范围?如果/当任务在与事务范围不同的线程上进行调度时,这会失败吗?

2 个答案:

答案 0 :(得分:4)

是的,确实如此。对于初学者,Entity Framework只使用下面的提供程序(默认为System.Data.SqlClient),它将从正在执行的线程中获取“环境”事务上下文。所以,从那里开始,唯一的技巧就是将单个事务传播到你启动的Tasks。我在this post解释了你如何做到这一点。

虽然这篇文章更多的是关于PLINQ衍生任务的推广,但如果您手动启动自己的Tasks,则适用相同的方法。如果您想要一个代码示例,请告诉我您的Task产生确切如何工作的基本细节,以便我可以提供良好的示例代码。

答案 1 :(得分:0)

不,你不能(有用)这样做。

虽然Drew Marsh的答案是正确的(存在使交易跨越线程边界的方法),但它不会对你有所帮助。 ObjectContext不是线程安全的 - 你不应该从其他线程访问它,你应该肯定不在其他线程上更新它;你将有未定义的行为:你可能会遇到数据损坏,这(如果你很幸运)将导致崩溃。

如果您需要多线程ObjectContext访问权限,则需要手动序列化访问,例如使用锁定。但是如果你这样做,你也可以简单地从一个线程访问上下文;它通常更简单,而且几乎总是更快 - 然后你的交易就没有问题了。

如果你坚持手动同步ObjectContext的访问而不是使用线程,你也可以使用普通CommittableTransaction并明确地传递它而不是使用环境事务;因为你无论如何都需要手动控制事务,所以使用对象的显式句柄而不是棘手的状态转换更清楚(其中哪个线程运行的重要细节在代码中是至关重要但不明确)。

顺便说一句,如果你使用环境事务,我会小心任务调度,特别是使用C#5的异步功能,因为你可能需要清楚地知道执行何时可以改变线程(我从来没有试过这个,所以我不能给你任何指示,不幸的是。)

摘要:只是不这样做:由于ObjectContext(以及实际上,DB)限制,多线程的获得并发,所以你不妨在一个线程上保留一个事务并保持简单。未来的维护者会感谢您的清晰。