近一年时间没有写blog了,由于各种忙——是时候更新一下了。

重新审视了一翻以前写的东西,发现问题不少,以 .net企业级架构实战之5——基于接口的访问层实现 为例,就一般的访问层对象而言,功能大致相同,每一个都存在SearchByWhere()等功能,在DaoTemplate模板类已经实现泛型化的基础上,如此实现各个Dao实在冗余啰嗦。

每个Dao最大的差异,在于这一片断:

Spring.net Dao的改进——使用属性类描述实体数据源private const string TableName = "TB_USER_MAIN";           //表名
Spring.net Dao的改进——使用属性类描述实体数据源
private const string PrimaryKey = "Id";                 //主键

 它们被这样使用:

        }

 

说白了,Dao除了名字不一样,最大差异体现在 对应实体数据源信息上。实体数据源信息的差异,应该由实体来描述,而不是Dao, "omg,多么糟糕的设计!"。

改过来,为实体创建一个描述数据源信息的属性类,以元标记的方式标注,其余的工作,一个泛型的Dao足矣。

    • 描述数据源信息的TableInfoAttribute类:
       woodigg.model
      {
          /// <summary>
          
      /// 实体的TABLE属性
          
      /// </summary>
          [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
          
      public class TableInfoAttribute : Attribute
          {
              
      #region Private Members
              
              
      private string tableName;       
              
      private string primaryKey;      
              
      private string columns;         

              
      #endregion

              
      #region Properties

              
      /// <summary>
              
      /// 表名
              
      /// </summary>
              
      /// <value>The table name.</value>
              public string TableName
              {
                  
      get { return tableName; }
                  
      set
                  {
                      tableName 
      = value;                
                  }
              }

              
      /// <summary>
              
      /// 主键
              
      /// </summary>
              
      /// <value>The table primaryKey.</value>
              public string PrimaryKey
              {
                  
      get { return primaryKey; }
                  
      set
                  {
                      primaryKey 
      = value;
                  }
              }

              
      /// <summary>
              
      /// 所有列
              
      /// </summary>
              
      /// <value>The table columns.</value>
              public string Columns
              {
                  
      get { return columns; }
                  
      set
                  {
                      columns 
      = value;
                  }
              }

              
      #endregion        
          }
      }
        •  设计这个泛型类Dao的接口,如IbandDaoSpring:
         woodigg.DAO
        {
            public interface IbandDaoSpring
            {
                
        /// <summary>
                
        /// 存
                
        /// </summary>
                bool Save<T>(T ab);

                
        /// <summary>
                
        /// 更新
                
        /// </summary>
                bool Update<T>(T ab);

                
        /// <summary>
                
        /// 删除
                
        /// </summary>
                bool Delete<T>(T ab);

                
        /// <summary>
                
        /// 读
                
        /// </summary>
                T LoadFromId<T>(int id);

                
        /// <summary>
                
        /// 查
                
        /// </summary>        
                IList<T> SearchByWhere<T>(string where);

                
        /// <summary>
                
        /// 查排序
                
        /// </summary>        
                IList<T> SearchByWhereOrder<T>(string wherestring propertyName, bool ascending);

                
        /// <summary>
                
        /// 分页
                
        /// 给出全部参数
                
        /// </summary>
                
        /// <param name="tableName">表名</param>
                
        /// <param name="PrimaryKey">主键</param>
                
        /// <param name="Columns"></param>
                
        /// <param name="pageSize">页大小</param>
                
        /// <param name="pageIdx">页号</param>
                
        /// <param name="OrderColumn">排序列</param>
                
        /// <param name="orderType">true降序 false 升级</param>
                
        /// <param name="condition">条件</param>
                
        /// <returns>DataTable</returns>
                DataTable GetPagerByStoreProc<T>(string tableName,string PrimaryKey,string Columns, int pageSize, int pageIdx
                    , 
        string OrderColumn, bool orderType, string condition);

                
        /// <summary>
                
        /// 重载版本分页
                
        /// 表名,主键 由元标记(TableInfo)给出
                
        /// </summary>
                DataTable GetPagerByStoreProc<T>(string Columns, int pageSize, int pageIdx
                    , 
        string OrderColumn, bool orderType, string condition);

                
        /// <summary>
                
        /// 重载版本分页
                
        /// 表名,主键,所有列 由元标记(TableInfo)给出
                
        /// </summary>
                DataTable GetPagerByStoreProc<T>(int pageSize, int pageIdx
                    , 
        string OrderColumn, bool orderType, string condition);

                
        /// <summary>
                
        /// 获取记录数
                
        /// </summary>
                int GetRecordCount<T>(string where);
            }
        }
          •  找个实体类,给它加上TableInfo数据源信息元标记:
            )]
                public class MEDIAAlbumRecommand{}

                
            * 找个页面,测试一下: 

            DataTable dt 
            =            BandDaoSpring.GetPagerByStoreProc<MEDIAAlbumRecommand>
                        (
            101"Id"false"1=1");
          找个页面,测试一下:
          Spring.net Dao的改进——使用属性类描述实体数据源DataTable dt =            BandDaoSpring.GetPagerByStoreProc<MEDIAAlbumRecommand>
          Spring.net Dao的改进——使用属性类描述实体数据源            (
          101"Id"false"1=1");


          终于告别一大堆名字不一样的Dao了,统统删掉,这样能让配置文件buessineConfig.xml瘦下来不少,看着舒服。也许看官您会问:如果对于特定的实体要实现事务呢 ——确实,这个Dao只是把通用的部分提炼出来,如果是个性化的操作,还是要单独创建操作类的。比如事务,创建一个基于接口实现的类,加上Transaction元标记,最后,在配置文件中指派Spring.net的某个AOP Proxy对象,让它来帮助你实现事务(在此向以前读过在下糙文的读者致歉,在spring.net中,Transaction元标记只是标注事务的范围,而具体的实现是基于 接口 及 接口切面代理对象 共同完成的

          • 来个小示例吧,先从配置文件说起,在applicationContext.xml配置了这样一个拦截器:
          Spring.net Dao的改进——使用属性类描述实体数据源<!--事务拦截器-->
          Spring.net Dao的改进——使用属性类描述实体数据源    
          <object id="TransactionInterceptor"             type="Spring.Transaction.Interceptor.TransactionInterceptor, Spring.Data">
          Spring.net Dao的改进——使用属性类描述实体数据源        
          <property name="TransactionManager" ref="HibernateTransactionManager" />
          Spring.net Dao的改进——使用属性类描述实体数据源        
          <property name="TransactionAttributeSource">
          Spring.net Dao的改进——使用属性类描述实体数据源            
          <object type="Spring.Transaction.Interceptor.AttributesTransactionAttributeSource, Spring.Data" />
          Spring.net Dao的改进——使用属性类描述实体数据源        
          </property>
          Spring.net Dao的改进——使用属性类描述实体数据源    
          </object>
          Spring.net Dao的改进——使用属性类描述实体数据源
          •  创建一个接口,描述某个有事务的类:
           woodigg.DAO
          {
              /// <summary>
              
          /// 用于事务的接口
              
          /// </summary>
              public interface ImediaInterface
              {
                  
          bool TransactionAdd(IList<MEDIARead> list);
              }
          }
          •  实现它,标注声明性事务:
           woodigg.DAO
          {
              public class MediaTransaction : ImediaInterface
              {
                  
          #region 注入的DaoTemplate
                  
          private DaoTemplate _DaoTemplate;
                  
          public DaoTemplate DaoTemplate
                  {
                      
          get { return _DaoTemplate; }
                      
          set { _DaoTemplate = value; }
                  }
                  
          #endregion

                  [Transaction(ReadOnly
          =false)]
                  
          public bool TransactionAdd(IList<MEDIARead> list)
                  {
                      
          bool flag = true;
                      
          foreach (MEDIARead r in list)
                      {
                          
          if (!DaoTemplate.Save<MEDIARead>(r)) {
                              flag 
          = false;
                              
          break;
                          }
                      }
                      
          return flag;
                  }
              }
          }
          •  在配置文件中,声明这个MediaTransaction对象,同时使用 ObjectNameAutoProxyCreator 代理来负责为它植入事务监听:
          Spring.net Dao的改进——使用属性类描述实体数据源<!--事务-->
          Spring.net Dao的改进——使用属性类描述实体数据源        
          <object id="MediaTransaction" type="woodigg.DAO.MediaTransaction,woodigg.DAO" autowire="byName" />
          Spring.net Dao的改进——使用属性类描述实体数据源        
          <object name="autoProxyCreator"
          Spring.net Dao的改进——使用属性类描述实体数据源                    type
          ="Spring.Aop.Framework.AutoProxy.ObjectNameAutoProxyCreator, Spring.Aop">
          Spring.net Dao的改进——使用属性类描述实体数据源              
          <property name="InterceptorNames" value="TransactionInterceptor"/>
          Spring.net Dao的改进——使用属性类描述实体数据源              
          <property name="ObjectNames">
          Spring.net Dao的改进——使用属性类描述实体数据源                  
          <list>                
          Spring.net Dao的改进——使用属性类描述实体数据源                      
          <idref local="MediaTransaction"/>
          Spring.net Dao的改进——使用属性类描述实体数据源                  
          </list>
          Spring.net Dao的改进——使用属性类描述实体数据源              
          </property>
          Spring.net Dao的改进——使用属性类描述实体数据源        
          </object>

                 list中可以安放你需要植入事务拦截器的任何对象。

          再次表示歉意!!

          相关文章:

          • 2021-06-24
          • 2022-12-23
          • 2022-01-24
          • 2021-12-14
          • 2022-12-23
          • 2022-12-23
          • 2021-07-15
          • 2022-12-23
          猜你喜欢
          • 2021-10-17
          • 2022-12-23
          • 2022-12-23
          • 2021-08-28
          • 2022-01-02
          • 2022-03-07
          • 2022-12-23
          相关资源
          相似解决方案