asp.net事务机制
在两年前面试时,一个技术总监问我在项目中怎样处理事务??这个问题我觉得有点歧义,首先不知道是什么事务,是关于数据库的事务还是页面中出现的事务,其实那个时候我就知道怎样在数据库端处理事务,而且直到现在才有时间来了解这个问题.唉,杯具啊!怪不得面试的时候笔试题总是和自己工作时的内容有很大的差别,其实有些笔试题平时也接触过,只不过都是自己在实践操作并没有把它抽象出来成为不成文的理论知识。所以,面试的笔试题总是我的难题。其实还有一个原因就是我的基础知识很烂,比较大脑比较空虚。不瞎扯淡了看看这个问题吧!
1.SQL和存储过程级别的事务
这个也是我经常用到的事务,其实这个可以用一个很简单的例子来形容就是银行取钱的问题,两个不同地方的存折但是是同一个账户,当其中一个地方的存折发生改变另外一个地方的存折数据也会跟着发生改变,存储过程实例:
CREATE PROCEDURE TRAN1
AS
BEGIN TRAN
SET xact_abort on
UPDATE 账户 set 金额=100 WHERE 帐号='帐号'
UPDATE 账户 set 金额=100 WHERE 帐号='帐号'
commit tran
GO
2.ADO.NET 级别的事务
这个就是我们在创建访问数据库的DBHelper类中经常使用的,如
/// <summary> /// 执行多条SQL语句,实现数据库事务。 /// </summary> /// <param name="SQLStringList">多条SQL语句</param> public static void ExecuteSqlTran(ArrayList SQLStringList) { using (SqlConnection conn = new SqlConnection(connectionString)) { conn.Open(); SqlCommand cmd = new SqlCommand(); cmd.Connection=conn; SqlTransaction tx=conn.BeginTransaction(); cmd.Transaction=tx; try { for(int n=0;n<SQLStringList.Count;n++) { string strsql=SQLStringList[n].ToString(); if (strsql.Trim().Length>1) { cmd.CommandText=strsql; cmd.ExecuteNonQuery(); } } tx.Commit(); } catch(System.Data.SqlClient.SqlException E) { tx.Rollback(); MyLog.logger.Error("执行多条SQL处理事务错误信息:" + E.Message); } } }
3.asp.net 页面级别的事务
首先在页面做事务设置,使用Transaction="Required":
<%@ Page Transaction="Required" Language="C#" AutoEventWireup="true" CodeFile="Default2.aspx.cs" Inherits="Default2" %>
然后在后台中使用ContextUtil.SetComplete();提交事务ContextUtil.SetAbort();取消事务,
try
{
//完成的第一个任务
TaskWork1();
//完成的第二个任务
TaskWork2();
//提交事务
ContextUtil.SetComplete();
}
catch(Exception ex)
{
//如果出现一场则回滚
ContextUtil.SetAbort();
Response.Write(ex.Message);
}
4.企业级服务COM+ 事务
这个使用机制我是第一次使用,我仅在项目中做了一个测试,但是还是没有正式的使用过,对于我这个菜鸟来说可能在技术上还差的很多。使用方式是这样:
1)首先引用:using System.EnterpriseServices;如果在见类库时不能引入可以先导入System.EnterpriseServices这个dll文件
2)让类继承ServicedComponent
3)在类头部加[Transaction(TransactionOption.Required)]
4)给程序添加强名
1.创建密钥 sn-k c:\key.snk 这个密钥文件用于对DLL进行签名,这个key.snk的文件创建需要在目录下找到sn.exe这个应该是在安装vs的时候自带的一个工具吧我找到的它的目录是在C:\Program Files\Microsoft SDKs\Windows\v7.0A\bin 可以把这个文件拷出来放在一个方便使用的目录。把生成的key.snk文件放入项目中。
2.在AssemblyInfo.cs引入[assembly: AssemblyKeyFile("..\\key.snk")]
5)手动事务处理
/// <summary>
/// 手动处理事务
/// </summary>
/// <returns></returns>
public string DoTran()
{
try
{
ContextUtil.EnableCommit();
DoWork();
DoWork();
ContextUtil.SetComplete();
return "方法执行成功";
}
catch (Exception)
{
ContextUtil.SetAbort();
return "两个方法至少有一个执行失败!";
}
}
6)自动处理事务在方法上加入
[AutoComplete(true)]
private void DoWork()
{
//解决问题的方法
}
这种形式是不是很麻烦,而且性能很低
5.System.Transactions 事务处理 (需要引入System.Transactions这个DLL文件)
public void UseTransactions()
{
using (TransactionScope ts = new TransactionScope())
{
try
{
//处理问题的方法
}
catch (Exception)
{
throw;
}
ts.Complete();
}
}
这种方式非常强大还可以同时连接两个数据库
public void UseTransactions()
{
using (TransactionScope ts = new TransactionScope())
{
using (SqlConnection conn = new SqlConnection(strCon))
{
using (SqlConnection conn1 = new SqlConnection(strCon1))
{
}
}
ts.Complete();
}
}
其实还有很多别的强大的功能,我在项目中没有用到过所以也没有仔细的研究。还有一个比较有用的是可以控制在操作失败后仍然执行一个操作然后再次进入事务中,如:如果我们需要在失败后生成一个失败的日志这种就比较实用了使用方式
using (TransactionScope ts = new TransactionScope())
{
using (TransactionScope ts = new TransactionScope(TransactionScopeOption.Suppress))
{
//不受事务控制
}
//受事务控制区域
}