当我们在C#中使用事务时,通常需要以下几个步骤:
- 创建一个SqlConnection对象,并打开连接
- 创建一个SqlTransaction对象,并使用SqlConnection.BeginTransaction()方法开始一个事务
- 使用SqlCommand对象执行多个SQL语句,这几个语句都要在同一个事务中执行
- 在所有SQL语句执行完之后,使用SqlTransaction.Commit()方法提交事务
- 如果任何一个SQL语句执行失败,使用SqlTransaction.Rollback()方法回滚事务
下面我们来看两个使用事务的示例:
示例一
我们可以使用事务来在两个不同的表中插入数据,确保只有在插入两个表的数据都成功之后才会提交事务,否则就会回滚事务,抛出异常。
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
SqlTransaction transaction = connection.BeginTransaction();
try
{
SqlCommand command1 = new SqlCommand("INSERT INTO Table1 (column1, column2) VALUES (@value1, @value2)", connection);
command1.Parameters.AddWithValue("@value1", "Value1");
command1.Parameters.AddWithValue("@value2", "Value2");
command1.Transaction = transaction;
command1.ExecuteNonQuery();
SqlCommand command2 = new SqlCommand("INSERT INTO Table2 (column3, column4) VALUES (@value3, @value4)", connection);
command2.Parameters.AddWithValue("@value3", "Value3");
command2.Parameters.AddWithValue("@value4", "Value4");
command2.Transaction = transaction;
command2.ExecuteNonQuery();
transaction.Commit();
}
catch (Exception ex)
{
transaction.Rollback();
Console.WriteLine(ex.Message);
}
}
在这个示例中,我们创建了一个SqlConnection对象并打开了连接。然后我们使用SqlConnection.BeginTransaction()方法创建一个SqlTransaction对象,并在这个对象上执行多个SqlCommand对象。
在这个示例中,我们在Table1和Table2中插入了两组数据。只有当这两个INSERT语句都执行成功之后,我们才会使用SqlTransaction.Commit()方法提交事务。
如果任何一个INSERT语句执行失败,我们就会使用SqlTransaction.Rollback()方法回滚事务并打印异常信息。
示例二
我们也可以使用事务来实现一个原子更新操作,确保在多个线程同时尝试更新同一个数据时,只会有一个线程更新成功,而其他线程都会被阻塞。
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
SqlTransaction transaction = connection.BeginTransaction(IsolationLevel.Serializable);
try
{
SqlCommand command1 = new SqlCommand("SELECT * FROM Table WHERE Id = @id FOR UPDATE", connection);
command1.Parameters.AddWithValue("@id", id);
command1.Transaction = transaction;
SqlDataReader reader = command1.ExecuteReader();
if (reader.Read())
{
SqlCommand command2 = new SqlCommand("UPDATE Table SET Column1 = @value1 WHERE Id = @id", connection);
command2.Parameters.AddWithValue("@id", id);
command2.Parameters.AddWithValue("@value1", "NewValue");
command2.Transaction = transaction;
command2.ExecuteNonQuery();
}
reader.Close();
transaction.Commit();
}
catch (Exception ex)
{
transaction.Rollback();
Console.WriteLine(ex.Message);
}
}
在这个示例中,我们使用Serializable隔离级别来确保在多个线程更新同一个数据时,只会有一个线程可以成功更新。我们首先使用SqlCommand对象的FOR UPDATE选项来锁定数据行,确保其他线程无法更新这行数据。
然后我们使用SqlCommand对象执行更新操作,并在这个对象上设置SqlTransaction属性,确保这个更新操作是在同一个事务中执行的。
在所有操作执行完成之后,我们使用SqlTransaction.Commit()方法提交事务。
如果任何一个SQL语句执行失败,我们就会使用SqlTransaction.Rollback()方法回滚事务并打印异常信息。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:事务在c#中的使用 - Python技术站