【问题标题】:Database Transaction with two Databases - is this method correct?具有两个数据库的数据库事务 - 这种方法是否正确?
【发布时间】:2013-09-09 07:32:01
【问题描述】:

我有 2 个数据库。

经理有公司表,基于这个值我必须创建一个新的数据库。

所以我正在使用 TransactionScope。我想知道以下是否正确?

这会回滚这两个更改吗?在两个数据库中是否发生错误?

using (TransactionScope ts = new TransactionScope())
{
    try
    {
        using(var ManagerContext = new ManagerEntities(
            ConnectionStringManager.GetManagerConnectionString()))
        {
            //Operations on Manager DB                         
            // Create new Company and get NEWCOMPANYID 
            // -- Used to create new DB
        }

        using(var companyContext = new CompanyEntities(
            ConnectionStringManager.GetCompanyConnectionString(
                NEWCOMPANYID.ToString())))
        {
            //Create New Company DB
        }

        ts.Complete();
    }
    catch (Exception ex)
    {
        ts.Dispose();
    }
}

【问题讨论】:

  • try-catch 是多余的,因为using 语句已经确保了TransactionScope 的处置。
  • 我不明白你的意思。如果 try{} 块中发生任何错误,我已经执行 ts.Dispose()
  • 如果分布式事务协调器被激活,这将起作用(例如,参见luisrocha.net/2011/08/managing-transactions-with-entity.html
  • @Matten 即使我使用两个单独的 DbContext 范围,我也必须激活分布式事务?
  • @DawoodAwan 不,你不需要Dispose() - 这正是using 所做的:它设置了一个try/finally,在ts 上调用Dispose() (如果它不为空)。

标签: c# database entity-framework transactions transactionscope


【解决方案1】:

只要这两个数据库上下文都知道TransactionScope,并且没有明确禁用环境事务登记(例如在连接字符串中),那么可以:应该可以正常工作。如果我们假设两个连接字符串不同,这肯定需要分布式事务 (DTC),不过 - 是否可以由您决定。如果连接字符串相同,您可能会改用 LTM(更少的开销/配置)。

请注意,根据 cmets - 您不需要 try/finally

【讨论】:

  • 您是否获得了有关如何为 Windows Server 2008 R2 激活 DTC 的分步教程的链接?
  • @Dawood 不,但谷歌可能会
  • 最后一个问题。 TransactionScopr Rollbak,在 Scope 中执行的 T-SQL 脚本。例如我有一个 T-SQL 脚本来生成表和存储过程,如果该脚本失败,它会回滚所有这些吗?
  • @DawoodAwan 是的,TransactionScope 在调用 Complete() 之前被处理,这算作回滚。根据我的回答中的警告 - 是的,只要连接没有明确选择退出环境事务,就会回滚数据库状态。请注意,有些事情不能回滚(例如xp_sendmail
  • 嗯嗯嗯。谢谢您的帮助。这真的帮助了我。现在我想我可以实现我想做的事情了。
【解决方案2】:

这没关系,虽然它会触发 DTC,正如 Marc 所解释的那样。您可以通过使用两个上下文共享的单个SqlConnection(或EntityConnection)来避免 DTC。您可以使用ChangeDatabase 切换连接的当前数据库。这避免了分布式事务的需要。

您还需要显式打开连接,因为默认情况下 EF 会为每个操作打开并关闭它。这会导致多个 DTC 登记(超过 2 个)。这是 EF 的设计缺陷。

【讨论】:

  • 听起来 LTM(而不是 DTC)应该仍然可以在那种情况下使用。但是,我不打算尝试检查
  • 我发现您是否需要 DTC 是不确定的。如果第二个连接恰好与第一个连接是相同的底层池连接,则不需要 DTC。如果它碰巧不同,它会触发 DTC。您通常只会在生产中的负载下发现该错误。糟糕的设计选择。
猜你喜欢
  • 2014-04-29
  • 2015-02-15
  • 2015-09-16
  • 2011-03-20
  • 2021-07-23
  • 1970-01-01
  • 2014-06-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多