zoukankan      html  css  js  c++  java
  • 使用NHibernate的你也许需要SessionQuicker

        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 ;    
            
            
    #region DataAssemblyName
            
    private string dataAssemblyName = "ApplicationServerSystem" ; 
            
    public  string DataAssemblyName
            {
                
    set
                {
                    
    this.dataAssemblyName = value ;
                }
            }
            
    #endregion        

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

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

            
    #region Action
            
    public void Action(CbDoSession target ,params object[] args)
            {
                ITransaction trans 
    = null ;
                ISession session 
    = null ;
                
    try
                {
                    session 
    = this.factory.OpenSession();
                    trans 
    = session.BeginTransaction(); 
                    target(session ,args) ;
                    trans.Commit();                
                }
                
    catch (Exception ee)
                {                
                    
    if(trans != null)
                    {
                        trans.Rollback();
                    }

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

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

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

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


            
    #region safty
            
            
    public void ActionSafty(CbDoSession target ,params object[] args)
            {
                
    try
                {
                    
    this.Action(target ,args) ;
                }
                
    catch(Exception ee)
                {
                    
    if(this.actionExceptionHandler != null)
                    {
                        
    this.actionExceptionHandler.HanleException(ee) ;
                    }
                }
            }
            
            
    public object ActionReturnObjSafty(CbDoSessionReturn target ,params object[] args)
            {
                
    try
                {
                    
    return this.ActionReturnObj(target ,args) ;
                }
                
    catch(Exception ee)
                {
                    
    if(this.actionExceptionHandler != null)
                    {
                        
    this.actionExceptionHandler.HanleException(ee) ;
                    }

                    
    return null ;
                }
            }
            
            
    #endregion
        }

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

        在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块比起来,优雅性就要差许多。
        我期待着有人提出更优雅的解决方案!

  • 相关阅读:
    二维坐标离散化
    unique()函数使用
    如果你的unordered_map头文件报错请看这里
    string删除与查找erase,find
    2017 ACM-ICPC, Universidad Nacional de Colombia Programming Contest K
    2017-2018 ACM-ICPC Pacific Northwest Regional Contest (Div. 2) P-Fear Factoring 区间内数的所有因数的和(除法分块)
    .NETCore使用EntityFrameworkCore连接数据库生成实体
    sql server 触发器开发
    Windows 配置定时任务 和任务无法执行原因分析
    sql 的存储过程和事务
  • 原文地址:https://www.cnblogs.com/zhuweisky/p/387224.html
Copyright © 2011-2022 走看看