.net 事务处理的实现方法

事务类型:

   1,手动事务:用开始和结束事务的显式指令(BEGIN TRANSACTION 和 END TRANSACTION )控制事务边界。从一个事务边界内可以开始第二个被称为嵌套事务的事务。直到所有从属事务提交,其父事务才提交。

   2:自动事务:基于每个组件的声明特性集管理事务边界。事务自动流向被指示参与事务的对象,并跳过被指示在事务外部执行的对象。使用自动事务模型时无法嵌套事务。

分布式事务处理 (TP):分布式事务处理 (TP) 系统旨在协助在分布式环境中跨异类的事务识别资源的事务。

手动事务和 ADO.NET
SQL 客户端和 OLE DB .NET 提供程序在公共语言运行库中支持手动事务。在 ADO.NET 中,这两个 .NET 提供程序都可以用来控制事务。

应使用 ADO.NET 连接对象 Connection.BeginTransaction 开始本地事务。用 Command 对象的 Transaction 属性登记该事务中的命令。使用 Transaction 对象根据事务组件的成功或失败而提交或回滚在数据源做的修改。

登记在默认情况下是自动的,而且可以禁用。如果禁用了自动登记,您可以手动登记。在一个现有分布式事务中使用 Connection.EnlistDistributedTransaction 进行登记。

若要执行事务,请执行下列操作:

调用 Connection 对象的 BeginTransaction 方法来标记事务的开始。BeginTransaction 方法返回对 Transaction 的引用。该引用将分配给登记在事务中的 Command 对象。
将 Transaction 对象分配给要执行的 Command 的 Transaction 属性。如果通过活动的 Transaction 对象对 Connection 执行 Command,但该 Transaction 对象尚未分配给 Command 的 Transaction 属性,则将引发异常。
执行所需的命令。
调用 Transaction 对象的 Commit 方法来完成事务,或调用 Rollback 方法来取消事务。
myConnection.Open();

SqlTransaction myTrans = myConnection.BeginTransaction();

SqlCommand myCommand = myConnection.CreateCommand();
myCommand.Transaction = myTrans;

try
{
  myCommand.CommandText = "Insert into Region (RegionID, RegionDescription) VALUES (100, 'Description')";
  myCommand.ExecuteNonQuery();
  myCommand.CommandText = "Insert into Region (RegionID, RegionDescription) VALUES (101, 'Description')";
  myCommand.ExecuteNonQuery();
  myTrans.Commit();
  Console.WriteLine("Both records are written to database.");
}
catch(Exception e)
{
  try
  {
    myTrans.Rollback();
  }
  catch (SqlException ex)
  {
    if (myTrans.Connection != null)
    {
      Console.WriteLine("An exception of type " + ex.GetType() +
                        " was encountered while attempting to roll back the transaction.");
    }
  }


分布事务:

如果 Connection 对象确定事务是活动的,它将自动登记在现有的分布式事务中。当打开连接或从连接池中检索连接时,将发生自动事务登记。这种情况,如果在Connection打开后,如果想再将新的的操作(command)登记入事务使不可能的。此时,应禁用自动登记功能:

   sqlserver为在连接字符串中设置Enlist字段为false:Enlist=false

   oledb中为OLE DB Services=-7

此时可以使用 EnlistDistributedTransaction 在事务中登记 Connection

SqlConnection nwindConn = new SqlConnection(".......;Enlist=false;");

SqlCommand cmd = new SqlCommand("......", nwindConn);


...

nwindConn.Open();

ITransaction trans =(ITransaction)ContextUtil.Transaction;//获取当前分布事务

nwindConn.EnlistDistributedTransaction(trans);//之前必须nwindConn.Open();

try
    {
      cmd.ExecuteNonQuery();//执行事务

      ContextUtil.SetComplete();//提交事务
    }
    catch (SqlException e)
    {
     ContextUtil.SetAbort();
    }
    finally
    {
      nwindConn.Close();
    }


例子:
/// <summary>
/// SQL Server事务样本类,演示Sql的事务操作
/// 作者:李斌(Camus)
/// </summary>
public class SQLServerTransactionDemo
{
private SQLServerTransactionDemo(){}

/// <summary>
/// 获取SQL Server事务样本类的实例方法
/// </summary>
/// <returns>SQL Server事务样本类的实例</returns>
public static SQLServerTransactionDemo GetHandle()
{
return new SQLServerTransactionDemo();
}

#region 运行SQL Server事务Run方法
/// <summary>
/// 运行SQL Server事务
/// </summary>
public void Run()
{
// 访问Microsoft SQL Server样本数据库Northwind,假设Microsoft SQL Server的sa密码为空
string connectionString=@"Server=(Local);Database=Northwind;UID=sa;PWD=;Persist Security Info=false;";

//创建Connection对象
System.Data.SqlClient.SqlConnection sqlConnection = null;
System.Data.SqlClient.SqlTransaction sqlTransaction = null;
try
{
sqlConnection = new System.Data.SqlClient.SqlConnection(connectionString);
sqlConnection.Open();//打开Connection

// 开始本地事务,Connection.BeginTransaction()
// IsolationLevel.ReadCommitted:
// 在正在读取数据时保持共享锁,以避免脏读,但是在事务结束之前可以更改数据,从而导致不可重复的读取或幻像数据。
sqlTransaction = sqlConnection.BeginTransaction(System.Data.IsolationLevel.ReadCommitted,"SQLTransaction");

//创建Command对象
System.Data.SqlClient.SqlCommand sqlCommand = sqlConnection.CreateCommand();
// 指派Connection和Transaction对象给Command对象
sqlCommand.Connection = sqlConnection;
sqlCommand.Transaction = sqlTransaction;

//开始执行事务,该事务由命令1 2 3组成.
// 执行数据库命令1
sqlCommand.CommandText = "Insert into Region (RegionID, RegionDescription) VALUES (200, \'Description\')";
sqlCommand.ExecuteNonQuery();
// 执行数据库命令2
sqlCommand.CommandText = "Insert into Region (RegionID, RegionDescription) VALUES (201, \'Description\')";
sqlCommand.ExecuteNonQuery();
// 执行数据库命令3!!!与命令1相同,会出错
sqlCommand.CommandText = "Insert into Region (RegionID, RegionDescription) VALUES (200, \'Description\')";
sqlCommand.ExecuteNonQuery();
// 提交事务
sqlTransaction.Commit();
Console.WriteLine("两条数据库命令已经执行完成.");
}
catch(Exception e)
{
try
{
if(sqlTransaction != null)
{
// 回滚事务
sqlTransaction.Rollback("SQLTransaction");
}
}
catch (System.Data.SqlClient.SqlException ex)
{
// 回滚事务失败
if (sqlTransaction.Connection != null)
{
Console.WriteLine("执行回滚事务时出现 " + ex.GetType() + " 违例!" + ex.Message);
}
}
   
Console.WriteLine("在执行数据库命令时出现 " + e.GetType() + " 违例!" + e.Message);
Console.WriteLine("两条数据库命令均未完成.");
}
finally 
{
//关闭Connection
if(sqlConnection != null)
{
sqlConnection.Close();
}
}
}
#endregion

public static void Main(string[] args)
{
SQLServerTransactionDemo.GetHandle().Run();
}
}



你可能感兴趣的:(sql,.net,SQL Server,活动,Microsoft)