使用NHibernate的你也许需要SessionQuicker

NHibernate功能的强大,勿庸置疑。但是很多地方使用起来也颇为繁琐,比如,无法完整的构建数据层、我们很多时候还是需要绕过NHibernate而直接使用ADO.net;比如,任何一次数据访问,哪怕只是简单的数据读取,我们都需要仔细的处理Session、Transaction。如果你的数据层使用NHibernate构建,那么类似下面的代码可能遍地开花:
ITransactiontrans = null ;
ISessionsession
= null ;
try
{
session
= this .factory.OpenSession();
trans
= session.BeginTransaction();

// dot.gifdot.gif访问数据库

trans.Commit();
}
catch (Exceptionee)
{
if (trans != null )
{
trans.Rollback();
}

throw ee;
}
finally
{
session.Close();
}

这种try...catch...finally会在每个需要数据访问的地方重复,这种无聊的Repeat使我忍不住要做点什么。最初,我希望能达到using块的效果,比如像这样:

using (ISessionsession = this .factory.OpenSession())
{
// dot.gifdot.gif数据访问
}

在using块退出的时候,能自动关闭session和提交/回滚Transaction。如果能这样,那真是太完美了!可是,我真的还不知如何去实现它。(如果你知道,一定请告诉我)
于是我只好退而求其次,将上面代码中的注释掉的数据访问代码通过delegate抽取出来,这样那个try...catch...finally块就可以重用了。所以我首先定义了两个delegate,一个没有返回值的delegate用于处理“数据命令”,一个有返回值的delegate用于处理“数据查询”。

public delegate void CbDoSession(ISessionsession);
public delegate object CbDoSessionReturn(ISessionsession);

在此基础上,SessionQuicker就呼之欲出了:

public class SessionQuicker
{
private ISessionFactoryfactory;

#region DataAssemblyName
private string dataAssemblyName = " ApplicationServerSystem " ;
public string DataAssemblyName
{
set
{
this .dataAssemblyName = value;
}
}
#endregion

public void Initialize()
{
Configurationconfig
= new Configuration().AddAssembly( this .dataAssemblyName);
this .factory = config.BuildSessionFactory();
}

#region ActionExceptionHandler
private IExceptionHandleractionExceptionHandler = null ;
public IExceptionHandlerActionExceptionHandler
{
set
{
this .actionExceptionHandler = value;
}
}
#endregion

#region Action
public void Action(CbDoSessiontarget, params object []args)
{
ITransactiontrans
= null ;
ISessionsession
= null ;
try
{
session
= this .factory.OpenSession();
trans
= session.BeginTransaction();
target(session,args);
trans.Commit();
}
catch (Exceptionee)
{
if (trans != null )
{
trans.Rollback();
}

throw ee;
}
finally
{
session.Close();
}
}
#endregion

public object ActionReturnObj(CbDoSessionReturntarget, params object []args)
{
ITransactiontrans
= null ;
ISessionsession
= null ;
try
{
session
= this .factory.OpenSession();
trans
= session.BeginTransaction();
object res = target(session,args);
trans.Commit();

return res;
}
catch (Exceptionee)
{
if (trans != null )
{
trans.Rollback();
}

throw ee;
}
finally
{
session.Close();
}
}


#region safty

public void ActionSafty(CbDoSessiontarget, params object []args)
{
try
{
this .Action(target,args);
}
catch (Exceptionee)
{
if ( this .actionExceptionHandler != null )
{
this .actionExceptionHandler.HanleException(ee);
}
}
}

public object ActionReturnObjSafty(CbDoSessionReturntarget, params object []args)
{
try
{
return this .ActionReturnObj(target,args);
}
catch (Exceptionee)
{
if ( this .actionExceptionHandler != null )
{
this .actionExceptionHandler.HanleException(ee);
}

return null ;
}
}

#endregion
}

public delegate void CbDoSession(ISessionsession, params object []args);
public delegate object CbDoSessionReturn(ISessionsession, params object []args);

在SessionQuicker的帮助下,你可以更简单的进行数据访问,比如:

private void OnButton1_Click( object sender,EventArgsargs)
{
IListlist
= (IList)sessionQuicker.ActionReturnObj( new CbDoSessionReturn( this .ReadStudentList));
// dot.gif处理list
}

private object ReadStudentList(ISessionss)
{
IQueryquery
= ss.CreateQuery( " fromStudentasstuwherestu.Age>:studentAge " );
query.SetInt32(
" studentAge " , 20 );
return query.List();
}

SessionQuicker的好处是避免了每次数据访问写重复的try...catch...finally块,但是与前面理想的using块比起来,优雅性就要差许多。
我期待着有人提出更优雅的解决方案!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值