ADO 实体框架是否支持非 DTC 事务?一个 EntityContext 和一个 TransactionScope 内的多个查询导致 DTC 升级
我有一个使用实体框架的 Web 应用程序 - 我们利用 TransactionScope 类来提供环境事务。
有没有办法告诉 EF 使用标准 T-SQL 事务而不是 DTC 事务?我们经常对一个 EntityContext 和一个 TransactionScope 实例中的不同表进行多次查询,但这似乎总是将事务提升为 DTC
我已经将一个简短的示例放在一起,请参见下文。对单个表的查询正确启动 T-SQL 事务并且连接 SPID 54 然后对 ContactUs 表进行查询,EF 在不同的连接 (SPID 53) 上执行此操作,这具有将事务提升为 DTC 事务的连锁效应。**
using (MyEntities DB = new MyEntities())
{
using (TransactionScope t = new TransactionScope())
{
DB.Individual.First().EmailAddress = "bob" + DateTime.Now.Second.ToString() + "@bob.com"; // done on connection 54
DB.ContactUs.First(); // done on connection 53 thus promoting the transaction!!
DB.SaveChanges();
t.Complete();
}
}
I have a web application that uses the Entity Framework - we make use of the TransactionScope class to provide ambient transactions.
Is there any way to tell EF to use a standard T-SQL transaction in preference to DTC transaction? Quite often we make a number of queries to different tables inside one EntityContext and one TransactionScope instance, however this seems to always promote the transaction to DTC
I have put a short example together, see below. The query to the individual table correctly starts a T-SQL transaction and was on connection SPID 54
Then the query to the ContactUs table is made and EF does this on a different connection (SPID 53) which has the knock on effect of promoting the transaction to a DTC transaction.**
using (MyEntities DB = new MyEntities())
{
using (TransactionScope t = new TransactionScope())
{
DB.Individual.First().EmailAddress = "bob" + DateTime.Now.Second.ToString() + "@bob.com"; // done on connection 54
DB.ContactUs.First(); // done on connection 53 thus promoting the transaction!!
DB.SaveChanges();
t.Complete();
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
在连接字符串上设置 Enlist=false 以避免在事务上自动登记。
手动将连接登记为事务范围的参与者。 (http://msdn.microsoft.com/ en-us/library/ms172153%28v=VS.80%29.aspx)
Set Enlist=false on connection string to avoid auto enlistment on transaction.
Manually enlist connection as participants in transaction scope. (http://msdn.microsoft.com/en-us/library/ms172153%28v=VS.80%29.aspx)
您没有提到,但听起来您正在使用 SQL Server 2005。在 SQL Server 2005 下,如果在 TransactionScope 内打开多个连接,则事务将 从轻量级事务升级为分布式事务。如果是相同的数据库和相同的 ConnectionString 并不重要——它仍然会被提升。
这不是实体框架的“问题”,而是 System.Transactions 的现有行为。常规 ADO.NET 也存在此问题。过去,我使用过企业库,它在幕后维护着参与事务的连接列表,如果您尝试在事务中检索新连接,它将返回已经打开并参与事务的连接。交易。
如果您使用 SQL Server 2008,则行为会得到改进,以便 打开与同一数据库的多个连接时不会提升事务。
You didn't mention, but it sounds like you are using SQL Server 2005. Under SQL Server 2005, if more than one connection is opened inside a TransactionScope then the transaction will escalate from a lightweight transaction to a distributed transaction. It doesn't matter if it is the same database and the same ConnectionString -- it still gets promoted.
This isn't an "issue" with Entity Framework as much as it is an existing behavior with System.Transactions. The issue exists with regular ADO.NET as well. In the past I have used Enterprise Library which under the covers maintains a list of connections that are participating in transactions and if you attempt to retrieve a new connection while in a transaction, it will return you the connection that is already open and participating in your transaction.
If you use SQL Server 2008, then the behavior is improved so that transactions are not promoted when opening multiple connections to the same database.
并不是实体框架导致了分布式事务的使用;而是实体框架导致了分布式事务的使用。相反,它是TransactionScope。 EF 将使用“正常”事务来包装在对
SaveChanges()
的单个调用的上下文中执行的所有 SQL 语句。在您给出的示例中,您只有一次对SaveChanges
的调用。因此,您根本不需要使用TransactionScope
来自动应用更改。我不知道如何使
TransactionScope
使用非分布式事务,但我有理由相信它不是实体框架正在执行此操作。It is not the Entity Framework which is causing use of distributed transactions; rather, it is
TransactionScope
. The EF will use a "normal" transaction to wrap up all SQL statements executed in the context of a single call toSaveChanges()
. In the example you give, you have only one call toSaveChanges
. Therefore, you would not need to useTransactionScope
at all to have your changes applied atomically.I do not know how to make
TransactionScope
use non-distributed transactions, but I'm reasonably confident that it is not the Entity Framework which is doing this.我在使用 Entity Framework 和 ASP.NET 成员资格系统时遇到了 DTC 升级问题,因为两者使用不同的连接字符串。在会员系统的连接字符串中设置“Enlist=false”解决了我的问题。
I was hitting DTC escalation issues using Entity Framework with the ASP.NET membership system as the two use different connection strings. Setting "Enlist=false" in the membership system's connection string solved the problem for me.