不使用DTC的TransactionScope替代方案

6

有没有替代TransactionScope的方法,不需要启用DTC?

在这个事务中,我需要执行两个操作:

  1. 创建一个用户(使用成员资格 - SQL成员资格提供程序)
  2. 进行一次插入操作。

1
根据我的经验,在连接字符串中设置 Enlist=false 会导致 TransactionScope 完全无法工作;没有更新被注册到可用的 TransactionScope 中。我使用标准 SQL 跟踪对 Entity Framework 6 应用程序进行了事务事件验证。 - Jean-Paul M
2个回答

11

TransactionScope使用.Net中的轻量级事务管理器LTM。只有在同一事务中打开多个连接或者在不同的数据库之间进行操作时,TransactionScope才会将事务升级为基于2PC的TX管理器DTC。

对于MS SQL Server 2008及以上版本,只有当您在打开连接到不同的数据库时,DTC才会参与其中。或者,如果您从多个线程中打开连接并在同一事务中操作(除非您正在使用DependentTransaction,这是您应该在全局事务中注册的内容,以便进行线程处理)。

另外,我在Castle.Transactions中提供了一些多线程故事的支持。

另外一个注意点:如果您使用TransactionScope,请务必显式声明IsolationLevel,否则您的所有事务都将串行化(IsolationLevel.Serializable)!


3
几乎正确。只有当您打开_不同的_连接(SQL Server 2008+)时,事务才会升级(如果您使用相同的连接字符串,则仍将使用LTM)。 - Oded
@Pedre - 对于一个“分布式”事务,你需要一个事务管理器。没有任何如果、但是或可能。 - Oded
@Oded,是的,这也取决于SQL Server的版本。 - Henrik
@MarcGravell - 就我所见,它们不在同一个数据库/服务器上。 - Oded
虽然有点晚了,但是@Henrik,你是说当在单个事务中从多个线程打开到同一数据库的多个连接时,可以通过使用DependentTransaction来避免DTC吗?你从哪里得到这个信息的?我在使用SQL Server 2013时很难使这种情况正常工作,所以开始怀疑这个说法。 :) - Anders
显示剩余7条评论

2
在您的成员身份验证连接字符串中添加Enlist=false
connectionString="Data Source=xxx;Initial Catalog=xxx;Persist Security Info=True;User ID=xxx;Password=xxx;Enlist=false"

这是我的使用案例:
using (TransactionScope tScope = new TransactionScope())
{
    MembershipCreateStatus createStatus;
    Membership.CreateUser(model.Email, model.Password, model.Email, null, null, true, model.Id, out createStatus);

    if (createStatus == MembershipCreateStatus.Success)
    {
       Roles.AddUserToRole(model.Email, "Administrator");
       _UpdatePersonnelAccess(model);
       _UpdatePersonnelHasAccess(model);
       _SendEmail_Welcome(model);
       PersonSessionLog.ManageSession(model);
    }
    else
       ViewBag.Message = "Error";

    tScope.Complete();
}

我的应用程序发布在Amazon EC2上,而数据库则位于Amazon RDS中。RDS不支持DTC,因此我还需要一种方法来防止升级到DTC。顺便说一下,我正在使用SQL Server 2008 R2。我有两个数据库 - ASPNETDB、data DB。感谢Paul post的帮助!

2
Enlist=false 不使用 Transaction 吗? - PreguntonCojoneroCabrón

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