Как использовать sqltransaction в C#
Я использую следующий код для выполнения двух команд одновременно. Я использовал sqltransaction, чтобы гарантировать выполнение или откат всех команд. Когда я запускаю свою программу без "транзакции", она запускается правильно, но когда я использую "транзакцию" с ними, они показывают ошибку. Мой код выглядит следующим образом;
SqlTransaction transaction = connectionsql.BeginTransaction();
try
{
SqlCommand cmd1 = new SqlCommand("select account_name from master_account where NOT account_name = 'BANK' AND NOT account_name = 'LOAN'", connectionsql);
SqlDataReader dr1 = cmd1.ExecuteReader();
while (dr1.Read())
{
comboBox1.Items.Add(dr1[0].ToString().Trim());
}
cmd1.Dispose();
dr1.Dispose();
SqlCommand cmd2 = new SqlCommand("select items from rate",connectionsql);
SqlDataReader dr2 = cmd2.ExecuteReader();
while (dr2.Read())
{
comboBox2.Items.Add(dr2[0].ToString().Trim());
}
cmd2.Dispose();
dr2.Dispose();
transaction.Commit();
dateTimePicker4.Value = dateTimePicker3.Value;
}
catch(Exception ex)
{
transaction.Rollback();
MessageBox.Show(ex.ToString());
}
и ошибка:
6 ответов
Вы должны указать своим объектам SQLCommand использовать транзакцию:
cmd1.Transaction = transaction;
или в конструкторе:
SqlCommand cmd1 = new SqlCommand("select...", connectionsql, transaction);
Убедитесь, что у вас также открыт объект connectionsql.
Но все, что вы делаете, это операторы SELECT. Транзакции выиграют больше, если вы используете действия типа INSERT, UPDATE и т. Д.
В следующем примере создаются SqlConnection и SqlTransaction. Здесь также показано, как использовать методы BeginTransaction, Commit и Rollback. Транзакция откатывается при любой ошибке или если она удаляется без предварительной фиксации. Обработка ошибок Try/Catch используется для обработки любых ошибок при попытке зафиксировать или откатить транзакцию.
private static void ExecuteSqlTransaction(string connectionString)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
SqlCommand command = connection.CreateCommand();
SqlTransaction transaction;
// Start a local transaction.
transaction = connection.BeginTransaction("SampleTransaction");
// Must assign both transaction object and connection
// to Command object for a pending local transaction
command.Connection = connection;
command.Transaction = transaction;
try
{
command.CommandText =
"Insert into Region (RegionID, RegionDescription) VALUES (100, 'Description')";
command.ExecuteNonQuery();
command.CommandText =
"Insert into Region (RegionID, RegionDescription) VALUES (101, 'Description')";
command.ExecuteNonQuery();
// Attempt to commit the transaction.
transaction.Commit();
Console.WriteLine("Both records are written to database.");
}
catch (Exception ex)
{
Console.WriteLine("Commit Exception Type: {0}", ex.GetType());
Console.WriteLine(" Message: {0}", ex.Message);
// Attempt to roll back the transaction.
try
{
transaction.Rollback();
}
catch (Exception ex2)
{
// This catch block will handle any errors that may have occurred
// on the server that would cause the rollback to fail, such as
// a closed connection.
Console.WriteLine("Rollback Exception Type: {0}", ex2.GetType());
Console.WriteLine(" Message: {0}", ex2.Message);
}
}
}
}
Смотрите класс SqlTransaction
Вы можете создать SqlTransaction
из SqlConnection
,
И использовать его для создания любого числа SqlCommands
SqlTransaction transaction = connection.BeginTransaction();
var cmd1 = new SqlCommand(command1Text, connection, transaction);
var cmd2 = new SqlCommand(command2Text, connection, transaction);
Или же
var cmd1 = new SqlCommand(command1Text, connection, connection.BeginTransaction());
var cmd2 = new SqlCommand(command2Text, connection, cmd1.Transaction);
Если сбой команд никогда не вызывает неожиданных изменений , не используйте транзакцию.
если сбой команд может привести к неожиданным изменениям, поместите их в блок Try/Catch и откатите операцию в другом блоке Try/Catch.
По данным MSDN:
Обработка исключенийTry/Catch всегда должна использоваться при откате транзакции. Откат генерирует
InvalidOperationException
если соединение разорвано или транзакция уже откатана на сервере.
Вот пример кода:
string connStr = "[connection string]";
string cmdTxt = "[t-sql command text]";
using (var conn = new SqlConnection(connStr))
{
conn.Open();
var cmd = new SqlCommand(cmdTxt, conn, conn.BeginTransaction());
try
{
cmd.ExecuteNonQuery();
//before this line, nothing has happened yet
cmd.Transaction.Commit();
}
catch(System.Exception ex)
{
//You should always use a Try/Catch for transaction's rollback
try
{
cmd.Transaction.Rollback();
}
catch(System.Exception ex2)
{
throw ex2;
}
throw ex;
}
conn.Close();
}
Транзакция откатывается в том случае, если она удаляется до вызова Commit или Rollback.
Так что вам не нужно беспокоиться о закрытии приложения.
Ну, я не понимаю, почему вы использовали транзакцию в случае, когда вы делаете select
,
Транзакция полезна при внесении изменений (добавление, редактирование или удаление) данных из базы данных.
Удалить транзакцию, если вы не используете insert
, update
или же delete
заявления
Обновить или удалить с помощью транзакции SQL
private void SQLTransaction() {
try {
string sConnectionString = "My Connection String";
string query = "UPDATE [dbo].[MyTable] SET ColumnName = '{0}' WHERE ID = {1}";
SqlConnection connection = new SqlConnection(sConnectionString);
SqlCommand command = connection.CreateCommand();
connection.Open();
SqlTransaction transaction = connection.BeginTransaction("");
command.Transaction = transaction;
try {
foreach(DataRow row in dt_MyData.Rows) {
command.CommandText = string.Format(query, row["ColumnName"].ToString(), row["ID"].ToString());
command.ExecuteNonQuery();
}
transaction.Commit();
} catch (Exception ex) {
transaction.Rollback();
MessageBox.Show(ex.Message, "Error");
}
} catch (Exception ex) {
MessageBox.Show("Problem connect to database.", "Error");
}
}
Во-первых, вам не нужна транзакция, поскольку вы просто запрашиваете операторы select, и, поскольку они оба являются операторами select, вы можете просто объединить их в один запрос, разделенный пробелом, и использовать набор данных для получения всех найденных таблиц. Это лучше, так как вы сделали только одну транзакцию с базой данных, потому что транзакции с базой данных дороги, а значит, ваш код быстрее. Второй из вас действительно должен использовать транзакцию, просто назначьте транзакцию для SqlCommand, как
sqlCommand.Transaction = transaction;
А также просто используйте один SqlCommand, не объявляйте более одного, так как переменные занимают место, и мы также находимся в теме повышения эффективности вашего кода, сделаем это, назначив commandText другой строке запроса и выполнив их следующим образом:
sqlCommand.CommandText = "select * from table1";
sqlCommand.ExecuteNonQuery();
sqlCommand.CommandText = "select * from table2";
sqlCommand.ExecuteNonQuery();