1. BLL层事务:
简单的BLL层的事物, 使用TransactionScope就可以, 在TransactionScope的代码块中, 无错误就调用TransactionScope对象上的Complete()方法提交数据, 若有错就自动回滚.
值得注意的是, 对于使用DataSet、DataTable等无连接存取数据时, 如果要实现BLL层事物, 则需要给出一个状态为Open的Connection. 详见文章中的System.Transactions and ADO.NET 2.0 (英文的).
//示例代码:
//DAL/Utility.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using System.Data;
namespace DAL
{
public class Utility
{
public static void ExeNoQuery( string sqlStr, string constr, CommandType type, params SqlParameter[] param)
{
SqlConnection con = new SqlConnection(constr);
SqlCommand com = new SqlCommand();
com.Connection = con;
com.CommandType = type;
com.CommandText = sqlStr;
if (type == CommandType.StoredProcedure)
{
for ( int i = 0 ; i < param.Length; i ++ )
{
if (param[i].Value as string == string .Empty)
{
param[i].Value = DBNull.Value;
}
com.Parameters.Add(param[i]);
}
}
try
{
con.Open();
com.ExecuteNonQuery();
}
catch (Exception ex)
{
throw ;
}
finally
{
if (con.State == ConnectionState.Open)
con.Close();
}
}
public static DataSet ExeDataSet( string sqlStr, string constr, CommandType type, params SqlParameter[] param)
{
SqlConnection con = new SqlConnection(constr);
SqlCommand com = new SqlCommand();
com.Connection = con;
com.CommandType = type;
com.CommandText = sqlStr;
if (type == CommandType.StoredProcedure)
{
for ( int i = 0 ; i < param.Length; i ++ )
com.Parameters.Add(param[i]);
}
DataSet ds = new DataSet();
SqlDataAdapter da = new SqlDataAdapter();
da.SelectCommand = com;
try
{
da.Fill(ds);
}
catch (Exception ex)
{
}
return ds;
}
public static SqlDataReader ExeQuery( string sqlStr, string constr, CommandType type, params SqlParameter[] param)
{
SqlDataReader dr = null ;
SqlConnection con = new SqlConnection(constr);
SqlCommand com = new SqlCommand();
com.Connection = con;
com.CommandType = type;
com.CommandText = sqlStr;
if (type == CommandType.StoredProcedure)
{
for ( int i = 0 ; i < param.Length; i ++ )
com.Parameters.Add(param[i]);
}
try
{
con.Open();
dr = com.ExecuteReader(CommandBehavior.CloseConnection);
}
catch (Exception ex)
{
}
return dr;
}
}
}
//DAL/EmployeeDAL.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DAL
{
public class EmployeeDAL
{
private static readonly string constr = System.Configuration.ConfigurationManager.ConnectionStrings[ " MsSql " ].ConnectionString;
public void InsertEmployee( string employeename, int departmentid)
{
System.Data.SqlClient.SqlParameter p_name = new System.Data.SqlClient.SqlParameter( " @ename " , System.Data.SqlDbType.NVarChar, 30 );
p_name.Value = employeename;
System.Data.SqlClient.SqlParameter p_depid = new System.Data.SqlClient.SqlParameter( " @depid " , System.Data.SqlDbType.Int);
p_depid.Value = departmentid;
Utility.ExeNoQuery( " SP_AddEmployee " , constr, System.Data.CommandType.StoredProcedure, p_name, p_depid);
}
}
}
//DAL/DepartmentDAL.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DAL
{
public class DepartmentDAL
{
private static readonly string constr = System.Configuration.ConfigurationManager.ConnectionStrings[ " MsSql " ].ConnectionString;
public int InsertDepartment( string departmentname)
{
int depid = - 1 ;
System.Data.SqlClient.SqlParameter p_name = new System.Data.SqlClient.SqlParameter( " @depname " , System.Data.SqlDbType.NVarChar, 30 );
p_name.Value = departmentname;
System.Data.SqlClient.SqlParameter p_id = new System.Data.SqlClient.SqlParameter( " @return_value " , System.Data.SqlDbType.Int);
p_id.Direction = System.Data.ParameterDirection.ReturnValue;
Utility.ExeNoQuery( " SP_AddDepartment " , constr, System.Data.CommandType.StoredProcedure, p_name, p_id);
depid = ( int )p_id.Value;
return depid;
}
}
}
//BLL/DepartmentBLL.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BLL
{
public class DepartmentBLL
{
#region 全局变量
DAL.DepartmentDAL dd = new DAL.DepartmentDAL();
DAL.EmployeeDAL ed = new DAL.EmployeeDAL();
#endregion
public void AddDepartmentWithSomeEmployees( string departmentname, params string [] employeenames)
{
// 添加System.Transactions.dll.
// 开启分布式事务支持:把 C:\WINDOWS\system32\dtclog 这个目录重命名(如果有),然后重新建立该目录。然后在命令行下: msdtc -resetlog
// 在“开始”->“设置”->“控制面板”->“管理工具”->“组件服务”中,“控制台根目录”->“组件服务”->“计算机”->“我的电脑”->“COM+应用程序”中,有一个“IIS Out-Of-Process Pooled”鼠标右键“属性”--“标识”--把“此用户”调整为“交互式用户--目前已登录的用户”。然后“确定”,再鼠标右键“属性”--“启动.
using (System.Transactions.TransactionScope ts = new System.Transactions.TransactionScope())
{
int departmentid = dd.InsertDepartment(departmentname);
for ( int i = 0 ; i < employeenames.Length; i ++ )
{
ed.InsertEmployee(employeenames[i], departmentid);
}
ts.Complete();
}
}
}
}
//UI/Default.aspx
<% @ Page Language = " C# " AutoEventWireup = " true " CodeFile = " Default.aspx.cs " Inherits = " _Default " %>
<! DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" >
< html xmlns ="http://www.w3.org/1999/xhtml" >
< head runat ="server" >
< title ></ title >
</ head >
< body >
< form id ="form1" runat ="server" >
< div >
< span > 部门: </ span >< asp:TextBox ID ="txt_dep" runat ="server" ></ asp:TextBox >
< hr />
< span > 员工1: </ span >< asp:TextBox ID ="txt_emp1" runat ="server" ></ asp:TextBox >
< span > 员工2: </ span >< asp:TextBox ID ="txt_emp2" runat ="server" ></ asp:TextBox >
< span > 员工3: </ span >< asp:TextBox ID ="txt_emp3" runat ="server" ></ asp:TextBox >
< asp:LinkButton ID ="lbtn_submit" runat ="server" onclick ="lbtn_submit_Click" > 添加 </ asp:LinkButton >
</ div >
</ form >
</ body >
</ html >
//UI/default.aspx.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class _Default : System.Web.UI.Page
{
#region 全局变量
BLL.DepartmentBLL db = new BLL.DepartmentBLL();
#endregion
protected void Page_Load( object sender, EventArgs e)
{
}
protected void lbtn_submit_Click( object sender, EventArgs e)
{
db.AddDepartmentWithSomeEmployees( this .txt_dep.Text, this .txt_emp1.Text, this .txt_emp2.Text, this .txt_emp3.Text);
}
}
//创建表的Sql命令
create database BLLTransactionDemo
go
use BLLTransactionDemo
go
if exists ( select [ name ] from sysobjects where [ name ] = ' T_Employee ' and [ type ] = ' U ' )
drop table T_Employee
go
create table T_Employee
(
eid int identity primary key not null ,
ename nvarchar ( 30 ) not null ,
depid int
)
go
if exists ( select [ name ] from sysobjects where [ name ] = ' T_Department ' and [ type ] = ' U ' )
drop table T_Department
go
create table T_Department
(
depid int identity primary key not null ,
depname nvarchar ( 30 ) not null
)
go
if exists ( select [ name ] from sysobjects where [ name ] = ' SP_AddDepartment ' and [ type ] = ' P ' )
drop procedure SP_AddDepartment
go
create procedure SP_AddDepartment
(
@depname nvarchar ( 30 )
)
as
begin
insert into T_Department(depname) values ( @depname );
return @@identity ;
end
go
exec SP_AddDepartment ' 32 '
if exists ( select [ name ] from sysobjects where [ name ] = ' SP_AddEmployee ' and [ type ] = ' P ' )
drop procedure SP_AddEmployee
go
create procedure SP_AddEmployee
(
@ename nvarchar ( 30 ),
@depid int
)
as
begin
insert into T_Employee(ename,depid) values ( @ename , @depid )
end
go
exec SP_AddEmployee ' 王 ' , 10
select * from T_employee
select * from T_department
2. asp.net的错误处理机制(简述):
asp.net的错误处理机制共分3个层次, 代码级的错误处理, 页面级的错误处理, 网站级的错误处理.
首先, 代码级的错误处理: 很简单,就是try...catch的使用
其次, 页面级的错误处理: 在页面事件处理方法中抛出的异常可以被IHttpHandler中约定的ProcessRequest方法所捕获, 可以通过页面处理对象的Error事件来处理异常.但是Error事件的委托类型是EventHandler, 换句话说就是它无法获得异常信息. 这时, 可以通过HttpContext获得Server对象, 该对象提供了public Exception GetLastError()和pulic void ClearError()两个方法来处理异常. 若,页面级处理了异常, 异常将不再会被抛出到应用程序中.
最后, 网站级的错误处理: 可以在HttpApplication对象的Error事件中处理, 可以再IHttpModule中处理, 但为简单起见, 更常见的是在Global.asax中处理. 值得注意的是, 此时的异常已被包装, 需要通过Server.GetLastException().InnerException来获取异常.
网站级别的异常处理的配置: 当网站出现未处理的异常时, 可以通过web.config文件中的customErrors元素进行配置(mode有3种可选值,off关闭错误处理, 直接显示异常给客户;On想所有用户返回自定义错误信息页面;RemoteOnly向远程用户返回自定义错误信息页面, 向本级客户返回错误详细内容.), 且defaultRedirect属性用来指出自定义的错误信息页面的URL地址(地址可以是相对的, 也可以使绝对的, 相对地址是针对网站根目录的).