在 TransactionScope 中优先使用 Oracle 的.NET 驱动

  • 王翔

2007 年 12 月 31 日

话题:.NETOracleDevOps语言 & 开发架构

分布式事务(DTx:Distributed Transaction)一直是大型应用所需的必要特性,由于需要同时协调不同的数据源(例如:数据库、队列、甚至注册表和新一代操作系统的 I/O),因此启动 DTx 的代价相对较大,而且很多中间件服务器的 DTx 协调器与应用位于不同的进程中,因此对于频繁提交的 OLTP 操作而言性能影响较大。

.NET Framework 2.0 开始默认提供 ORACLE 的 ADO.NET 驱动,虽然也支持通过 TransactionScope 隐式启动 DTx,但却采用应用宿主进程外的 dllhost.exe 作为独立的 DTx 协调器(DTC)。ORACLE 在自己的 ADO.NET 驱动中对该问题进行了显著优化,不仅对反复打开的连接提供了默认的连接池引用重定向,而且把 DTx 的协调工作置于.NET CLR 与应用宿主内部,对于大型应用而言可以有效的减少因跨多进程协调引发的性能损失。

下面的示例代码采用 ORACLE 的 ADO.NET 驱动(using Oracle.DataAccess.Client)运行,从 COM+ 的统计看并不会引起 DTC 调用,而如果换成微软的 ORACLE ADO.NET 驱动(using System.Data.OracleClient),就需要启动昂贵的 DTC 服务。

private const string ConnectionString = "Data Source = localhost:1521/XE; User ID = scott; Password = tiger";

private const string SqlConnectionString = "Data Source = (local); Initial Catalog = Northwind; Integrated Security = SSPI";

[TestMethod]

public void TestOracleDriver()

{

     using (TransactionScope scope = new TransactionScope())

     {

        Oracle.DataAccess.Client.OracleConnection connection = new Oracle.DataAccess.Client.OracleConnection(ConnectionString);

        connection.Open();

        Oracle.DataAccess.Client.OracleCommand command = connection.CreateCommand();

        command.CommandText = "UPDATE DEPT SET DNAME = DNAME";

        command.CommandType = CommandType.Text;

        command.ExecuteNonQuery();

        // 为了模拟一个分布式数据的操作,下面还增加了一段 SqlConnection 的 DML 操作。

        SqlConnection sqlC = new SqlConnection(SqlConnectionString);

        sqlC.Open();

        SqlCommand sComm = sqlC.CreateCommand();

        sComm.CommandText = "UPDATE Products SET ProductName = ProductName";

        sComm.CommandType = CommandType.Text;

        sComm.ExecuteNonQuery();

        scope.Complete();

    }

}

[TestMethod]



public void TestMicrosoftDriver()

{

    using (TransactionScope scope = new TransactionScope())

    {

        System.Data.OracleClient.OracleConnection connection = new System.Data.OracleClient.OracleConnection(ConnectionString);

        connection.Open();

        System.Data.OracleClient.OracleCommand command = connection.CreateCommand();

        command.CommandText = "UPDATE DEPT SET DNAME = DNAME";

        command.CommandType = CommandType.Text;

        command.ExecuteNonQuery();

        // 为了模拟一个分布式数据的操作,下面还增加了一段 SqlConnection 的 DML 操作。

        SqlConnection sqlC = new SqlConnection(SqlConnectionString);

        sqlC.Open();

        SqlCommand sComm = sqlC.CreateCommand();

        sComm.CommandText = "UPDATE Products SET ProductName = ProductName";

        sComm.CommandType = CommandType.Text;

        sComm.ExecuteNonQuery();

        scope.Complete();

    }

}

.NETOracleDevOps语言 & 开发架构