是否可以打开TransactionScope
,运行在EF4 Task
上运行的异步ObjectContext
,然后提交结果?
EF4如何推断当前的交易范围?如果/当任务在与事务范围不同的线程上进行调度时,这会失败吗?
答案 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)限制,多线程的不获得并发,所以你不妨在一个线程上保留一个事务并保持简单。未来的维护者会感谢您的清晰。