c#在TransactionScope事务中获取当前连接

时间:2010-09-15 15:11:19

标签: c# .net sql-server-2005 transactions transactionscope

我想在一个带有

的业务逻辑的.net 2.0项目中进行事务性的一系列sp调用(sql server 2005)
using(TransactionScope...)

不幸的是,我从另一个项目继承了DAL,我不想在那里做很多改动。问题是每个调用存储过程的方法都会打开一个新的连接。

所以,我的问题是:有没有办法检索当前事务使用的连接,即来自Transaction.Current ??

谢谢

更新:请告诉我这个控制台应用程序有什么问题(vs2005,.net 2.0,Sql server 2005)

using System;
using System.Collections.Generic;
using System.Text;
using System.Data.SqlClient;
using System.Data;
using System.Transactions;

namespace ConsoleApplication1
{
    public class Program
    {
        static void Main(string[] args)
        {
            using (TransactionScope ts = new TransactionScope(TransactionScopeOption.Required))
            {
                Console.WriteLine("1");
                test();
                Console.WriteLine("2");
                test();
            }
            Console.WriteLine("END");
        }

        public static void test()
        {
            string connectionString = @"Persist Security Info=True;User ID=usr123;Password=123;Initial Catalog=db123;Data Source=myserver\myinstance;Connect Timeout=180;";

            using (SqlConnection conn = new SqlConnection(connectionString))
            {
                conn.Open();
            }
        }
    }
}

3 个答案:

答案 0 :(得分:1)

好的,有几件事:

  1. 我怀疑TransactionScope甚至有(Sql)连接的概念。原因是它可以与各种事务资源一起使用,无论是dabatabase,消息排队系统还是其他任何事务资源。您可能需要参考MSDN Docs for System.Transactions以获取更多信息。所以,我猜你的方法注定要失败。

  2. 在您的示例中,您错过了“ts.Complete()”调用,因此当using-Scope结束时,您的(分布式)事务将始终回滚。现在,这与你所描述的问题无关,但值得指出。

  3. 您的环境事务(由TransactionScope实例类似的环境事务)将传播到分布式事务,因为您在其中使用了多个连接。基本上,系统上的DTC需要与数据库服务器上的DTC通信。为了实现这一点,必须正确配置。

  4. 要通过执行C:\Windows\System32\com\comexp.msc配置DTC,请运行“组件服务”管理控制台。在树视图中,导航到“组件服务\计算机\我的计算机”。在上下文菜单中打开“属性”。在“属性”对话框中,选择“MSDTC”选项卡,单击“安全配置...”按钮。

    在对话框中确保选择以下选项:

    • “网络DTC访问”
    • “允许远程客户端”
    • “允许入境”
    • “允许出站”
    • “启用交易互联网协议(TIP)交易”
    • “启用XA交易”

    (注意:其中一些可能实际上不是必需的,YMMV)

    您可能还希望设置为“无需身份验证”,具体取决于您当地的政策/要求。

    您需要在两个系统上执行此操作:运行应用程序的系统和带有数据库的系统。

答案 1 :(得分:1)

好的,谢谢大家... ..最后我写完了类似你可以在企业库(http://entlib.codeplex.com)中找到的Microsoft.Practices.EnterpriseLibrary.Data.TransactionScopeConnections。

答案 2 :(得分:0)

除非你因为某些原因没有使用连接池,否则没有理由不新建一个SqlConnection并进入城镇。让运行时处理制作该性能的细节 - 这就是连接池的用途。听起来DAL写得正确:

...
using (var conn = new SqlConnection("connection string"))
{
    using (var cmd = conn.CreateCommand())
    {
        conn.Open();
        //Do stuff with cmd
    }
}
....

即使您没有使用连接池(并且您有正当理由不这样做),最好的路径可能仍然是新建一个SqlConnection并转到城镇。您不希望意外地执行诸如关闭事务范围正在使用的连接之类的事情,并且假设它实际上有一个SqlConnection供您引用。