C# 具有两个数据库的数据库事务-此方法正确吗?

C# 具有两个数据库的数据库事务-此方法正确吗?,c#,database,entity-framework,transactions,transactionscope,C#,Database,Entity Framework,Transactions,Transactionscope,我有一个情况,我有两个数据库 经理有公司表,根据这个值我必须创建一个新的数据库 所以我使用TransactionScope。我想知道以下是正确的吗 这会回滚这两个更改吗?在两个数据库中,是否发生错误 using (TransactionScope ts = new TransactionScope()) { try { using(var ManagerContext = new ManagerEntities( ConnectionStr

我有一个情况,我有两个数据库

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

所以我使用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();
    }
}

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


请注意,根据注释-您不需要使用
try
/
finally

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


请注意,根据注释-您不需要
尝试
/
最终

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


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

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



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

try catch是多余的,因为
using
语句已经确保了
TransactionScope
的处理。我不明白你的意思。如果try{}块中发生任何错误,我必须执行ts.Dispose()。如果分布式事务协调器被激活(例如,请参见)@Matten,则该操作将有效。即使我使用两个单独的DbContext作用域,我也必须激活分布式事务?@DawoodAwan否,您不需要
Dispose()
-这正是
using
所做的:它设置了一个
try
/
finally
,在
ts
上调用
Dispose()
(如果它是非空的)。try catch是多余的,因为
using
语句已经确保了
TransactionScope
的处理。我不明白你的意思。如果try{}块中发生任何错误,我必须执行ts.Dispose()。如果分布式事务协调器被激活(例如,请参见)@Matten,则该操作将有效。即使我使用两个单独的DbContext作用域,我也必须激活分布式事务?@DawoodAwan否,您不需要
Dispose()
-这正是
使用
所要做的:它设置了一个
try
/
finally
,在
ts
上调用
Dispose()
(如果它不为空)。你有一个关于如何为Windows Server 2008 R2激活DTC的分步教程的链接吗?@Dawood没有,但谷歌可能没有最后一个问题。在作用域中执行的TransactionScopr Rollbak、T-SQL脚本。e、 g.我有一个生成表和存储过程的T-SQL脚本,如果该脚本失败,它会返回所有这些吗?@DawoodAwan是的,它在调用
Complete()
之前处理
TransactionScope
,这算是回滚。根据我回答中的警告——是的,只要连接没有明确选择退出环境事务,就会回滚数据库状态。请注意,有些内容无法回滚(例如,
xp\u sendmail
)hmmmmm。谢谢你的帮助。这真的帮助了我。现在我想我可以实现我想做的事情了。你有一个关于如何激活WindowsServer2008R2的DTC的分步教程的链接吗?@Dawood没有,但谷歌可能会回答最后一个问题。在作用域中执行的TransactionScopr Rollbak、T-SQL脚本。e、 g.我有一个生成表和存储过程的T-SQL脚本,如果该脚本失败,它会返回所有这些吗?@DawoodAwan是的,它在调用
Complete()
之前处理
TransactionScope
,这算是回滚。根据我回答中的警告——是的,只要连接没有明确选择退出环境事务,就会回滚数据库状态。请注意,有些内容无法回滚(例如,
xp\u sendmail
)hmmmmm。谢谢你的帮助。这真的帮助了我。现在我想我可以实现我想做的事情了。听起来LTM(而不是DTC)应该仍然可以在那个场景中使用。然而,我不打算尝试检查,我发现您是否需要DTC是不确定的。如果第二个连接恰好与第一个连接是相同的基础池连接,则不需要DTC。如果恰好不同,则会触发DTC。您通常只会在生产负载下发现该错误。糟糕的设计选择。听起来像是李