Asp.Net事务和异常处理:

一。什么是事务处理?
事务处理是一组组和成逻辑工作单元的数据库操作,虽然系统中可能会出错,但事务将控制和维护每个数据库的一致性和完整性。
如果在事务过程中没有遇到错误,事务中的所有修改都将永久成为数据库中的一部分,如果遇到错误,则不会对数据库进行任何修改。
二。事务处理过程。
1. 开始一个事务。进入“事务待命”状态。
2. 在“事务待命”状态,记录事务中改变的数据库记录。此改变不能直接改变数据库中的值,必须先用一个顺序的“事务日志”记录在一边。同时,对于要改变的原始记录加锁,让其它用户无法读和写。如果记录已经被其它事务加锁,则报错。
3. 在“事务待命”,如果用户给出commit transaction命令,则进入“事务拷贝”状态,拷贝所有加锁的记录成备份。
4. 上面3执行完,则进入“事务更新”状态,用“事务日志”中记录一一更新实际的数据库记录。
5. 上面4执行完,则进入“事务结束”状态,释放所有的记录锁,然后抛弃“事务日志”和备份的原数据库记录。
6. 上面5做完后,事务被删除。但是,最为关键的是,事务系统必须执行以下过程:一但数据库由于软件、硬件问题发生故障,重启动后,一旦有事务没正常删除,则:
7. 如果在“事务待命”、“事务结束”状态,则重新从5中结束事务的动作开始执行。
8. 如果在“事务更新”状态,则重新从4开始更新记录,并继续想下执行。结果,虽然系统崩溃过,但事务仍然能正常提交。
三。事务处理的有关事项
•事务处理的关键是在提交事务或者取消事务时,万一系统崩溃了,数据库在再次启动时,仍然需要保持数据可逻辑一致性。
• 应用中包含的事务应当尽量让它“瞬间”完成,避免在比较忙时造成用户进程的互锁。
• Informix、Oracle、DB2等数据库的实际事务处理流程更复杂,目的是具有更好的抵抗系统错误性质,因为事务保护是业务系统安全稳定的最后一道防线。

四。事务处理的方法
1,直接写入SQL。我们来看一个例子。新建一个表,具体过程我就不给出了,大家自己建,也就是达到测试地目的,有个用户名就可以。然后写存储过程:

create procedure [SqlAcTran] As
begin tran
declare @UserInfoError int 
delete from [SqlAction] where username='测试'
select @UserInfoError =@@error
if(@UserInfoError =0)
commit tran
else
rollback tran
go

然后建立一个页面,页面简单之极,只用一个BUTTON来执行命令,然后对BUTTON编程,这里如果对连接语句不明白的话参加我的

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Data.SqlClient;

namespace WebApplication1
{
    public partial class SqlAction : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        protected void btn_Click(object sender, EventArgs e)
        {
            SqlConnection con = new SqlConnection();
            con.ConnectionString=ConfigurationManager.ConnectionStrings["DSN"].ConnectionString;
            con.Open();
            SqlCommand com = new SqlCommand();
            com.Connection = con;
            com.CommandType = CommandType.StoredProcedure;
            com.CommandText = "SqlAcTran";
            com.ExecuteNonQuery();
            con.Close();

        }
    }
}

2,Ado.Net事务处理。
在ADO.NET 中,可以使用Connection 和Transaction 对象来控制事务。若要执行事务,请执行下列操作:
• 调用Connection 对象的BeginTransaction 方法来标记事务的开始。
• 将Transaction 对象分配给要执行的Command的Transaction 属性。
• 执行所需的命令。
• 调用Transaction 对象的Commit 方法来完成事务,或调用Rollback 方法来取消事务。
当然ADO.NET事务处理有优点和缺点,运用起来看具体情况了。
• 优点:
– 简单性
– 和数据据事务差不多的快
– 独立于数据库,不同数据库的专有代码被隐藏了
• 缺点:
– 事务不能跨越多个数据库连接
– 事务执行在数据库连接层上,所以需要在事务过程中维护一个数据库连接。
下边我们看一个例子,建立一个页面,同样简单,只需要一个按钮,然后编程:

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Data.SqlClient;

namespace WebApplication1
{
    public partial class AdoAction : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        protected void btn_Click(object sender, EventArgs e)
        {
            SqlConnection con = new SqlConnection();
            con.ConnectionString=ConfigurationManager.ConnectionStrings["DSN"].ConnectionString;
            con.Open();
            //启动一个事务。
            SqlTransaction myTran = con.BeginTransaction();
            //为事务创建一个命令,注意我们执行双条命令,第一次执行当然成功。我们再执行一次,失败。
            //第三次我们改其中一个命令,另一个不改,这时候事务会报错,这就是事务机制。
            SqlCommand myCom = new SqlCommand();
            myCom.Connection = con;
            myCom.Transaction = myTran;
            try
            {
                myCom.CommandText = "insert into SqlAction values ('测试2','111')";
                myCom.ExecuteNonQuery();
                myCom.CommandText = "insert into SqlAction values ('测试3','111')";
                myCom.ExecuteNonQuery();
                myTran.Commit();
                Response.Write("成功执行");

            }
            catch (Exception Ex)
            {
                myTran.Rollback();
                //创建并且返回异常的错误信息
                Response.Write(Ex.ToString());
                Response.Write("写入数据库失败");
            }
            finally
            {
                con.Close();
            }
 
        }


    }
}

3,COM+事务
一般的数据库事务控制要求事务里所做的操作必须在同一个数据库内,这样在出现错误的时候才能回滚(RollBack)到初始状态。这就存在一个问题,在分布式应用程序中,我们往往需要同时操作多个数据库,使用数据库本身的事务处理,很难满足程序对事务控制的要求。在COM+中,提供了完整的事务服务,我们可以利用它来完成在分布式应用程序中的事务控制。
创建参与自动事务的类:
1. 将TransactionAttribute 类应用于您的类,指定组件请求的自动事务类型。事务类型必须是TransactionOption 枚举的成员。
2. 从ServicedComponent 类派生您的类。ServicedComponent 是所有使用COM+ 服务
的类的基类。
3. 用强名称(strong name) 标记(sign) 程序集(assembly),确保程序集包含唯一的密钥对。
4. 在COM+ catalog 中注册包含您的类的程序集.
• 定义一个COM+事务处理的类
[Transaction(TransactionOption.Required)]
public class
DataAccess:System.EnterpriseServices.ServicedCo
mponent
{
}
• TransactionOption枚举类型支持5个COM+值
– Disabled 忽略当前上下文中的任何事务。
– NotSupported 使用非受控事务在上下文中创建组件。
– Required 如果事务存在则共享事务,并且如有必要则创建新事务。
– RequiresNew 使用新事务创建组件,而与当前上下文的状态无关。
– Supported 如果事务存在,则共享该事务。
强名称:
为使该组件正确运行,该组件必须有一个强名称。生成一个强名称,然后使用该强名称对程序集进行签名。为此,请按照下列步骤操作:
• 在命令提示符下,键入sn -k snEnterprise.snk 以创建一个密钥文件。
• 将snEnterprise.snk 复制到您的项目文件夹中。
• 在AssemblyInfo.vc 中,将以下代码添加到其他程序集属性语句之前或之后:[assembly:AssemblyKeyFileAttribute("..\\..\\snEnterprise.snk")]
• 进行保存,然后生成您的项目
• 使用regsvcs.exe将Dll注册到COM+ Services里面
注意事项:
• 确保使用COM+ 服务的所有项目都有一个强名称。
• 使用COM+ 服务的所有类都必须继承服务组件。服务组件位于System.EnterpriseServices 命名空间中。
• 进行调试时,事务在提交或终止前可能会超时。要避免出现超时,请在事务属性中使用一个超时属性。在面的示例中,在完成任何事务时,关联的方法在超时前都有1,200 秒的执行时间。
[Transaction(TransactionOption.Required,timeout:=1200)]
下边做例子,这是VS2005中的,我修改了一晚上才成功。。哭.写个数据库:

use myDatabase
go
create table ComAction
(
    userID int identity,
    userName varchar(30) not null,
    userScore int not null
)
insert into ComAction values('张三',100)

首先我们建立一个类库prjEnterprise 添加引用System.EnterpriseService。  然后添加一个类clsEs

using System;
using System.Collections.Generic;
using System.Text;
using System.Data.SqlClient;
using System.EnterpriseServices;

namespace prjEnterprise
{
    [Transaction(TransactionOption.Required)]public class clsES:System.EnterpriseServices.ServicedComponent
    {
        public SqlConnection Conn;

        public void dbAccess(int  pID1, int nScore)
        {
            try
            {
                SqlConnection Conn = new SqlConnection("user id=sa;password=;Initial Catalog=myDataBase;Data Source=.;");
                Conn.Open();
                SqlCommand sqlCommand = new SqlCommand("UPDATE ComAction SET userScore = " + nScore + " WHERE userID = " + pID1, Conn);
                sqlCommand.ExecuteNonQuery();

                ContextUtil.SetComplete();
                Conn.Close();
            }
            catch (Exception e)
            {
                ContextUtil.SetAbort();

                throw e;
            }
            finally
            {

            }
        }
    }
}

然后给程序添加强名(strong name)
1:创建一对密钥
使用sn.exe这个工具
sn –k SnEnterprise.snk
其中SnEnterprise.snk 代表将保存密钥的文件的名称。它的名称可以是任意的,不过习惯上带有.snk后缀名。
2:签名
签名通常是在编译时进行的。签名时,用户可利用C#属性通知编译器应该使用正确的密钥文件对DLL进行签名。要做到这一点用户需要打开工程中的AssemblyInfo.cs文件并进行修改。
 [assembly: ComVisible(true)] 这里的true默认是false需要改,要不不成我就卡到这上一个晚上。
[assembly:AssemblyKeyFile(“..\\..\\SnEnterprise.snk”)]
注:SnEnterprise.snk文件和项目文件在同一个文件夹
注:SnEnterprise.snk文件和项目文件在同一个文件夹
3:编译成DLL
4:使用regsvcs.exe将Dll注册到COM+ Services里面,我的是这样

C:\web study\WebApplication1\WebApplication1\prjEnterprise\bin\Debug>regsvcs prjEnterprise.dll
Microsoft(R) .NET Framework 服务安装实用工具版本 2.0.50727.42
Copyright (c) Microsoft Corporation.  All rights reserved.

警告: 程序集未声明 ApplicationAccessControl 属性。默认情况下启用应用程序安全性。

已安装的程序集:
        程序集: C:\web study\WebApplication1\WebApplication1\prjEnterprise\bin\D
ebug\prjEnterprise.dll
        应用程序: prjEnterprise
        TypeLib: C:\web study\WebApplication1\WebApplication1\prjEnterprise\bin\
Debug\prjEnterprise.tlb

然后在WebApplication1理添加引用。然后添加测试页面

<form id="_03ComPlusAction" method="post" runat="server">
   <asp:Button id="btnCommit1" style="Z-INDEX: 101; LEFT: 240px; POSITION: absolute; TOP: 102px" runat="server" Text="调用1" OnClick="btnCommit1_Click"></asp:Button>
   <asp:Button id="btnCommit2" style="Z-INDEX: 102; LEFT: 241px; POSITION: absolute; TOP: 164px" runat="server" Text="调用2" OnClick="btnCommit2_Click"></asp:Button>
  </form>
后台编程:

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

namespace WebApplication1
{
    public partial class ComAcction : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        protected void btnCommit1_Click(object sender, EventArgs e)
        {
            prjEnterprise.clsES myTest = new prjEnterprise.clsES();
            try
            {
                myTest.dbAccess(1, 300);
                Response.Write("事务成功!");
            }
            catch (Exception)
            {
                Response.Write("事务失败!");
            }

        }

        protected void btnCommit2_Click(object sender, EventArgs e)
        {
            prjEnterprise.clsES myTest = new prjEnterprise.clsES();

            try
            {
                myTest.dbAccess(1,1000000000);
                Response.Write("事务成功!");
            }
            catch (Exception)
            {
                Response.Write("事务失败!");
            }
        }
    }
}

什么是异常处理
• 异常是正在执行的程序所遇到的任何错误情形或者意外行为。
• 很多原因都可以引起异常,例如,代码中错误、操作系统资源不可用、公共语言运行时(common language runtime)中的意外情况等等。
• 然而应用程序能够从上述的一些情况中恢复执行,但是大多数运行时异常是不可恢复的。在这种情况下,需要一种有效的方法来处理这些异常并给调用者提供相同的异常。
用结构化的异常处理方法来处理异常
• 在.NET Web服务中,对异常处理支持的关键点是由try...catch..finally语句提供的。
• 关键字try放在可能抛出异常的普通处理代码块之前。
• 关键字catch放在异常处理代码块之前。
• 关键字finally放在那些经常在异常处理后还需要执行的代码块之前。
• 一旦异常从try代码块中抛出,程序流切换到后面的第一个catch代码块
异常类
• Exception 所有异常对象的基类
• SystemException 运行时产生的所有错误的基类
• IndexOutOfRangeException 当一个数组的下标超出范围时运行时引发
• NullReferenceException 当一个空对象被引用时运行时引发
• InvalidOperationException 当对方法的调用对对象的当前状态无效时,由某些方法引发
• ArgumentException 所有参数异常的基类
• ArgumentNullException 在参数为空(不允许)的情况下,由方法引发
• ArgumentOutOfRangeException 当参数不在一个给定范围之内时,由方法引发
• InteropException 目标在或发生在CLR外面环境中的异常的基类
• ComException 包含COM 类的HRESULT信息的异常
• SEHException 封装win32 结构异常处理信息的异常
优化异常
• 理解异常是一定会发生的
– 大多数的软件系统都不是百分之百可靠的!
– 要站在异常一定可能会发生的角度来编写异常
处理程序,应对程序有可能发生的错误。
– 建立一个良好的异常处理策略
• 处理未预料的异常
– 确保所有程序的入口都使用了try-catch
– 在catch中截获所有的异常
异常处理注意事项
• 当引发异常时,要提供有意义的文本。
• 要引发异常仅当条件是真正异常;也就是当一个正常的返回值不满足时。
• 如果你的方法或属性被传递一个坏参数,要引发一个ArgumentException异常。
• 当调用操作不适合对象的当前状态时,要引发一个InvalidOperationException异常。
• 要引发最适合的异常。
• 要使用链接异常,它们允许你跟踪异常树。
• 不要为正常或预期的错误使用异常。
• 不要为流程的正常控制使用异常。
• 不要在方法中引发NullReferenceException或IndexOutOfRangeException异常。
异常处理技术
• 记录异常
– 在文件中记录异常
– 在数据库中记录异常
– 在eventlog中记录异常
• 发送email通知异常
• 异常产生时,用友好(user-friendly)的方式通知用户
处理错误
• Page_Error事件
• Application_Error事件
• 利用配置文件,自定义错误页面
– <customErrors defaultRedirect="url" mo
de="RemoteOnly">
< error statusCode="code" redirect="url
"></error>
< /customErrors>

异常的例子我就不说了,大家知道的一定比我多,网上也可以搜到很多相关的例子来。

转载:http://www.cnblogs.com/zijinguang/archive/2008/06/06/1215123.html

Asp.Net事务和异常处理:的更多相关文章

  1. asp.net core 自定义异常处理中间件

    asp.net core 自定义异常处理中间件 Intro 在 asp.net core 中全局异常处理,有时候可能不能满足我们的需要,可能就需要自己自定义一个中间件处理了,最近遇到一个问题,有一些异 ...

  2. ASP.NET MVC统一异常处理

    前言: 今早看了篇文章:求知成瘾,却无作品 的思考:很有感触,发现原来自己也是这样,对每样东西都抱有很大的兴趣或者希望自己去学,一年后发现原来自己什么都是皮毛什么都不精!最终发现真正的大牛都是在某一个 ...

  3. ASP.NET事务存储过程

    --修改存储过程 alter proc proc_get_student as select * from student; asp.net 的事务就是针对数据层来处理的呀! 没有数据处理不能使用事务 ...

  4. Oracle 事务和异常处理

    Oracle 的异常和回滚 DECLARE dept_no ) :; BEGIN --开始事务 INSERT INTO dept VALUES (dept_no, '市场部', '北京'); --插入 ...

  5. 说说asp.net中的异常处理和日志追踪

    关于异常的处理想必大家都了解try{}catch(){}finally{},这里就不再讲了.通过在VS里的"调试"-"异常",在弹出的异常对话框里的Common ...

  6. Asp.net MVC 之异常处理

    对于Asp.Net MVC 项目中,对于异常情况下,会跳转到自己定义好的页面,这时就用到了MVC中的异常过滤器(Exception Filters) (1)一旦action 方法中出现异常,异常过滤器 ...

  7. SqlServer 事务和异常处理示例

    BEGIN TRANSACTION--开始事务 DECLARE @errorSun INT --定义错误计数器SET @errorSun=0 --没错为0 UPDATE dbo.Test SET te ...

  8. ASP.NET Core 统一异常处理和返回

    业务场景: 业务需求要求,需要对 ASP.NET Core 异常进行统一处理和返回,比如出现 500 错误和业务服务错误进行不同的处理和返回. 具体实现: using Microsoft.AspNet ...

  9. ASP.NET MVC自定义异常处理

    1.自定义异常处理过滤器类文件 新建MyExceptionAttribute.cs异常处理类文件

随机推荐

  1. jquery uploadify上传文件插件导致浏览器崩溃问题解决方法

    自谷歌浏览器更新到(版本39.0.2171.99 )后,访问上传文件界面浏览器就崩溃了,而其他的浏览器不会出现问题. 出现这种问题的原因就是谷歌浏览器缓存问题,但将访问该jsp页面路径添加上时间戳后无 ...

  2. 【HDOJ】4652 Dice

    1. 题目描述对于m面的骰子.有两种查询,查询0表示求最后n次摇骰子点数相同的期望:查询1表示最后n次摇骰子点数均不相同的期望. 2. 基本思路由期望DP推导,求得最终表达式.(1) 查询0    不 ...

  3. input之placeholder与行高的问题。

    我们实现一个输入框的视觉的时候为了保持其各种各样的兼容性: 1.鼠标要跟文字一样高度. 2.文字要居中对齐. 3.还要有placeholder 第一个目标,当实现一个高度为40像素的高度输入框时,为了 ...

  4. NK 1137: 石子合并问题

     1137: 石子合并问题 Time Limit: 1500 ms    Memory Limit: 10000 kB    Judge type: Multi-cases Total Submit ...

  5. 【转】目前最细致清晰的NSDictionary以及NSMutableDictionary用法总结 -- 不错

    原文网址:http://www.cnblogs.com/wengzilin/archive/2012/03/15/2397712.html 做过Java语言 或者 C语言 开发的朋友应该很清楚 关键字 ...

  6. AM335x(TQ335x)学习笔记——挂载Ramdisk

    上篇文章中我们已经能够通过u-boot启动内核了,但是没有能够启动成功,从内核的log中可以看出,内核启动失败的原因是没有挂载到root文件系统,本文将使用busybox制作根文件系统并打包成ramd ...

  7. 数列极限---和Gauss(取整)函数有关

  8. 消息系统Kafka介绍

    1.  概述 Kafka是Linkedin于2010年12月份开源的消息系统,它主要用于处理活跃的流式数 据.活跃的流式数据在web网站应用中非常常见,这 些数据包括网站的pv.用户访问了什么内容,搜 ...

  9. C#给文件重命名

    使用的主要方法是: File.Move(oldFileDir,newFileDir);//这个是移动文件的方法 Directory.GetFiles(dir);//获取dir路径下的所有文件的全路径 ...

  10. 将UIWebView显示的内容转为图片和PDF

    今天开发MarkEditor时要用到将 UIWebView 中显示的内容转为图片,方便转发到各个社交网络(Twiiter,Facebook,Weibo),这样内容就不受长度限制,类似于长微博. 之前关 ...