为了账号安全,请及时绑定邮箱和手机立即绑定

通用查询设计思想(2)- 基于ADO.Net的设计

标签:
MySQL

 不少公司用的是ADO.NET的访问方式,估计不少朋友对于sql的拼写真是深恶痛绝,在没有一个封装足够好的底层的项目,特别是经过许多人接手之后,代码那叫一个惨不忍睹,本文借助【通用查询设计思想】这篇文章的思想和基于ADO.NET进行通用查询设计。

  【通用查询设计思想】这篇文章是基于核心方法GenerateQueryExpression来生成表达式的,基于这个思想我们重新写个方法拼装成类似sql中的where条件

复制代码

      /// <summary>
        /// 生成查询条件        /// </summary>
        /// <typeparam name="TEntity">要查询的实体类型</typeparam>
        public static string GenerateQueryCriterion<TEntity>(this IQuery<TEntity> query) where TEntity : class
        {            var criterion = " where 1 = 1 ";            if (query == null) return criterion;            var condition = " and ";            var returnStr = string.Empty;            var queryType = query.GetType();            foreach (PropertyInfo property in queryType.GetProperties())
            {                var value = property.GetValue(query);                if (value is string)
                {                    var str = ((string)value).Trim();
                    value = string.IsNullOrEmpty(str) ? null : str;
                }                //针对QueryMode特性获取我们指定要查询的路径
                foreach (var attribute in property.GetAttributes<QueryModeAttribute>())
                {                    var propertyPath = attribute.PropertyPath;                    if (propertyPath == null)
                        propertyPath = property.Name;                    var conditionStr = CreateConditionString(value, propertyPath, attribute.Compare);                    if (string.IsNullOrWhiteSpace(conditionStr))                        continue;
                    returnStr += criterion + condition + conditionStr;
                }
            }            return returnStr;
        }        /// <summary>
        /// 生成sql条件        /// </summary>
        /// <param name="value"></param>
        /// <param name="propertyPath"></param>
        /// <param name="compare"></param>
        /// <returns></returns>
        private static string CreateConditionString(object value, string propertyPath, QueryCompare compare)
        {            switch (compare)
            {                case QueryCompare.Equal:                    return CreateEqualString(propertyPath, value);                default:                    return null;
            }
        }        /// <summary>
        /// 生成sql的等于条件        /// </summary>
        /// <param name="propertyPath"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        private static string CreateEqualString(string propertyPath, object value)
        {            if (value == null) return string.Empty;            if (value is string)
            {                return propertyPath + "='" + value + "'";
            } 

            return propertyPath + "=" + value;
        }

复制代码

  方法返回的就是我们常见的“ 1 = 1 and System='A' ” 这样的查询条件,其他的类似 大于,小于,like这些条件,相信以朋友们高超的智慧肯定不是什么难事:)

   

  为避免新朋友没看过【通用查询设计思想】这篇文章,个人把这次的变动的类罗列出来

  查询基类(保留表达式的方法,兼容同时使用Linq和ADO.NET的情况:))

复制代码

    public class Query<TEntity> : IQuery<TEntity> where TEntity: class 
    {        /// <summary>
        /// 指定查询条件        /// </summary>
        protected Expression<Func<TEntity, bool>> Predicate;        /// <summary>
        /// 创建一个新的 <see cref="Query{TEntity}"/>
        /// </summary>
        public Query()
        {
        }        /// <summary>
        /// 创建一个指定查询条件的<see cref="Query{TEntity}"/>
        /// </summary>
        /// <param name="predicate">指定的查询条件</param>
        public Query(Expression<Func<TEntity, bool>> predicate)
        {
            Predicate = predicate;
        }        /// <summary>
        /// 生成表达式        /// </summary>
        /// <returns></returns>
        public Expression<Func<TEntity, bool>> GenerateExpression()
        {            return Predicate.And(this.GetQueryExpression());
        }        /// <summary>
        /// 生成sql条件        /// </summary>
        /// <returns></returns>
        public string GenerateSqlCriterion()
        {            return this.GenerateQueryCriterion();
        }
    }

复制代码

  查询模式(PropertyPath不再是数组,因为ADO.NET中应该不会涉及到导航属性

复制代码

    public class QueryModeAttribute : Attribute
    {        /// <summary>
        /// 比较方式        /// </summary>
        public QueryCompare Compare { get; set; }        /// <summary>
        /// 对应属性路径        /// </summary>
        public string PropertyPath { get; set; }        /// <summary>
        /// 查询字段        /// </summary>
        public QueryAttribute(QueryCompare compare, string propertyPath)
        {
            PropertyPath = propertyPath;
            Compare = compare;
        }
    }

复制代码

   查询实体

复制代码

    public class AccountQuery : PageQuery<Account>
    {        /// <summary>
        /// 姓名        /// </summary>        [Query(QueryCompare.Equal, nameof(Account.Name))]        public string Name { get; set; }
    
    //其他查询条件...
    }

复制代码

  来看一下我们完整的使用例子,很多情况下我们是需要分页和添加类似于Order By或者Group By这样的高级条件(本例子前端是使用layui,数据库是mysql)

复制代码

      public PageResult<AccountDto> GetAccount(AccountQuery query)
        {            var sql = @"select xx,xx,xx from user ";            var criterion = query.GenerateSqlCriterion();

            sql += criterion;            return MySqlHelper.GetPageResult<AccountDto>(sql, null, query.PageIndex, query.PageSize, query.Field, query.Order);
        }


      /// <summary>
        /// 获取分页数据        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="cmdText"></param>
        /// <param name="cmdParms"></param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <param name="orderField"></param>
        /// <param name="sort"></param>
        /// <param name="groupBy"></param>
        /// <returns></returns>
        public static PageResult<T> GetPageResult<T>(string cmdText,
            MySqlParameter[] cmdParms, int pageIndex, int pageSize, string orderField ="id", string sort = "desc", string groupBy = "") where T : class, new()
        {            var result = new PageResult<T>
            {
                PageSize = pageSize,
                PageIndex = pageIndex
            };            //获取总数
            var sqlCount = $"SELECT COUNT(*) FROM ({cmdText}) TableCount ";            var objCount = ExecuteScalar(CommandType.Text, sqlCount, cmdParms);
            result.TotalCount = Convert.ToInt32(objCount);            string pagingSql;            //获取分页数据
            if (string.IsNullOrWhiteSpace(groupBy))
            {
                pagingSql =
                    $"{cmdText} ORDER BY {orderField} {sort} " +
                    $"LIMIT {(pageIndex - 1) * pageSize}, {pageSize}";
            }            else
            {                //Group by 
                pagingSql =
                    $"{cmdText} GROUP BY {groupBy} ORDER BY {orderField} {sort} " +
                    $"LIMIT {(pageIndex - 1) * pageSize}, {pageSize}";
            }            var dt = ExecuteDataTable(CommandType.Text, pagingSql, cmdParms);            if (dt != null)
            {
                result.Data = dt.ToList<T>();
            }            return result;
        }

复制代码

 

  当然,这只是我们的一般查询情况,实际情况中我们会遇到更复杂的sql,基于本文的中心主题,不再深入讨论其他场景。

作者:lex-wu

原文出处:https://www.cnblogs.com/lex-wu/p/10486959.html  

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消