gaoxiang

专注于.NET技术

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

                
//访问数据库

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

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

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

            using(ISession session = this.factory.OpenSession())
            {
                
//数据访问
            }

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

    public delegate void   CbDoSession(ISession session) ;
    
public delegate object CbDoSessionReturn(ISession session) ;

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

    public class SessionQuicker
    {
        
private ISessionFactory factory ;

        
public SessionQuicker(ISessionFactory fac)
        {
            
this.factory = fac ;
        }

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

        
public void Action(CbDoSession target)
        {
            ITransaction trans 
= null ;
            ISession session 
= null ;
            
try
            {
                session 
= this.factory.OpenSession();
                trans 
= session.BeginTransaction(); 
                target(session) ;
              
  trans.Commit();                
            }
            
catch (Exception ee)
            {                
                
if(trans != null)
                {
                    trans.Rollback();
                }

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

        
public void ActionSafty(CbDoSession target)
        {
            
try
            {
                
this.Action(target) ;
            }
            
catch(Exception ee)
            {
                
if(this.actionExceptionHandler != null)
                {
                    
this.actionExceptionHandler.HanleException(ee) ;
                }
            }
        }

        
public object ActionReturnObj(CbDoSessionReturn target)
        {
            ITransaction trans 
= null ;
            ISession session 
= null ;
            
try
            {
                session 
= this.factory.OpenSession();
                trans 
= session.BeginTransaction(); 
                
object res = target(session) ;
                trans.Commit();                

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

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

        
public object ActionReturnObjSafty(CbDoSessionReturn target)
        {
            
try
            {
                
return this.ActionReturnObj(target) ;
            }
            
catch(Exception ee)
            {
                
if(this.actionExceptionHandler != null)
                {
                    
this.actionExceptionHandler.HanleException(ee) ;
                }

                
return null ;
            }
        }
    }

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

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

        
private object ReadStudentList(ISession ss)
        {    
            IQuery query 
= ss.CreateQuery("from Student as stu where stu.Age > :studentAge" ) ;
            query.SetInt32(
"studentAge" ,20) ;
            
return query.List() ;         
        }

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

posted on 2006-05-18 14:42  S孤单一吻S  阅读(140)  评论(0)    收藏  举报