【问题标题】:Transaction on two DB两个数据库上的事务
【发布时间】:2013-04-22 20:52:53
【问题描述】:

我想知道我该如何处理这种情况,如果有人可以帮助我,我将不胜感激!

我为注册和角色用户等使用一个数据库。我还为一个用户的所有数据使用另一个数据库。我只有一个数据库供所有用户使用,但我为每个用户提供一个数据库来存储他的数据。 当我创建用户时,我会在 UserDB 和 UserData 上插入数据。我正在使用会员 api 进行注册。

我想知道如何使用事务来检查所有数据是否正确插入(第一次创建用户时)。

例如:

我注册了一个用户(为我的 UserDB 上的每个表创建一行)。 我在他的 Data DB 的一个表中为该用户创建了一个包含主要信息的数据库。

如果我可以在 Data DB 上插入,我如何回滚事务?

【问题讨论】:

  • 使用分布式事务(必须开启 DTC)。如果是同一台服务器,可能不需要 DTC,只需 BEGIN a Transaction...
  • 我想你会发现this这个答案很有用:你可以在多台服务器上管理一个事务。
  • 我不能使用分布式事务,因为我使用的是merbership api。
  • 顺便问一下DTC是什么?

标签: c# asp.net linq


【解决方案1】:

正如 cmets 中的其他人所指出的,您需要使用分布式事务来确保两个数据库事务在单个工作单元下进行(或者即使更新同一个数据库,因为成员资格将使用自己的连接,DTC仍然需要)。通过将您对ASP Net Membership API 和其他数据库连接(例如Linq2SQL 或实体框架)的调用包装在System.Transactions.TransactionScope 下,您可以确保您的更新是ACID。

请注意,您需要在应用服务器和两个数据库服务器上运行和配置 MS DTC。

下面是一个例子:

using (var ts = new TransactionScope())
{
    // Update Membership user   
    MembershipUser currentUser = Membership.GetUser(someUserId);    
    currentUser.Comment = "HairColor is changing";
    Membership.UpdateUser(currentUser);

    // Update equivalent record in other database (assumed EF Context and Same Primary Key)
    var otherUser = _db.OtherUserTable.Where(ut => ut.UserId == someUserId)
                                      .FirstOrDefault();
    otherUser.HairColor = "Orange";
    _db.SaveChanges();

    // Commit  
    ts.Complete();
}

需要注意TransactionScope 的一个警告是,默认隔离级别是Read Serializable,在许多情况下这可能是多余的——Read Committed 通常足以满足大多数情况。更多信息请看这里:Why is System.Transactions TransactionScope default Isolationlevel Serializable

【讨论】:

    猜你喜欢
    • 2014-06-07
    • 1970-01-01
    • 1970-01-01
    • 2012-03-17
    • 2021-06-20
    • 2012-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多