Como usar um único SqlTransaction para vários SqlConnections em .NET?
-
03-07-2019 - |
Pergunta
- Eu tenho SQL Server 2000, não suporta MultipleActiveResults .
- Eu tenho que fazer várias inserções, e é feito com uma conexão por inserção.
- Eu quero iniciar uma transação antes de todas as inserções e terminá-lo depois de todas as inserções.
- Como posso fazê-lo?
Solução
O que é a razão que você não use uma conexão e comandos múltiplas (na verdade um comando recriado em circuito)? Talvez esta solução irá trabalhar para você:
public static void CommandExecNonQuery(SqlCommand cmd,
string query, SqlParameter[] prms)
{
cmd.CommandText = query;
cmd.Parameters.AddRange(prms);
cmd.ExecuteNonQuery();
cmd.Parameters.Clear();
}
static void Main(string[] args)
{
string insertQuery =
@"INSERT TESTTABLE (COLUMN1, COLUMN2) " +
"VALUES(@ParamCol1, @ParamCol2)";
using (SqlConnection connection =
new SqlConnection(connectionString))
{
using (SqlCommand command =
connection.CreateCommand())
{
SqlTransaction transaction = null;
try
{
// BeginTransaction() Requires Open Connection
connection.Open();
transaction = connection.BeginTransaction();
// Assign Transaction to Command
command.Transaction = transaction;
for (int i = 0; i < 100; i++)
CommandExecNonQuery(command, insertQuery,
new SqlParameter[] {
new SqlParameter("@ParamCol1", i),
new SqlParameter("@ParamCol2", i.ToString()) });
transaction.Commit();
}
catch
{
transaction.Rollback();
throw;
}
finally
{
connection.Close();
}
}
}
}
Veja também
SQL Server Transações - ADO.NET 2.0 - Commit e Rollback - Usando declaração - IDisposable
Outras dicas
Você não especificou se você estiver usando o .NET 2.0, mas eu vou fazer essa suposição. C # 3.0 código de amostra é listado abaixo:
using (var tx = new TransactionScope()) {
// Execute multiple DB statements inside here
ts.Complete();
}
Se alguma das declarações DB falhar, o ts.complete nunca será alcançada e a transação será revertida automaticamente no final da instrução using. No entanto, uma ressalva a esta abordagem é que você vai acabar aproveitando o DTC se você usar várias conexões, o que significa um desempenho mais lento.
editado para mudar SqlTransaction para TransactionScope
Um exemplo de forçar uma única conexão SQL para evitar o uso do DTC:
using (var tx = new TransactionScope())
using (var db = new SqlConnection(connString)) {
// Command 1
using (var cmd = db.CreateCommand()) {
cmd.CommandText = "select...";
using (var reader = cmd.ExecuteReader()) {
// Process results or store them somewhere for later
}
}
// Command 2
using (var cmd = db.CreateCommand()) {
cmd.CommandText = "select...";
using (var reader = cmd.ExecuteReader()) {
// Process results or store them somewhere for later
}
}
// Command 3
using (var cmd = db.CreateCommand()) {
cmd.CommandText = "select...";
using (var reader = cmd.ExecuteReader()) {
// Process results or store them somewhere for later
}
}
tx.Complete();
}
Transações são criadas em uma conexão e não têm escopo para além da conexão que eles são criados em que você não pode fazer o que você está pedindo. Refactor para que você possa executar as inserções sequencialmente em uma conexão em vez de simultaneamente ou implementar um mecanismo diferente para conseguir o desmantelamento (por exemplo, uma tabela de chaves inseridas que pode ser usado como um olhar-se para apagar registros inseridos, se for encontrado um erro no final do processo)
Eu não acho que uma transação pode abranger várias conexões.
Qual é o raciocínio para fazer as várias inserções em conexões separadas? Eu acho que você quer que eles em uma única conexão normalmente.