您的位置:首页 > 其它

.Net中的5种事务总结

2012-11-15 12:00 253 查看


.Net中的5种事务总结

.Net 2010-01-29
23:52:28 阅读164 评论0 字号:大中小 订阅

在一个MIS系统中,没有用事务那就绝对是有问题的,要么就只有一种情况:你的系统实在是太小了,业务业务逻辑有只要一步执行就可以完成了。因此掌握事务处理的方法是很重要,进我的归类在.net中大致有以下4种事务处理的方法。大家可以参考一下,根据实际选择适当的事务处理。

1、SQL事务

sql事务是使用SQL server自身的事务:在存储过程中直接使用Begin Tran,Rollback Tran,Commit Tran实现事务:

优点:执行效率最佳

限制:事务上下文仅在数据库中调用,难以实现复杂的业务逻辑。

Demo:(所有demo,都以SQL Server自带的Northwind数据的表Region为例)

带事务的存储过程

CREATE PROCEDURE dbo.SPTransaction

(

@UpdateID int,

@UpdateValue nchar(50),

@InsertID int,

@InsertValue nchar(50)

)

AS

begin Tran

Update Region Set where RegionID=@UpdateID

insert into Region Values (@InsertID,@InsertValue)

declare @RegionError int

select @RegionError=@@error

if(@RegionError=0)

COMMIT Tran

else

ROLLBACK Tran

GO

执行带事务的存储过程

/**//// <summary>

/// SQL事务:

/// </summary>

public void SQLTran()

{

SqlConnection conn = new SqlConnection("Data
Source=127.0.0.1;Initial Catalog=Northwind;Persist Security Info=True;User );

SqlCommand cmd = new SqlCommand();

cmd.CommandText = "SPTransaction";

cmd.CommandType = CommandType.StoredProcedure;

cmd.Connection = conn;

conn.Open();

SqlParameter[] paras= new SqlParameter[]{

new SqlParameter ("@UpdateID",SqlDbType.Int,32),

new SqlParameter ("@UpdateValue",SqlDbType .NChar,50),

new SqlParameter ("@InsertID",SqlDbType.Int ,32),

new SqlParameter ("@InsertValue",SqlDbType.NChar ,50)};

paras[0].Value = "2";

paras[1].Value = "Update Value1";

paras[2].Value = "6";

paras[3].Value = "Insert Value1";

foreach (SqlParameter para in paras )

{

cmd.Parameters.Add(para);

}

cmd.ExecuteNonQuery();

}

2、ADO.net事务

Ado.net事务可能是大家一般都用的

优点:简单,效率和数据库事务差不多。

缺点:事务不能跨数据库,只能在一个数据库连接上。如果是两个数据库上就不能使用该事务了。

Demo:

ADO.net事务

/**//// <summary>

/// 一般的ADO.net 事务

/// </summary>

public void ADONetTran1()

{

SqlConnection conn = new SqlConnection("Data
Source=127.0.0.1;Initial Catalog=Northwind;Persist Security Info=True;User );

SqlCommand cmd = new SqlCommand();

try

{

cmd.CommandText = "Update Region Set where RegionID=@UpdateID";

cmd.CommandType = CommandType.Text;

cmd.Connection = conn;

conn.Open();

SqlParameter[] paras = new SqlParameter[]{

new SqlParameter ("@UpdateID",SqlDbType.Int,32),

new SqlParameter ("@UpdateValue",SqlDbType .NChar,50)};

paras[0].Value = "2";

paras[1].Value = "Update Value12";

foreach (SqlParameter para in paras)

{

cmd.Parameters.Add(para);

}

//开始事务

cmd.Transaction = conn.BeginTransaction();

cmd.ExecuteNonQuery();

cmd.CommandText = "insert into Region values(@InsertID,@InsertValue)";

cmd.CommandType = CommandType.Text;

paras = new SqlParameter[]{

new SqlParameter ("@InsertID",SqlDbType.Int ,32),

new SqlParameter ("@InsertValue",SqlDbType.NChar ,50)};

paras[0].Value = "7";

paras[1].Value = "Insert Value";

cmd.Parameters.Clear();

foreach (SqlParameter para in paras)

{

cmd.Parameters.Add(para);

}

cmd.ExecuteNonQuery();

//提交事务

cmd.Transaction.Commit();

}

catch

{

//回滚事务

cmd.Transaction.Rollback();

throw;

}

finally

{

conn.Close();

}

}

3、TransactionScope事务

TransactionScope事务类,它可以使代码块成为事务性代码。并自动提升为分布式事务

优点:实现简单,同时能够自动提升为分布式事务

Demo:

TransactionScope事务

/**//// <summary>

/// TransactionScope事务:可自动提升事务为完全分布式事务的轻型(本地)事务。

/// 使用时要保证MSDTC服务(控制分布事务)是开启的可以使用:net start msdtc命令开启服务;

/// </summary>

public void ADONetTran2()

{

SqlConnection conn = new SqlConnection("Data
Source=127.0.0.1;Initial Catalog=Northwind;Persist Security Info=True;User );

SqlCommand cmd = new SqlCommand();

try

{

using (System.Transactions.TransactionScope ts = new TransactionScope())

{

cmd.CommandText = "Update Region Set where RegionID=@UpdateID";

cmd.CommandType = CommandType.Text;

cmd.Connection = conn;

conn.Open();

SqlParameter[] paras = new SqlParameter[]{

new SqlParameter ("@UpdateID",SqlDbType.Int,32),

new SqlParameter ("@UpdateValue",SqlDbType .NChar,50)};

paras[0].Value = "2";

paras[1].Value = "Update Value12";

foreach (SqlParameter para in paras)

{

cmd.Parameters.Add(para);

}

cmd.ExecuteNonQuery();

cmd.CommandText = "insert into Region values(@InsertID,@InsertValue)";

cmd.CommandType = CommandType.Text;

paras = new SqlParameter[]{

new SqlParameter ("@InsertID",SqlDbType.Int ,32),

new SqlParameter ("@InsertValue",SqlDbType.NChar ,50)};

paras[0].Value = "8";

paras[1].Value = "Insert Value";

cmd.Parameters.Clear();

foreach (SqlParameter para in paras)

{

cmd.Parameters.Add(para);

}

cmd.ExecuteNonQuery();

//提交事务

ts.Complete(); //提交事务之前conn不能关闭的(Not conn.Close()),否则报错

}

}

catch

{

throw;

}

finally

{

conn.Close();

}

}

4、COM+事务

在分布式应用程序中,往往要同时操作多个数据库,使用数据库事务就不能满足业务的要求了。在COM+中,提供完整的事务处理服务。很方便处理多个数据库上的事务。

例一:

COM+事务

/**//// <summary>

/// COM+事务

/// </summary>

public void ComTran()

{

SqlConnection conn = new SqlConnection("Data
Source=127.0.0.1;Initial Catalog=Northwind;Persist Security Info=True;User );

SqlCommand cmd = new SqlCommand();

ServiceConfig sc = new ServiceConfig();

//指定事务类型

sc.Transaction = TransactionOption.Required;

//设置启动跟踪

sc.TrackingEnabled = true;

//创建一个上下文,该上下文的配置由作为 cfg 参数传递的 ServiceConfig 对象来指定。

//随后,客户端和服务器端的策略均被触发,如同发生了一个方法调用。

//接着,新的上下文被推至上下文堆栈,成为当前上下文

ServiceDomain.Enter(sc);

try

{

cmd.CommandText = "Update Region Set where RegionID=@UpdateID";

cmd.CommandType = CommandType.Text;

cmd.Connection = conn;

conn.Open();

SqlParameter[] paras = new SqlParameter[]{

new SqlParameter ("@UpdateID",SqlDbType.Int,32),

new SqlParameter ("@UpdateValue",SqlDbType .NChar,50)};

paras[0].Value = "2";

paras[1].Value = "Update Value22";

foreach (SqlParameter para in paras)

{

cmd.Parameters.Add(para);

}

cmd.ExecuteNonQuery();

cmd.CommandText = "insert into Region values(@InsertID,@InsertValue)";

cmd.CommandType = CommandType.Text;

paras = new SqlParameter[]{

new SqlParameter ("@InsertID",SqlDbType.Int ,32),

new SqlParameter ("@InsertValue",SqlDbType.NChar ,50)};

paras[0].Value = "9";

paras[1].Value = "Insert Value";

cmd.Parameters.Clear();

foreach (SqlParameter para in paras)

{

cmd.Parameters.Add(para);

}

cmd.ExecuteNonQuery();

//提交事务

ContextUtil.SetComplete();

}

catch

{

//回滚事务

ContextUtil.SetAbort();

throw;

}

finally

{

conn.Close();

//触发服务器端的策略,随后触发客户端的策略,如同一个方法调用正在返回。

//然后,当前上下文被弹出上下文堆栈,调用 Enter 时正在运行的上下文成为当前的上下文。

ServiceDomain.Leave();

}

需要特别补充的是:

如果你使用的是分布事务(TransactionScope事务和COM+事务),在默认情况下你是要重新配置安装SQL Server数据库服务器和访问数据库的客户端的.(如果没有配置运行会出现以下错误:该伙伴事务管理器已经禁止了它对远程/网络事务的支持。 (异常来自 HRESULT:0x8004D025)

)下面是MSDN上关于配置分布式事务的一段原话:

配置分布式事务

要启用分布式事务,可能需要通过网络启用 MS DTC,以便在使用应用了最新的 Service Pack 的较新操作系统(例如 Windows XP 或 Windows 2003)时使用分布式事务。如果启用了 Windows 防火墙(Windows XP Service Pack 2 的默认设置),必须允许 MS DTC 服务使用网络或打开 MS DTC 端口。

实际怎么配置呢,经过我的实际使用:大致如下:打开'控制面板'->'管理工具'->'组件服务',点开'组件服务'->'计算机'->'我的电脑',在'我的电脑'上右击属性,点'MSDTC',然后点'安全性配置'。作为数据库的服务器的配置如下:

而访问数据库的客户端的配置和服务器端的稍有些差别:

在设置完上面的还有使防火墙MS DTC 服务使用网络或打开 MS DTC 端口:运行netsh firewall set allowedprogram %windir%\system32\msdtc.exe MSDTC enable命令就可以了

ASP.NET事务可以说是在.NET平台上事务实现方式最简单的一种,你仅仅需要一行代码即可。在aspx的页面声明中加一个额外的属性,即事务属性Transaction="Required",它有如下的值:Disabled(默认)、NotSupported、Supported、Required和RequiresNew,这些设置和COM+及企业级服务中的设置一样,典型的一个例子是如果你想在页面上下文中运行事务,那么要将其设置为Required。如果页面中包含有用户控件,那么这些控件也会包含到事务中,事务会存在于页面的每个地方。

页面声明Transaction="Required":

<%@ Page Transaction="Required" Language="C#" AutoEventWireup="true"

CodeBehind="WebForm3.aspx.cs" Inherits="WebApplication4.WebForm3" %>

页面引用:using System.EnterpriseServices;。

然后,数据操作代码:

protected void Button1_Click(object sender, EventArgs e)

{

try

{

Work1();

Work2();

ContextUtil.SetComplete(); //提交事务

}

catch (System.Exception except)

ContextUtil.SetAbort(); //撤销事务

Response.Write(except.Message);

}

}

private void Work1()

{

string conString = "data
source=127.0.0.1;database=codematic;user >

password=";

SqlConnection myConnection = new SqlConnection(conString);

string strSql = "Insert Into P_Category(CategoryId,Name)values('1',

'test1')";

SqlCommand myCommand = new SqlCommand(strSql, myConnection);

myConnection.Open();

int rows = myCommand.ExecuteNonQuery();

myConnection.Close();

}

private void Work2()

{

string conString = "data
source=127.0.0.1;database=codematic;user >

password=";

SqlConnection myConnection = new SqlConnection(conString);

string strSql = "Insert Into P_Category(CategoryId,Name)values('2',

'test2')";

SqlCommand myCommand = new SqlCommand(strSql, myConnection);

myConnection.Open();

int rows = myCommand.ExecuteNonQuery();

myConnection.Close();

}

ContextUtil是用于获取 COM+ 上下文信息的首选类。由于此类的成员全部为static,因此在使用其成员之前不需要对此类进行实例化。

ASP.NET页面事务的优势和限制如下。

l限制:页面的所有代码都是同一个事务,这样的事务可能会很大,而也许我们需要的是分开的、小的事务实现在Web层。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: