6

我将 EF5.0 与 SQL Server 2008 一起使用。我在同一个服务器实例上有两个数据库。我需要更新两个数据库上的表并希望它们是相同的事务。所以我使用了TransactionScope。下面是代码 -

public void Save()
{
        var MSObjectContext = ((IObjectContextAdapter)MSDataContext).ObjectContext;
        var AWObjectContext = ((IObjectContextAdapter)AwContext).ObjectContext;

        using (var scope = new TransactionScope(TransactionScopeOption.Required,
                                             new TransactionOptions
                                                 {
                                                     IsolationLevel = IsolationLevel.ReadUncommitted
                                                 }))
        {               
            MSObjectContext.SaveChanges(SaveOptions.DetectChangesBeforeSave);
            AWObjectContext.SaveChanges(SaveOptions.DetectChangesBeforeSave);

            scope.Complete();
        }
    }

当我使用上面的代码时,事务被提升为 DTC。在互联网上搜索后,我发现这是由于两个不同的连接字符串/连接而发生的。但我不明白的是,如果我在一个数据库上编写一个存储过程来更新不同数据库(在同一台服务器上)中的表,则不需要 DTC。那为什么 EF 或 TransactionScope 将这个推广到 DTC 呢?有没有其他解决方法?

请指教

提前致谢

4

1 回答 1

9

使用 plain DbConnections,您可以通过使用相同的连接字符串(使用您喜欢的任何数据库)来防止同一服务器上的多个数据库的 DTC 升级,并手动更改打开的连接对象上的数据库,如下所示:

using (var tx = new TransactionScope())
{
    using (var conn = new SqlConnection(connectStr))
    {
        conn.Open();
        new SqlCommand("INSERT INTO atest VALUES (1)", conn).ExecuteNonQuery();
    }
    using (var conn = new SqlConnection(connectStr))
    {
        conn.Open();
        conn.ChangeDatabase("OtherDB");
        new SqlCommand("INSERT INTO btest VALUES (2)", conn).ExecuteNonQuery();
    }
    tx.Complete();
}

这不会升级为 DTC,但如果您对connectStr.

我不熟悉 EF 以及它如何管理连接和上下文,但使用上述见解,您可以通过执行 aconn.ChangeDatabase(..)然后创建您的上下文(如new DbContext(conn, ...).

但请注意,即使使用共享连接字符串,只要您同时打开多个连接,DTC 就会参与进来,就像在这个修改后的示例中一样:

using (var tx = new TransactionScope())
{
    using (var conn = new SqlConnection(mssqldb))
    {
        conn.Open();
        new SqlCommand("INSERT INTO atest VALUES (1)", conn).ExecuteNonQuery();
        using (var conn2 = new SqlConnection(mssqldb))
        {
            conn2.Open();
            conn2.ChangeDatabase("otherdatabase");
            new SqlCommand("INSERT INTO btest VALUES (2)", conn2).ExecuteNonQuery();
        }
    }
    tx.Complete();
}
于 2013-10-11T08:01:25.527 回答