Отличается ли Connection.BeginTransaction () от SQL начальная транзакция? - PullRequest
0 голосов
/ 17 марта 2019

Сегодня кто-то сказал, что C # connection.BeginTransaction() отличается от begin transaction в T-SQL, поэтому я проверил его, и результат оказался верным.

Код C # с использованием connection.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
}

код C # с использованием T-SQL 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

Вопрос:

Это реально или просто скрыто от базы данных?

1 Ответ

1 голос
/ 17 марта 2019

Существуют значительные различия из-за того, как транзакции реализуются в .NET, хотя во многих случаях (как в вашем примере) они выглядят одинаково.

  • Транзакции в SQL Server будут автоматически продвигаться по мере необходимости. Транзакций ADO.NET не будет.
  • ADO.NET не разрешит параллельное транзакции, даже если включены несколько наборов результатов.
  • ADO.NET транзакции связаны с объектом Connection, что очевидно в код, но легко запутывает людей:
var transaction = connection.BeginTransaction()
  • Почему это сбивает с толку? Потому что объекты Command также связаны с Connection, но транзакция в Connection не приравнивается к транзакции в его объектах Command.
    • Пример. Возьмите ваше Соединение, в котором запущена транзакция, создайте с ним новую Команду и попробуйте выполнить. Он не будет выполнен, если вы явно не предоставите транзакцию новому объекту Command.

В соответствии с передовой практикой я обнаружил следующее:

  • Хранимые процедуры - лучший способ избежать проблем, когда необходимы транзакции
  • Следует избегать использования DDL (даже для временных таблиц) в транзакции. SQL Server разрешит это, но другие базы данных, такие как Oracle, не разрешат.

Подробнее об этом вы можете прочитать в документации MS здесь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...