SubSonic使用起来非常像Rails中的ActiveRecord,不仅将代码生成工具集成到了IDE中,而且还可以自己来定制模板。虽然还存在问题,但现在的版本是可以满足日常开发了。
由于把数据库操作封装起来了,因此现有的事务处理方式并不能满足需求,在这之前一直在使用Castle ActiveRecord进行开发,它提供的TransactionScope使用非常方便,这次改造也得益于Castle ActiveRecord。
一、DataProvider改造
添加如下代码:
//
jy
protected bool _IsNeedTransaction = false ;
protected DbTransaction _Transaction;
internal void BeginShareTransaction()
{
if (__sharedConnection == null ||
__sharedConnection.State != ConnectionState.Open)
{
InitializeSharedConnection();
}
_Transaction = __sharedConnection.BeginTransaction();
_IsNeedTransaction = true ;
}
internal void BeginShareTransaction(IsolationLevel level)
{
if (__sharedConnection == null ||
__sharedConnection.State != ConnectionState.Open)
{
InitializeSharedConnection();
}
_Transaction = __sharedConnection.BeginTransaction(level);
_IsNeedTransaction = true ;
}
internal void PrcessTransaction( bool rollback)
{
try
{
if (_Transaction != null )
{
if ( ! rollback)
{
_Transaction.Commit();
}
else
{
_Transaction.Rollback();
}
}
else
{
throw new ApplicationException( " 请先实例化TrancactionScope类启动事务! " );
}
}
finally
{
if (__sharedConnection.State == ConnectionState.Open)
{
__sharedConnection.Close();
}
__sharedConnection.Dispose();
}
}
// jy end
protected bool _IsNeedTransaction = false ;
protected DbTransaction _Transaction;
internal void BeginShareTransaction()
{
if (__sharedConnection == null ||
__sharedConnection.State != ConnectionState.Open)
{
InitializeSharedConnection();
}
_Transaction = __sharedConnection.BeginTransaction();
_IsNeedTransaction = true ;
}
internal void BeginShareTransaction(IsolationLevel level)
{
if (__sharedConnection == null ||
__sharedConnection.State != ConnectionState.Open)
{
InitializeSharedConnection();
}
_Transaction = __sharedConnection.BeginTransaction(level);
_IsNeedTransaction = true ;
}
internal void PrcessTransaction( bool rollback)
{
try
{
if (_Transaction != null )
{
if ( ! rollback)
{
_Transaction.Commit();
}
else
{
_Transaction.Rollback();
}
}
else
{
throw new ApplicationException( " 请先实例化TrancactionScope类启动事务! " );
}
}
finally
{
if (__sharedConnection.State == ConnectionState.Open)
{
__sharedConnection.Close();
}
__sharedConnection.Dispose();
}
}
// jy end
二、添加TransactionScope类
using
System;
using System.Collections.Generic;
using System.Text;
using System.Data.Common;
using System.Data;
namespace SubSonic
{
/// <summary>
/// 使用共享连接完成事务处理。
/// </summary>
public class TransactionScope : IDisposable
{
DataProvider _Provider = null ;
bool _IsRollback = false ;
#region 构造函数
/// <summary>
/// 构造函数,开始事务处理。
/// </summary>
public TransactionScope()
{
_Provider = DataService.GetInstance( null );
_Provider.BeginShareTransaction();
}
/// <summary>
/// 构造函数,开始事务处理。
/// </summary>
/// <param name="level"> 事务级别 </param>
public TransactionScope(IsolationLevel level)
{
_Provider = DataService.GetInstance( null );
_Provider.BeginShareTransaction(level);
}
/// <summary>
/// 构造函数,开始事务处理。
/// </summary>
/// <param name="ProviderName"> 提供器名称 </param>
public TransactionScope( string ProviderName)
{
_Provider = DataService.GetInstance(ProviderName);
_Provider.BeginShareTransaction();
}
/// <summary>
/// 构造函数,开始事务处理。
/// </summary>
/// <param name="ProviderName"> 提供器名称 </param>
/// <param name="level"> 事务级别 </param>
public TransactionScope( string ProviderName,IsolationLevel level)
{
_Provider = DataService.GetInstance(ProviderName);
_Provider.BeginShareTransaction(level);
}
#endregion
/// <summary>
/// 标记为提交状态。
/// </summary>
public void VoteCommit()
{
if (_IsRollback)
{
throw new ApplicationException( " 当前事务已回滚,不能再进行提交操作! " );
}
}
/// <summary>
/// 标记为回滚状态。
/// </summary>
public void VoteRollback()
{
_IsRollback = true ;
}
#region IDisposable 成员
/// <summary>
///
/// </summary>
public void Dispose()
{
_Provider.PrcessTransaction(_IsRollback);
}
#endregion
}
}
using System.Collections.Generic;
using System.Text;
using System.Data.Common;
using System.Data;
namespace SubSonic
{
/// <summary>
/// 使用共享连接完成事务处理。
/// </summary>
public class TransactionScope : IDisposable
{
DataProvider _Provider = null ;
bool _IsRollback = false ;
#region 构造函数
/// <summary>
/// 构造函数,开始事务处理。
/// </summary>
public TransactionScope()
{
_Provider = DataService.GetInstance( null );
_Provider.BeginShareTransaction();
}
/// <summary>
/// 构造函数,开始事务处理。
/// </summary>
/// <param name="level"> 事务级别 </param>
public TransactionScope(IsolationLevel level)
{
_Provider = DataService.GetInstance( null );
_Provider.BeginShareTransaction(level);
}
/// <summary>
/// 构造函数,开始事务处理。
/// </summary>
/// <param name="ProviderName"> 提供器名称 </param>
public TransactionScope( string ProviderName)
{
_Provider = DataService.GetInstance(ProviderName);
_Provider.BeginShareTransaction();
}
/// <summary>
/// 构造函数,开始事务处理。
/// </summary>
/// <param name="ProviderName"> 提供器名称 </param>
/// <param name="level"> 事务级别 </param>
public TransactionScope( string ProviderName,IsolationLevel level)
{
_Provider = DataService.GetInstance(ProviderName);
_Provider.BeginShareTransaction(level);
}
#endregion
/// <summary>
/// 标记为提交状态。
/// </summary>
public void VoteCommit()
{
if (_IsRollback)
{
throw new ApplicationException( " 当前事务已回滚,不能再进行提交操作! " );
}
}
/// <summary>
/// 标记为回滚状态。
/// </summary>
public void VoteRollback()
{
_IsRollback = true ;
}
#region IDisposable 成员
/// <summary>
///
/// </summary>
public void Dispose()
{
_Provider.PrcessTransaction(_IsRollback);
}
#endregion
}
}
三、SqlDataProvider改造
在每一个新建了SqlCommand的地方都添加以下代码:
//
jy
if (_IsNeedTransaction)
{
cmd.Transaction = _Transaction as SqlTransaction;
}
// jy end
if (_IsNeedTransaction)
{
cmd.Transaction = _Transaction as SqlTransaction;
}
// jy end
其它数据库提供器的也使用相同的方法进行改造。
四、使用示例
///
<summary>
/// 收货处理。
/// </summary>
/// <param name="id"></param>
/// <param name="UserId"></param>
public static void Receiving( object id, object UserId)
{
using (TransactionScope tran = new TransactionScope())
{
try
{
LogiPackage lp = new LogiPackage(id);
string strSql = "" ;
LogiWarehouse lw = new LogiWarehouse();
LogiPackageDetailCollection lpds = lp.LogiPackageDetails();
// foreach (LogiPackageDetail d in lpds)
// {
// Query q = LogiWarehouse.Query();
// q.AddWhere("Freight_Id", d.FreightId);
// // 检查发送人的库存
// q.AND("Company_Id", lp.SendId);
// lw.LoadAndCloseReader(q.ExecuteReader());
// // if (lw.Count < d.Count)
// // {
// // throw new ProcessErrorException("库存不足,请检查!");
// // }
// }
foreach (LogiPackageDetail d in lpds)
{
Add(lp.InceptId, d.FreightId, d.Count);
Dec(lp.SendId, d.FreightId, d.Count);
}
LogiPackageStatus lps = new LogiPackageStatus( " Code " , 3 );
lp.StatuId = lps.Id;
lp.Save();
Log( new Guid(UserId.ToString()), lps.Id, lp.Id);
tran.VoteCommit();
}
catch
{
tran.VoteRollback();
throw ;
}
}
/// 收货处理。
/// </summary>
/// <param name="id"></param>
/// <param name="UserId"></param>
public static void Receiving( object id, object UserId)
{
using (TransactionScope tran = new TransactionScope())
{
try
{
LogiPackage lp = new LogiPackage(id);
string strSql = "" ;
LogiWarehouse lw = new LogiWarehouse();
LogiPackageDetailCollection lpds = lp.LogiPackageDetails();
// foreach (LogiPackageDetail d in lpds)
// {
// Query q = LogiWarehouse.Query();
// q.AddWhere("Freight_Id", d.FreightId);
// // 检查发送人的库存
// q.AND("Company_Id", lp.SendId);
// lw.LoadAndCloseReader(q.ExecuteReader());
// // if (lw.Count < d.Count)
// // {
// // throw new ProcessErrorException("库存不足,请检查!");
// // }
// }
foreach (LogiPackageDetail d in lpds)
{
Add(lp.InceptId, d.FreightId, d.Count);
Dec(lp.SendId, d.FreightId, d.Count);
}
LogiPackageStatus lps = new LogiPackageStatus( " Code " , 3 );
lp.StatuId = lps.Id;
lp.Save();
Log( new Guid(UserId.ToString()), lps.Id, lp.Id);
tran.VoteCommit();
}
catch
{
tran.VoteRollback();
throw ;
}
}
目前已成功在http://www.massany.com和帮朋友做的一个物流系统中使用。
有更好的改进建议,希望大家交流一下!SubSonic修改过的工程下载: http://files.cnblogs.com/jinyong/subsonic2.1.zip