事务类型:
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();
}