Connection.BeginTransaction()与SQL开始事务是否不同?

时间:2019-03-17 15:42:55

标签: c# sql-server

今天有人说C#connection.BeginTransaction()与T-SQL的begin transaction不同,所以我对其进行了测试,结果似乎是正确的。

使用connection.BeginTransaction()的C#代码:

using (var connection = Connection)
{
    connection.Open();
    var cmd = connection.CreateCommand();
    cmd.CommandText = "create table #TransactionTest ([ID] int);";
    cmd.ExecuteNonQuery();
    cmd.CommandText = "insert into #TransactionTest ([ID]) values (1);";
    cmd.ExecuteNonQuery();

    using (var transaction = connection.BeginTransaction())
    {
        cmd.CommandText = "insert into #TransactionTest ([ID]) values (1);";
        cmd.Transaction = transaction;
        cmd.ExecuteNonQuery();

        transaction.Rollback();
    }

    cmd.CommandText = "select count(1) from #TransactionTest";
    var count = cmd.ExecuteScalar(); //result : 0 count
}

使用T-SQL Begin Transaction的C#代码:

using (var connection = Connection)
{
    connection.Open();
    var cmd = connection.CreateCommand();
    cmd.CommandText = "create table #TransactionTest ([ID] int);";
    cmd.ExecuteNonQuery();
    cmd.CommandText = "insert into #TransactionTest ([ID]) values (1);";
    cmd.ExecuteNonQuery();

    cmd.CommandText = "begin transaction;";
    cmd.ExecuteNonQuery();
    cmd.CommandText = "insert into #TransactionTest ([ID]) values (1);";
    cmd.ExecuteNonQuery();
    cmd.CommandText = "rollback;";
    cmd.ExecuteNonQuery();

    cmd.CommandText = "select count(1) from #TransactionTest";
    var count = cmd.ExecuteScalar(); //result : 0 count
}

在我看来,这种逻辑等效于以下SQL:

create table #TransactionTest ([ID] int, [Value] varchar(32));

begin transaction;
    insert into #TransactionTest ([ID], [Value]) 
    values (1, 'ABC');

    rollback transaction ;

    insert into #TransactionTest ([ID]) 
    values (1); 

    select * from #TransactionTest; 

我发现使用SQL Server Profiler和C#connection.BeginTransaction进行调整时,没有开始事务操作

20190317231252-image.png

但是找到了C#sql BeginTransaction 20190318002252-image.png

问题:

它是真实的,还是只是隐藏在数据库中?

1 个答案:

答案 0 :(得分:1)

由于在.NET中实现事务的方式存在很大差异,尽管在许多情况下(例如您的示例中),它们似乎起着相同的作用。

  • SQL Server中的事务将根据需要自动升级。 ADO.NET事务不会。
  • ADO.NET不允许并行 事务,即使启用了多个结果集也是如此。
  • ADO.NET 事务绑定到Connection对象,这很明显 代码,但很容易使人们感到困惑:
var transaction = connection.BeginTransaction()
  • 为什么令人困惑?因为Command对象也绑定到Connection,但是Connection中的事务并不等同于其Command对象中的事务。
    • 示例:使用已启动事务的Connection,用它​​创建一个新的Command并尝试执行。除非您将事务显式提供给新的Command对象,否则它将失败。

根据最佳做法,我发现以下情况是正确的:

  • 存储过程是避免必要交易时出现问题的最佳方法
  • 应避免在事务中具有DDL(即使临时表也是如此)。 SQL Server会允许它,但是Oracle等其他数据库则不允许。

您可以在MS文档here.

中了解更多信息。