EF4、TransactionScope和Task<>是什么?

4

是否可以打开一个TransactionScope,运行一系列操作EF4ObjectContext的异步Task,然后提交结果?

在EF4中如何推断当前事务范围?如果/当任务被调度到不同于事务范围的线程上时,会发生什么错误?

2个回答

4
是的,它是可以的。首先,Entity Framework 只是在使用提供程序 (默认为 System.Data.SqlClient) ,该提供程序会从正在执行的线程中获取“环境”事务上下文。因此,从那里开始,唯一的技巧就是将单个事务传播到您启动的 Tasks 中。我已经在这篇文章中解释了如何实现这一点。
虽然这篇文章更多地涉及到传递给 PLINQ 生成的任务,但如果您手动启动自己的Tasks, 同样的方法也适用。如果您需要代码示例,请告诉我有关您的Task生成方式的基本细节,以便我可以提供良好的示例代码。

0

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

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

如果你想要多线程ObjectContext访问,你需要手动序列化访问,例如使用锁。但如果你这样做,你也可以简单地从一个线程访问上下文;这通常更简单,几乎总是更快 - 然后你就不会遇到事务问题了。

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

顺便说一下,如果您确实使用环境事务,我建议您在任务调度方面要小心,特别是在使用C# 5的异步功能时,因为您可能需要清楚地知道何时执行可以更改线程(我从未尝试过这样做,所以无法给您任何指针,不幸的是)。
总结:千万不要这样做:由于ObjectContext(在实践中是数据库)的限制,您并没有通过多线程获得并发性,因此最好将一个事务留在一个线程上并保持简单。未来的维护者会感谢您的清晰度。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接