目录一、概述1、事务ACID特性2、.net开发者用到的5种事务机制:二、数据库事务1、不同数据库的事务规则2、数据库事务的优势和限制(1)优势:(2)限制:三、ADO.Net事务四
事务将一系列的工作视为一个工作单元,它具有 ACID 特性:
这5种事务机制有着各自的优势和劣势,分别表现在性能、代码数量和部署设置等方面。开发人员可以根据项目的实际情况选择相应的事务机制。
数据库事务是其他事务模型的基础,当一个事务创建时不同数据库系统都有自己的规则。
例如:SQL Server数据库T-SQL语句中显示指定事务
declare @TranName varchar(20);
select @TranName = 'MyTransaction';
begin transaction @TranName;
Go
use AdventureWorks;
go
delete from AdventureWorks.HumanResources.JobCandidate where JobCandidateID = 13;
go
commit transaction MyTransaction;
go
或在存储过程中使用
create procedure Tran1
as
begin tran;
set xact_abort on; --set xact_abort on表示遇到错误立即回滚。
insert into P_Category ( CategoryId, Name ) values ( '1', 'test1' );
insert into P_Category ( CategoryId, Name ) values ( '2', 'test2' );
commit tran;
go
ADO.Net事务为System.Data.Common.DbTransaction类的各种派生类。ADO.Net事务不是分布式事务,不支持跨多个连接,它总是关联到一个连接上的本地事务上。
ADO.NET 显式事务占用资源少、速度快,但功能简单,只能管理单一对象和单一持久资源间的事务。
using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["MysqlServer"].ConnectionString))
{
conn.Open();
using (SqlTransaction tran = conn.BeginTransaction())
{
using (SqlCommand cmd = new SqlCommand())
{
cmd.Connection = conn;
cmd.Transaction = tran;
cmd.CommandType = CommandType.Text;
try
{
cmd.CommandText = "insert into TranTable(Priority) values(1)";
cmd.ExecuteNonQuery();
cmd.CommandText = "insert into TranTable(Priority) values(256)";
cmd.ExecuteNonQuery();
tran.Commit();
Response.Write("Ok");
}
catch (SqlException ex)
{
tran.Rollback();
Response.Write("Error:" + ex.Message);
}
}
}
conn.Close();
}
不需要显示进行事务处理,运行库自动创建事务。多个对象能轻松的运行在同一个事务中。但它需要COM+主机模型。
使用此技术的类必须派生自ServicedComponen类。
[Transaction(TransactionOption.Required)]
public class OrderContrl : ServicedComponent
{
[AutoComplete]
public void NeWorder(Order order)
{
using (OrderData data = new OrderData())
{
data.Insert(order);
}
}
}
System.Transactions是所有事务处理类的基类。
System.Transactions基础结构通过支持SQL Server、ADO.NET、MSMQ和Microsoft分布式事务协调器(MSDTC)中启动的事务,使得整个平台的事务编程变得简单和高效。
它既提供了基于Transaction 类的显式编程模型,也提供了使用TransactionScope类的隐式编程模型,它里面的事务由基础设施自动管理。强烈建议使用更简单的隐式开发模型TransactionScope。
提交、回滚事务都由程序员编程来决定的方式,叫“显式事务(Explicit Transaction)”。Transaction 类及其派生类为显式事务。
唯一支持提交的事务类是CommitableTransaction,它直接继承自Transaction。
CommittableTransaction提供了“Commit”同步方法和“BeginCommit”、“EndCommit”异步方法组合对事务的提交。
创建CommittableTransaction事务并不会自动设置环境事务。
CommittableTransaction事务不能被重用。可以将数据库连接登记到事务。
注意:只有一个DbConnection时为本地事务;当存在多个DbConnection时才会启动MSDTC(MSDTC不够稳定,尽量避免引入分布式服务)
using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["mysqlServer"].ConnectionString))
{
using (CommittableTransaction ct = new CommittableTransaction ())
{
conn.Open();
conn.EnlistTransaction(ct);//将数据库连接登记到事务
using (SqlCommand cmd = new SqlCommand())
{
cmd.Connection = conn;
cmd.CommandType = CommandType.Text;
try
{
cmd.CommandText = "insert into TranTable(Priority) values(1)";
cmd.ExecuteNonQuery();
cmd.CommandText = "insert into TranTable(Priority) values(256)";
cmd.ExecuteNonQuery();
ct.Commit(); //提交事务
Response.Write("Ok");
}
catch (SqlException ex)
{
ct.Rollback();//回滚事务
Response.Write("Error:" + ex.Message);
}
}
conn.Close();
}
}
TransactionScope为隐式事务。它为一组事务型操作创建一个执行范围,而这个范围始于TransactionScope创建之时,结束于TransactionScope被回收(调用Dispose方法)。
TransactionScope实现了IDisposable接口,除了Dispose方法之外,仅仅具有一个唯一的方法:Complete()。
目前 TransactionScope 只能处理数据库的事务,对于其他事务,如 I/O,目前的 .NET 版本无法处理。
using (SqlConnection conn = new SqlConnection("Data Source=.; Initial Catalog=TestDb; Integrated Security=SSPI;"))
{
using (TransactionScope ts = new TransactionScope())
{
conn.Open();
try
{
SqlCommand cmd = new SqlCommand(conn);
cmd.CommandText = "INSERT INTO [Test]([Name],[Value]) VALUES ('测试1','1')";
cmd.ExecuteNonQuery();
cmd.CommandText = "INSERT INTO [Test]([Name],[Value]) VALUES ('测试2','2')";
cmd.ExecuteNonQuery();
ts.Complete();
}
catch (SqlException)
{
}
conn.Close();
}
}
TransactionScope却有一组丰富的构造函数。我们先来看看这些构造函数相应的参数如何影响TransactionScope对事务控制的行为。
void Main()
{
TransactionOptions transactionOptions = new TransactionOptions()
{
IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted,
Timeout = new TimeSpan(0, 2, 0)//超时间隔两分钟
};
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, transactionOptions))
{
Transaction.Current.TransactionCompleted += (sender, args) =>
{
Console.Write(args.Transaction.TransactionInformation.LocalIdentifier);
}
AddStudent(new Student { });
scope.Complete();//提交事务
}
}
public void AddStudent(Student s)
{
SqlConnection conn = new SqlConnection();//环境事务内新建的连接自动附加到事务
//如果连接在TransactionScope建立之前已存在,需要手工用conn.EnlistTrasaction(Transaction.Current)登记事务
conn.Open();
try
{
SqlCommand command = new SqlCommand();
}
catch (Exception ex)
{
throw;
}
}
7个隔离级别之中,Serializable具有最高隔离级别,代表的是一种完全基于序列化(同步)的数据存取方式。按照隔离级别至高向低,7个不同的隔离级别代表的含义如下:
using (TransactionScope outerScope = new TransactionScope())
{
using (TransactionScope innerScope = new TransactionScope(TransactionScopeOption.Required, transactionOptions))
{
//事务型操作
innerScope.Complete();
}
//事务型操作
outerScope.Complete();
}
使用TransactionScopeOptions可以改变TransactionScope的默认事务类型。
一般情况下只要你使用"TransactionScope",都要配置MSDTC,要配防火墙,要开139端口,这个端口不可以更改。
对MSDTC组件设置:控制面板--->管理工具--->服务 中,开启Distributed Transaction Coordinator 服务。
一个环境事务绑定到一个线程上,如果新建了一个线程它就不会有第一个线程中的环境事务,两个线程中的事务完全独立。
如果多个线程使用同一个环境事务,需要给新线程传递一个依赖事务,调用Transaction的DependentClone方法创建依赖事务。
依赖事务通过DependentTransaction类型表示,和CommittableTransaction一样,DependentTransaction也是Transaction的子类。
DependentTransaction依赖于现有的Transaction对象而存在,相当于被依赖事务的子事务,具有一个唯一的方法成员:Complete。调用这个方法意味着向被依赖事务发送通知,表明所有与依赖事务相关的操作已经完成。
DependentClone方法具有一个DependentCloneOption枚举类型的参数:
下面的代码示例演示如何创建一个依赖事务来管理两个并发任务,具体为克隆一个依赖的事务并将其传递给辅助线程。
void Main()
{
using (TransactionScope scope = new TransactionScope())
{
DependentTransaction dTx = Transaction.Current.DependentClone(DependentCloneOption.BlockCommitUntilComplete);
Thread thread = new Thread(ThreadMethod);
thread.Start(dTx);
scope.Complete();
}
}
public void ThreadMethod(object transaction)
{
DependentTransaction dTx = transaction as DependentTransaction;
try
{
//将DependentTransaction对象作为TransactionScope的参数,以初始化环境事务
using (TransactionScope ts = new TransactionScope(dTx))
{
ts.Complete();//完成环境事务
}
}
finally
{
dTx.Complete();//完成依赖事务
dTx.Dispose();
}
}
--结束END--
本文标题: 事务在c#中的使用
本文链接: https://lsjlt.com/news/148263.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2024-03-01
2024-03-01
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0