IBatis.Net框架封装,快速开发

本文介绍了作者在项目中使用IBatis.Net框架的经验,指出其轻量级和简单配置的优势。在新的项目中,为了提高开发效率,作者决定进行IBatis的封装,以避免重复的增删改查操作。由于未能找到合适的现成解决方案,作者自行实现了IBaseDao接口,封装了包括添加、删除、修改、查询和分页排序在内的通用方法。详细讲述了分页查询排序的实现思路,以及针对不同字段类型的条件设置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

之前做了一个项目,项目中使用了IBatis for .net框架,感觉IBatis使用起来还是比较方便,且较之NHibernate配置比较简单,属于轻量级ORM框架。最近又有一个项目需要开动,我琢磨着还是使用IBatis吧,毕竟前面项目使用过,大家都比较熟悉,而且构建起来也比较方便。但是在构建的时候,感觉在做重复劳动,每个实体都有增删改查几个共用的操作,写完这些也需要不少时间,而且无意义,最多只能增加对IBatis使用熟练度,相对于花下去的成本还是不值得的。百度、google想找一些封装好的通用类,类似于NHibernate的IBaseDao,然而并没有找到合适的。那只能自己动手写了,参考了NHibernate的IBaseDao封装,主要封装了以下几个方法(添加一个实体,添加多个实体,删除一个实体,删除多个实体,修改一个实体,获取一个实体,获取所有实体,分页,分页排序查询)。

IBaseDao接口

      /// <summary>
    /// 基础操作
    /// </summary>
    /// <typeparam name="TEntity">实体对象</typeparam>
    /// <typeparam name="TPk">主键类型</typeparam>
    public interface IBaseDao<TEntity, TPk>
    {
        /// <summary>
        /// 添加一个实体,返回主键
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        TPk Add(TEntity entity);


        /// <summary>
        /// 添加多个实体,返回主键列表
        /// </summary>
        /// <param name="entities"></param>
        /// <returns></returns>
        IList<TPk> Add(IEnumerable<TEntity> entities);


        /// <summary>
        /// 通过主键删除实体
        /// </summary>
        /// <param name="id"></param>
        void Delete(TPk id);


        /// <summary>
        /// 通过id集合删除实体
        /// </summary>
        /// <param name="ids"></param>
        void Delete(IEnumerable<TPk> ids);


        /// <summary>
        /// 更新实体,为null则不操作
        /// </summary>
        /// <param name="entity"></param>
        void Update(TEntity entity);


        /// <summary>
        /// 通过主键获取实体
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        TEntity Get(TPk id);


        /// <summary>
        /// 通过主键获取实体
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        IList<TEntity> Get(IEnumerable<TPk> ids);


        /// <summary>
        /// 获取所有实体
        /// </summary>
        /// <returns></returns>
        IList<TEntity> GetAll();


        /// <summary>
        /// 分页
        /// </summary>
        /// <typeparam name="TSearchSortCriteria"></typeparam>
        /// <param name="currentPage"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        PageData<TEntity> GetPageDate<TSearchSortCriteria>(int currentPage, int pageSize) where TSearchSortCriteria : SearchSortPageEntity, new();


        /// <summary>
        /// 分页查询排序
        /// </summary>
        /// <typeparam name="TSearchSortCriteria"></typeparam>
        /// <param name="currentPage"></param>
        /// <param name="pageSize"></param>
        /// <param name="searchSortCriteria"></param>
        /// <returns></returns>
        PageData<TEntity> GetPageDate<TSearchSortCriteria>(int currentPage, int pageSize, TSearchSortCriteria searchSortCriteria) where TSearchSortCriteria : SearchSortPageEntity, new();
    }

IBaseDao的实现

    public class BaseDao<TEntity, TPk> : IBaseDao<TEntity, TPk>
    {
        public ISqlMapper RealMapper = Mapper.GetMaper;
        private readonly string _className = typeof(TEntity).Name;

        public TPk Add(TEntity entity)
        {
            string command = "Add" + _className;
            var obj = RealMapper.Insert(command, entity);
            return (TPk)obj;
        }

        public IList<TPk> Add(IEnumerable<TEntity> entities)
        {
            var tPks = new List<TPk>();
            using (var tran = RealMapper.BeginTransaction())
            {
                tPks.AddRange(from entity in entities let command = "Add" + _className select RealMapper.Insert(command, entity) into obj select (TPk)obj);
                tran.CommitTransaction();
            }
            return tPks;
        }

        public void Delete(TPk id)
        {
            string command = "Delete" + _className;
            RealMapper.Delete(command, id);
        }

        public void Delete(IEnumerable<TPk> ids)
        {
            string command = "Delete" + _className + "s";
            RealMapper.Delete(command, ids);
        }

        public void Update(TEntity entity)
        {
            string command = "Update" + _className;
            RealMapper.Update(command, entity);
        }

        public TEntity Get(TPk id)
        {
            string command = "Get" + _className;
            return RealMapper.QueryForObject<TEntity>(command, id);
        }

        public IList<TEntity> Get(IEnumerable<TPk> ids)
        {
            string command = "Get" + _className + "s";
            return RealMapper.QueryForList<TEntity>(command, ids);
        }

        public IList<TEntity> GetAll()
        {
            string command = "GetAll" + _className + "s";
            return RealMapper.QueryForList<TEntity>(command, null);
        }

        public PageData<TEntity> GetPageDate<TSearchSortCriteria>(int currentPage, int pageSize) where TSearchSortCriteria : SearchSortPageEntity, new()
        {
            return GetPageDate(currentPage, pageSize, new TSearchSortCriteria());
        }

        public PageData<TEntity> GetPageDate<TSearchSortCriteria>(int currentPage, int pageSize, TSearchSortCriteria searchSortCriteria) where TSearchSortCriteria : SearchSortPageEntity, new()
        {
            int startRowNumber = (currentPage - 1) * pageSize + 1;
            int endRowNumber = currentPage * pageSize;
            searchSortCriteria.StartRowNumber = startRowNumber;
            searchSortCriteria.EndRowNumber = endRowNumber;
            string command = "Get" + _className + "sWithPageAndSearch";
            IList<TEntity> entities = RealMapper.QueryForList<TEntity>(command, searchSortCriteria);

            command = "Get" + _className + "sWithPageAndSearchCount";
            var totalCount = (int)RealMapper.QueryForObject(command, searchSortCriteria);

            var pageDate = new PageData<TEntity>
                {
                    Data = entities,
                    Pager = new Pager(totalCount, currentPage, pageSize)
                };
            return pageDate;
        }
    }

其中需要解释的操作是“分页查询排序”,TSearchSortCriteria是查询排序条件,每个实体的查询条件都不一样,且继承SearchSortCriteria类(包含公共条件)

SearchSortCriteria代码:

    public abstract class SearchSortPageEntity
    {
        /// <summary>
        /// StartRowNumber
        /// </summary>
        public int? StartRowNumber { get; set; }


        /// <summary>
        /// EndRowNumber
        /// </summary>
        public int? EndRowNumber { get; set; }

        /// <summary>
        /// SortField
        /// </summary>
        public string SortField { get; set; }

        /// <summary>
        /// Sort
        /// </summary>
        public string Sort { get; set; }
    }

注意点:

1、这里我会为每个表字段都创建为一个查询条件(除了主键)

2、针对值类型的字段,如int,decimal使用 “=”条件

3、针对引用类型的字段,如nvarchar,varchar使用 like ‘%%’

4、针对时间类型,为其创建2个字段 BeginDatetime,EndDatetime,创建条件 >= ‘BeginDatetime’,<= 'EndDatetime'

示例代码如下:(AccountSearchCriteria.cs)

    public class AccountSearchCriteria : SearchSortPageEntity
    {
        /// <summary>
        /// UserName
        /// </summary>
        public string SearchUserName { get; set; }

        /// <summary>
        /// Password
        /// </summary>
        public string SearchPassword { get; set; }

        /// <summary>
        /// BeginRegisterDate
        /// </summary>
        public DateTime? BeginRegisterDate { get; set; }

        /// <summary>
        /// EndRegisterDate
        /// </summary>
        public DateTime? EndRegisterDate { get; set; }
    }
Account的表结构(接下来代码全部以Account为例):
序号列名数据类型长度小数位标识主键外键允许空默认值说明
1Idint40   
2UserNamevarchar180     
3Passwordvarchar500     
4RegisterDatedatetime83   getdate 
Account的sqlmapper.xml(可用代码生成器生成)
<?xml version="1.0"  encoding="utf-8" ?>
<sqlMap namespace="Account" xmlns="http://ibatis.apache.org/mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <alias>
    <!--alias:取别名
            assembly:表示类所在的文件
            type:表示该类的完整的名称
      	-->
    <typeAlias alias="Account" assembly="ULH.Entity.dll" type="ULH.Entity.User.AccountPo" />
    <typeAlias alias="AccountSearchCriteria" assembly="ULH.Service.dll" type="ULH.Service.User.SearchCriteria.AccountSearchCriteria" />
  </alias>
  <resultMaps>
		<resultMap id="AccountResult"  class="Account">
			<result property="Id"    column="Id"/>
	    	<result property="UserName"    column="UserName"/>
	    	<result property="Password"    column="Password"/>
	    	<result property="RegisterDate"    column="RegisterDate"/>
	    </resultMap>	    
	    
	    <resultMap id="AccountSearchCriteriaResult"  class="AccountSearchCriteria">
	    	<result property="StartRowNumber"    column="StartRowNumber"/>
			<result property="EndRowNumber"    column="EndRowNumber"/>
			<result property="SortField"    column="SortField"/>
			<result property="Sort"    column="Sort"/>					
			<result property="SearchUserName"    column="SearchUserName"/>			
			<result property="SearchPassword"    column="SearchPassword"/>
			<result property="BeginRegisterDate"    column="BeginRegisterDate"/>
			<result property="EndRegisterDate"    column="EndRegisterDate"/>		
		</resultMap>
  	</resultMaps>
  	<statements>
   		<insert id="AddAccountPo" parameterClass="Account">
      	  INSERT INTO Account VALUES(#UserName# ,#Password# ,#RegisterDate#)
      	<selectKey resultClass="int" type="post" property="Id">
          SELECT @@IDENTITY
      	</selectKey>
    	</insert>    	
    	
	    <delete id="DeleteAccountPo" parameterClass="int" restultClass="int">
	      DELETE FROM Account WHERE Id = #Id#
	    </delete>
	    
        <delete id="DeleteAccountPos" parameterClass="List">
	      DELETE FROM Account
	      <iterate prepend="WHERE" open="(" close=")" conjunction="OR">
	        Id = #[]#
	      </iterate>
	    </delete>
	    
	    <update id="UpdateAccountPo" parameterClass="Account" restltClass="int">
	      UPDATE Account  
	      <dynamic prepend="SET">	      	
	      	<isNotEmpty prepend="," property="UserName">
	      		UserName = #UserName# 
	      	</isNotEmpty>
	      	      	
	      	<isNotEmpty prepend="," property="Password">
	      		Password = #Password# 
	      	</isNotEmpty>
	      	      	
	      	<isNotEmpty prepend="," property="RegisterDate">
	      		RegisterDate = #RegisterDate# 
	      	</isNotEmpty>
	      </dynamic> WHERE Id = #Id#
	    </update>
	    
        <select id="GetAccountPo" parameterClass="int" resultClass="Account">
	      SELECT Id ,UserName ,Password ,RegisterDate FROM Account WHERE Id = #Id#
	    </select>
	    
	    <select id="GetAccountPos" parameterClass="List" resultClass="Account">
	      SELECT Id ,UserName ,Password ,RegisterDate FROM Account
	      <iterate prepend="WHERE" open="(" close=")" conjunction="OR">
	        Id = #[]#
	      </iterate>
	    </select>
	    
        <select id="GetAllAccountPos" resultClass="Account">
	      SELECT Id ,UserName ,Password ,RegisterDate FROM Account
	    </select>
	    
	    <select id="GetAccountPosWithPageAndSearch" parameterClass="AccountSearchCriteria" resultClass="Account">
		WITH    TempAccount
    	     AS ( SELECT 	Id ,UserName ,Password ,RegisterDate ,    	      				
        	                ROW_NUMBER() OVER ( ORDER BY <isEmpty property="SortField">Id</isEmpty>
        	                							 <isNotEmpty property="SortField">#SortField#</isNotEmpty> 
        	                							 <isEmpty property="Sort">Asc</isEmpty>
        	                							 <isNotEmpty property="Sort">#Sort#</isNotEmpty>) AS RowNumber
            	   FROM     Account
            	   <dynamic prepend="WHERE">
						<isNotEmpty prepend="AND" property="SearchUserName">
							UserName LIKE '%$SearchUserName$%'
						</isNotEmpty>
						<isNotEmpty prepend="AND" property="SearchPassword">
							Password LIKE '%$SearchPassword$%'
						</isNotEmpty>
						<isNotEmpty prepend="AND" property="BeginRegisterDate">
							<![CDATA[RegisterDate >= #BeginRegisterDate#]]>
						</isNotEmpty>
						<isNotEmpty prepend="AND" property="EndRegisterDate">            	   		
							<![CDATA[RegisterDate <= #EndRegisterDate#]]>
						</isNotEmpty>            	   	
            	   	</dynamic>
             	)	
    	<![CDATA[SELECT  Id ,UserName ,Password ,RegisterDate
    	FROM    TempAccount
    	WHERE   RowNumber >= #StartRowNumber#
            AND RowNumber <= #EndRowNumber#]]>
	    </select>
	    
	    <select id="GetAccountPosWithPageAndSearchCount" parameterClass="AccountSearchCriteria" resultClass="int">
		 SELECT 	COUNT(1)
           FROM     Account
           <dynamic prepend="WHERE"> 
				<isNotEmpty prepend="AND" property="SearchUserName">
					UserName LIKE '%$SearchUserName$%'
				</isNotEmpty>
				<isNotEmpty prepend="AND" property="SearchPassword">
					Password LIKE '%$SearchPassword$%'
				</isNotEmpty>
				<isNotEmpty prepend="AND" property="BeginRegisterDate">
					<![CDATA[RegisterDate >= #BeginRegisterDate#]]>
				</isNotEmpty>
				<isNotEmpty prepend="AND" property="EndRegisterDate">            	   		
					<![CDATA[RegisterDate <= #EndRegisterDate#]]>
				</isNotEmpty>           
           </dynamic>
	    </select>
    </statements>
</sqlMap>
IAccountDao
    public interface IAccountDao : IBaseDao<AccountPo, int>
    {

    }
AccountDao
    public class AccountDao : BaseDao<AccountPo, int>, IAccountDao
    {

    }
现在就可以直接使用基础操作了
    public class UserService : IUserService
    {
        private readonly IAccountDao _accountDao = Container.CommonContainer.Resolve<IAccountDao>();

        public int CreateAccount(Account account)
        {
            return _accountDao.Add(GetAccountPoFromVo(account));
        }

        public void DeleteAccount(int id)
        {
            _accountDao.Delete(id);
        }

        public void DeleteAccounts(List<int> ids)
        {
            _accountDao.Delete(ids);
        }

        public void UpdateAccount(Account account)
        {
            _accountDao.Update(GetAccountPoFromVo(account));
        }

        public void UpdateAccounts(List<Account> accounts)
        {
            foreach (var account in accounts)
            {
                UpdateAccount(account);
            }
        }

        public Account GetAccount(int id)
        {
            return GetAccountVoFromPo(_accountDao.Get(id));
        }

        public List<Account> GetAllAccount()
        {
            return _accountDao.GetAll().Select(GetAccountVoFromPo).ToList();
        }

        public PageData<Account> GetAccountPageData(int currentPage, int pageSize)
        {
            return GetAccountPageData(currentPage, pageSize, new AccountSearchCriteria());
        }

        public PageData<Account> GetAccountPageData(int currentPage, int pageSize, AccountSearchCriteria accountSehSotPage)
        {
            var pageDataVo = new PageData<Account>();
            var pageDataPo = _accountDao.GetPageDate(currentPage, pageSize, accountSehSotPage);
            pageDataVo.Data = pageDataPo.Data.Select(GetAccountVoFromPo).ToList();
            pageDataVo.Pager = pageDataPo.Pager;
            return pageDataVo;
        }

        #region 辅助方法

        internal static Account GetAccountVoFromPo(AccountPo accountPo)
        {
            Account account = null;
            if (accountPo != null)
            {
                account = new Account
                    {
                        Id = accountPo.Id,
                        UserName = accountPo.UserName,
                        RegisterDate = accountPo.RegisterDate
                    };
            }
            return account;
        }

        internal static AccountPo GetAccountPoFromVo(Account account)
        {
            AccountPo accountPo = null;
            if (account != null)
            {
                accountPo = new AccountPo
                {
                    Id = account.Id,
                    Password = account.Password,
                    UserName = account.UserName,
                    RegisterDate = account.RegisterDate
                };
            }
            return accountPo;
        }

        #endregion
    }
最后共享一下代码模板,使用动软代码生成器生成





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值