Транзакция с чистой точечной сетью

Я хотел бы запустить несколько операторов вставки для нескольких таблиц. Я использую dapper.net. Я не вижу способа обрабатывать транзакции с dapper.net.

Пожалуйста, поделитесь своими идеями о том, как использовать транзакции с dapper.net.

6 ответов

Решение

Вот фрагмент кода:

using System.Transactions;    
....    
using (var transactionScope = new TransactionScope())
{
    DoYourDapperWork();
    transactionScope.Complete();
}

Обратите внимание, что вам нужно добавить ссылку на System.Transactions сборка, потому что на нее нет ссылок по умолчанию.

Я предпочел использовать более интуитивный подход, получая транзакцию непосредственно из соединения:

// This called method will get a connection, and open it if it's not yet open.
using (var connection = GetOpenConnection())
using (var transaction = connection.BeginTransaction())
{
    connection.Execute(
        "INSERT INTO data(Foo, Bar) values (@Foo, @Bar);", listOf5000Items, transaction);
    transaction.Commit();
}

В Dapper есть 3 подхода к выполнению транзакций.

  1. Простая транзакция
  2. Транзакция из области транзакции
  3. Использование Dapper Transaction ( и наиболее предпочтительный подход)

Вы можете узнать больше об этих подходах к транзакциям на официальном веб-сайте руководства здесь.

Для справки вот разбивка подходов к транзакциям

1. Простая транзакция

В этом примере вы создаете транзакцию в существующем соединении с базой данных, а затем передаете транзакцию методу Execute на dapper (который является необязательным параметром).

Выполнив всю свою работу, просто зафиксируйте транзакцию.

      string sql = "INSERT INTO Customers (CustomerName) Values (@CustomerName);";

using (var connection = new SqlConnection(FiddleHelper.GetConnectionStringSqlServerW3Schools()))
{
    connection.Open();
    
    using (var transaction = connection.BeginTransaction())
    {
        connection.Execute(sql, new {CustomerName = "Mark"}, transaction: transaction);
        connection.Execute(sql, new {CustomerName = "Sam"}, transaction: transaction);
        connection.Execute(sql, new {CustomerName = "John"}, transaction: transaction);
        
        transaction.Commit();
    }
}

2. Транзакция из области транзакции

Если вы хотите создать область транзакции, вам нужно будет сделать это до создания соединения с базой данных. После того, как вы создали область транзакции, вы можете просто выполнить все свои операции, а затем выполнить один вызов для завершения транзакции, которая затем зафиксирует все команды.

      using (var transaction = new TransactionScope())
{
    var sql = "INSERT INTO Customers (CustomerName) Values (@CustomerName);";

    using (var connection = My.ConnectionFactory())
    {
        connection.Open();

        connection.Execute(sql, new {CustomerName = "Mark"});
        connection.Execute(sql, new {CustomerName = "Sam"});
        connection.Execute(sql, new {CustomerName = "John"});
    }

    transaction.Complete();
}

3. Использование Dapper Transaction

Это наиболее благоприятный подход для выполнения транзакции в коде, поскольку он упрощает чтение и реализацию кода. Существует расширенная реализация транзакции SQL под названием Dapper Transaction (которую вы можете найти дополнительный пакет nugetздесь ), которая позволяет вам запускать SQL, выполняемый непосредственно из транзакций.

      string sql = "INSERT INTO Customers (CustomerName) Values (@CustomerName);";

using (var connection = new SqlConnection(FiddleHelper.GetConnectionStringSqlServerW3Schools()))
{
    connection.Open();
    
    using (var transaction = connection.BeginTransaction())
    {
        transaction.Execute(sql, new {CustomerName = "Mark"});
        transaction.Execute(sql, new {CustomerName = "Sam"});
        transaction.Execute(sql, new {CustomerName = "John"});

        transaction.Commit();
    }
}

Вы должны быть в состоянии использовать TransactionScope так как Dapper запускает только команды ADO.NET.

using (var scope = new TransactionScope())
{
   // insert
   // insert
   scope.Complete();
}

Учитывая, что все ваши таблицы находятся в одной базе данных, я не согласен с TransactionScope Решение предлагается в некоторых ответах здесь. Ссылайтесь на этот ответ.

  1. TransactionScope обычно используется для распределенных транзакций; транзакции, охватывающие разные базы данных, могут находиться в разных системах. Для этого нужны некоторые конфигурации в операционной системе и SQL Server, без которых это не будет работать. Это не рекомендуется, если все ваши запросы относятся к одному экземпляру базы данных.
    Но с одной базой данных это может быть полезно, когда вам нужно включить код в транзакцию, которая не находится под вашим контролем. С единой базой данных она также не требует специальных настроек.

  2. connection.BeginTransaction является синтаксисом ADO.NET для реализации транзакции (в C#, VB.NET и т. д.) для одной базы данных Это не работает в нескольких базах данных.

Так, connection.BeginTransaction() это лучший способ пойти.

Даже лучший способ обработать транзакцию - реализовать UnitOfWork, как описано в этом ответе.

Ответ Даниэля сработал, как и ожидалось для меня. Для полноты приведем фрагмент, демонстрирующий фиксацию и откат с использованием области транзакции и dapper:

using System.Transactions;
    // _sqlConnection has been opened elsewhere in preceeding code 
    using (var transactionScope = new TransactionScope())
    {
        try
        {
            long result = _sqlConnection.ExecuteScalar<long>(sqlString, new {Param1 = 1, Param2 = "string"});

            transactionScope.Complete();
        }
        catch (Exception exception)
        {
            // Logger initialized elsewhere in code
            _logger.Error(exception, $"Error encountered whilst executing  SQL: {sqlString}, Message: {exception.Message}")

            // re-throw to let the caller know
            throw;
        }
    } // This is where Dispose is called 
Другие вопросы по тегам