Я хотел бы запустить несколько операторов вставки в нескольких таблицах. Я использую dapper.net. Я не вижу способа обрабатывать транзакции с dapper.net.
Поделитесь своими идеями о том, как использовать транзакции с dapper.net.
Я хотел бы запустить несколько операторов вставки в нескольких таблицах. Я использую dapper.net. Я не вижу способа обрабатывать транзакции с dapper.net.
Поделитесь своими идеями о том, как использовать транзакции с dapper.net.
Вот фрагмент кода:
using System.Transactions;
....
using (var transactionScope = new TransactionScope())
{
DoYourDapperWork();
transactionScope.Complete();
}
Обратите внимание, что вам нужно добавить ссылку на сборку System.Transactions
, потому что по умолчанию на нее нет ссылки.
Dispose()
. Если Complete()
не был вызван, транзакция откатывается.
- person the_joric; 04.10.2017
TransctionScope
используя блок, если вы выберете этот ответ.
- person 0x49D1; 08.06.2018
Я предпочел использовать более интуитивный подход, получая транзакцию непосредственно из соединения:
// 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();
}
.BeginTransaction()
? Если бы это было так, этот метод расширения способствовал бы неправильному использованию транзакции. (IMO, он должен даже бросить не удается открыть транзакцию после того, как соединение уже открыто.)
- person ANeves thinks SE is evil; 23.11.2015
Execute
, так как это необходимо.
- person Arve Systad; 14.06.2017
Вы должны иметь возможность использовать TransactionScope
, поскольку Dapper выполняет только команды ADO.NET.
using (var scope = new TransactionScope())
{
// open connection
// insert
// insert
scope.Complete();
}
Учитывая, что все ваши таблицы находятся в единой базе данных, я не согласен с решением TransactionScope
, предложенным в некоторых ответах здесь. См. этот ответ.
TransactionScope
обычно используется для распределенных транзакций; транзакция, охватывающая разные базы данных, может находиться в другой системе. Для этого требуются некоторые настройки операционной системы и SQL Server, без которых это не будет работать. Это не рекомендуется, если все ваши запросы относятся к одному экземпляру базы данных.
Но с одной базой данных это может быть полезно, когда вам нужно включить код в транзакцию, которая не находится под вашим контролем. При единой базе данных не требуется особых настроек.
connection.BeginTransaction
- это синтаксис ADO.NET для реализации транзакции (в C #, VB.NET и т. Д.) С единой базой данных. Это не работает с несколькими базами данных.
Итак, connection.BeginTransaction()
- лучший способ пойти.
Даже лучший способ обработки транзакции - это реализовать UnitOfWork, как описано в этом ответе.
TransactionScope
, что неэффективно для того, что хочет OP. Я согласен, что TransactionScope
- хороший инструмент во многих случаях; но не это.
- person Amit Joshi; 15.11.2017
Ответ Дэниела сработал для меня, как и ожидалось. Для полноты, вот фрагмент, который демонстрирует фиксацию и откат с использованием области транзакции и 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
Dispose
вызывается первым или вторым, просто он вызывается дважды. Что касается того, что повторный вызов dispose не вреден, это большое предположение. Я узнал, что документы и фактические реализации часто не совпадают. Но если вам нужны слова Microsoft: msdn. microsoft.com/en-us/library/
- person CodeNaked; 24.08.2016
В Dapper есть 3 подхода к выполнению транзакций.
Вы можете узнать больше об этих подходах к транзакциям на официальном веб-сайте руководства здесь
Для справки вот разбивка подходов к транзакциям
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 (которую вы можете найти здесь ), что позволяет запускать 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();
}
}