代码之家  ›  专栏  ›  技术社区  ›  Wei Lin

C connection.beginTransaction()与SQL BEGIN TRANSACTION不同?

  •  0
  • Wei Lin  · 技术社区  · 6 年前

    今天有人说C# connection.BeginTransaction() 与t-sql不同 begin transaction ,所以我测试了一下,结果似乎是真的。

    C代码使用 连接.BeginTransaction() :

    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的c代码 Begin Transaction :

    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

    问题:

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

    0 回复  |  直到 6 年前
        1
  •  1
  •   Todd Copeland    6 年前

    由于在.NET中实现事务的方式不同,它们之间存在显著差异,尽管在许多情况下(如您的示例中),它们的行为似乎相同。

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

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

    • 当需要事务时,存储过程是避免问题的最佳方法
    • 应该避免在事务中使用ddl(即使是临时表)。SQL Server将允许它,但Oracle等其他数据库则不允许。

    您可以在ms文档中阅读更多关于它的信息 here.