//by lostinet.com
using System;
using System.Collections;
using System.Data.SqlClient;namespace ct
{
public class SqlScopeException:Exception
{
public SqlScopeException(string message)
:base(message)
{
}
public SqlScopeException(string message,Exception innerException)
:base(message,innerException)
{
}
}
/// <summary>
/// 通过传递SqlScope,实现SqlConnection,SqlTransaction的创建,起用,传递和释放
/// </summary>
public class SqlScope:IDisposable
{
string connString;
SqlConnection conn=null;
SqlTransaction trans=null;
Stack stack=null; public SqlConnection Connection
{
get
{
CheckConnection();
return conn;
}
}
public SqlTransaction Transaction
{
get
{
CheckConnection();
return trans;
}
}
public string ConnectionString
{
get
{
return connString;
}
}
static public implicit operator SqlConnection (SqlScope ss)
{
return ss.Connection;
}
static public implicit operator SqlTransaction (SqlScope ss)
{
return ss.Transaction;
} public SqlScope(string ConnectionString)
{
if(ConnectionString==null)
throw(new ArgumentNullException("ConnectionString"));
connString=ConnectionString;
}
~SqlScope()
{
Dispose();
}
public void Dispose()
{
stack=null;
try
{
if(trans!=null)
trans.Dispose();
}
finally
{
try
{
if(conn!=null)
conn.Dispose();
}
finally
{
conn=null;
trans=null;
}
}
}
void OpenConnection(bool beginTransaction)
{
if(stack!=null)
throw(new SqlScopeException("Connection已经被打开!"));
stack=new Stack();
conn=new SqlConnection(connString);
conn.Open();
if(beginTransaction)
trans=conn.BeginTransaction("trans");
}
void CheckConnection()
{
if(stack==null)
throw(new SqlScopeException("Connection没有打开或者已经被关闭"));
}
public SqlCommand CreateCommand(string commandText)
{
if(commandText==null)
throw(new ArgumentNullException("commandText"));
CheckConnection();
return new SqlCommand(commandText,conn,trans);
}
public SqlDataAdapter CreateAdapter(string commandText)
{
if(commandText==null)
throw(new ArgumentNullException("commandText"));
CheckConnection();
return new SqlDataAdapter(CreateCommand(commandText));
}
/// <summary>
/// 和Commit或Rollback对应
/// </summary>
public void BeginTransaction()
{
if(stack==null)
{
try
{
OpenConnection(true);
}
catch(Exception x)
{
Dispose();
throw(x);
}
}
else
{
trans.Save("trans"+stack.Count.ToString());
}
stack.Push(true);
}
public void Commit()
{
CheckConnection();
bool isTrans=(bool)stack.Peek();
if(!isTrans)
throw(new SqlScopeException("不能使用Commit,因为对应的一次调用不是BeginTransaction"));
stack.Pop();
if(stack.Count==0)
{
try
{
trans.Commit();
}
finally
{
Dispose();
}
}
}
public void Rollback()
{
CheckConnection();
bool isTrans=(bool)stack.Peek();
if(!isTrans)
throw(new SqlScopeException("不能使用Rollback,因为对应的一次调用不是BeginTransaction"));
stack.Pop();
if(stack.Count==0)
{
trans.Rollback("trans");
Dispose();
}
else
{
trans.Rollback("trans"+stack.Count.ToString());
}
} /// <summary>
/// 和EnterQuery对应,和BeginTransaction不同之处,是它不会启动Transaction
/// </summary>
public void EnterQuery()
{
if(stack==null)
{
OpenConnection(false);
}
stack.Push(false);
}
public void LeaveQuery()
{
CheckConnection();
bool isTrans=(bool)stack.Peek();
if(isTrans)
throw(new SqlScopeException("不能使用LeaveQuery,因为对应的一次调用不是EnterQuery"));
stack.Pop();
if(stack.Count==0)
{
Dispose();
}
}
}
}
using System;
using System.Collections;
using System.Data.SqlClient;namespace ct
{
public class SqlScopeException:Exception
{
public SqlScopeException(string message)
:base(message)
{
}
public SqlScopeException(string message,Exception innerException)
:base(message,innerException)
{
}
}
/// <summary>
/// 通过传递SqlScope,实现SqlConnection,SqlTransaction的创建,起用,传递和释放
/// </summary>
public class SqlScope:IDisposable
{
string connString;
SqlConnection conn=null;
SqlTransaction trans=null;
Stack stack=null; public SqlConnection Connection
{
get
{
CheckConnection();
return conn;
}
}
public SqlTransaction Transaction
{
get
{
CheckConnection();
return trans;
}
}
public string ConnectionString
{
get
{
return connString;
}
}
static public implicit operator SqlConnection (SqlScope ss)
{
return ss.Connection;
}
static public implicit operator SqlTransaction (SqlScope ss)
{
return ss.Transaction;
} public SqlScope(string ConnectionString)
{
if(ConnectionString==null)
throw(new ArgumentNullException("ConnectionString"));
connString=ConnectionString;
}
~SqlScope()
{
Dispose();
}
public void Dispose()
{
stack=null;
try
{
if(trans!=null)
trans.Dispose();
}
finally
{
try
{
if(conn!=null)
conn.Dispose();
}
finally
{
conn=null;
trans=null;
}
}
}
void OpenConnection(bool beginTransaction)
{
if(stack!=null)
throw(new SqlScopeException("Connection已经被打开!"));
stack=new Stack();
conn=new SqlConnection(connString);
conn.Open();
if(beginTransaction)
trans=conn.BeginTransaction("trans");
}
void CheckConnection()
{
if(stack==null)
throw(new SqlScopeException("Connection没有打开或者已经被关闭"));
}
public SqlCommand CreateCommand(string commandText)
{
if(commandText==null)
throw(new ArgumentNullException("commandText"));
CheckConnection();
return new SqlCommand(commandText,conn,trans);
}
public SqlDataAdapter CreateAdapter(string commandText)
{
if(commandText==null)
throw(new ArgumentNullException("commandText"));
CheckConnection();
return new SqlDataAdapter(CreateCommand(commandText));
}
/// <summary>
/// 和Commit或Rollback对应
/// </summary>
public void BeginTransaction()
{
if(stack==null)
{
try
{
OpenConnection(true);
}
catch(Exception x)
{
Dispose();
throw(x);
}
}
else
{
trans.Save("trans"+stack.Count.ToString());
}
stack.Push(true);
}
public void Commit()
{
CheckConnection();
bool isTrans=(bool)stack.Peek();
if(!isTrans)
throw(new SqlScopeException("不能使用Commit,因为对应的一次调用不是BeginTransaction"));
stack.Pop();
if(stack.Count==0)
{
try
{
trans.Commit();
}
finally
{
Dispose();
}
}
}
public void Rollback()
{
CheckConnection();
bool isTrans=(bool)stack.Peek();
if(!isTrans)
throw(new SqlScopeException("不能使用Rollback,因为对应的一次调用不是BeginTransaction"));
stack.Pop();
if(stack.Count==0)
{
trans.Rollback("trans");
Dispose();
}
else
{
trans.Rollback("trans"+stack.Count.ToString());
}
} /// <summary>
/// 和EnterQuery对应,和BeginTransaction不同之处,是它不会启动Transaction
/// </summary>
public void EnterQuery()
{
if(stack==null)
{
OpenConnection(false);
}
stack.Push(false);
}
public void LeaveQuery()
{
CheckConnection();
bool isTrans=(bool)stack.Peek();
if(isTrans)
throw(new SqlScopeException("不能使用LeaveQuery,因为对应的一次调用不是EnterQuery"));
stack.Pop();
if(stack.Count==0)
{
Dispose();
}
}
}
}
解决方案 »
- 新人问自定义控件问题
- 如何实现如浏览器的选项卡那样可以远程调用网站的ICO图标
- VS 2005 professional Edition 没有windows service项目?
- 在前台页面中,带后台参数的链接怎么写?
- dataset 与 hashtable ?
- 简单代码:C# + Access数据库 添加记录总出错
- txtBOX文本框绑定后,为何不随DataGrid,comboBox连动?谢谢指导
- web程序无法访问网络路径上的文件
- 关于使用setInterval不断刷新显示SQL数据表记录数问题
- 在.NET SDK中找不到CoolBar。
- datagrid 问题,欢迎高手指教
- Borland将于年末推出完整的Delphi.net开发平台
using System;
using System.Data;
using System.Data.SqlClient;namespace ct
{
class Class1
{
static string ConnectionString
{
get
{
return "server=(local);trusted_connection=true;database=northwind;";
}
} static void BuildTable()
{
using(SqlScope ss=new SqlScope(ConnectionString))
{
ss.BeginTransaction();
using(SqlCommand cmd=ss.CreateCommand(
@"
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[test]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [dbo].[test]CREATE TABLE [dbo].[test] (
[id] [int] IDENTITY (1, 1) NOT NULL ,
[text] [nvarchar] (1000) COLLATE Chinese_PRC_CI_AS NOT NULL
) ON [PRIMARY]ALTER TABLE [dbo].[test] WITH NOCHECK ADD
CONSTRAINT [PK_test] PRIMARY KEY CLUSTERED
(
[id]
) ON [PRIMARY]
"
))
{
cmd.ExecuteNonQuery();
} ss.Commit(); //并不需要使用Rollback,因为SqlScope是在这里被创建的。
//如果ss没有被提交,最后Dispose时会自动Rollback
}
}
static int InsertText(SqlScope ss,string text)
{
using(SqlCommand cmd=ss.CreateCommand(
@"
SET NOCOUNT ON
INSERT INTO test(text) VALUES(@text)
SET NOCOUNT OFF
SELECT SCOPE_IDENTITY();
"
))
{
cmd.Parameters.Add("@text",SqlDbType.NVarChar,1000).Value=text;
return Convert.ToInt32(cmd.ExecuteScalar());
}
}
[STAThread]
static void Main(string[] args)
{
BuildTable(); Console.WriteLine("开始ExecuteA");
ExecuteA("Call ExecuteA In Main");
Console.WriteLine();
using(SqlScope ss=new SqlScope(ConnectionString))
{
ss.BeginTransaction(); //以下的调用是共用一个Connection和Transaction try
{
Console.WriteLine();
Console.WriteLine("开始ExecuteB");
ExecuteB(ss);
}
catch
{
}
try
{
Console.WriteLine();
Console.WriteLine("开始ExecuteC");
ExecuteC(ss);
}
catch
{
}
try
{
Console.WriteLine();
Console.WriteLine("开始ExecuteD");
ExecuteD(ss);
}
catch
{
} ss.Commit();
} using(SqlScope ss=new SqlScope(ConnectionString))
{
//ss在这里并没有调用BeginTransaction
//在ExecuteD里,不会产生事务。
try
{
Console.WriteLine();
Console.WriteLine("最后一次调用ExecuteD");
ExecuteD(ss);
}
catch
{
}
}
} static void ExecuteA(string msg)
{
SqlScope ss=new SqlScope(ConnectionString);
ss.BeginTransaction();
try
{ int msgid=InsertText(ss,msg);
Console.WriteLine("A msgid={0} OK",msgid); ExecuteB(ss); try
{
ExecuteC(ss);
ExecuteD(ss);
}
catch
{
//忽略C,D的异常。
} //到这里提交结果。
ss.Commit();
}
catch(Exception x)
{
ss.Rollback(); Console.WriteLine("A异常 : "+x.Message);
throw(x);
}
} static void ExecuteB(SqlScope ss)
{
ss.BeginTransaction();
try
{ int msgid=InsertText(ss,null);//异常。text不能为NULL
Console.WriteLine("B msgid={0} OK",msgid); ExecuteC(ss);
ExecuteD(ss); ss.Commit();
}
catch(Exception x)
{
//异常后回滚 B 的操作,但是不影响调用 B 的外部程序。例如 Main 或 A
ss.Rollback(); Console.WriteLine("B异常 : "+x.Message);
}
}
static void ExecuteC(SqlScope ss)
{
ss.BeginTransaction();
try
{
int msgid=InsertText(ss,"ExecuteC..");
Console.WriteLine("C msgid={0} OK",msgid);
//可以见到有C msgid={0} OK的输出。
//但是因为下面D抛出了异常。所以后面的Rollback被调用了 ExecuteD(ss); ss.Commit();
}
catch(Exception x)
{
ss.Rollback(); Console.WriteLine("C异常 : "+x.Message);
}
}
static void ExecuteD(SqlScope ss)
{
ss.EnterQuery();
//try,finally是必须的。
//必须保证调用了EnterQuery后能调用LeaveQuery try
{
DataSet ds=new DataSet(); using(SqlDataAdapter sda=ss.CreateAdapter("SELECT * FROM test WHERE id=2003"))
{
sda.Fill(ds);
string text=ds.Tables[0].Rows[0]["text"].ToString();//异常。Rows.Count为0
Console.WriteLine("D getmsg:{0}",text);
} }
catch(Exception x)
{
Console.WriteLine("D异常 : "+x.Message);
throw(x);
}
finally
{
ss.LeaveQuery();
}
}
}
}