zoukankan      html  css  js  c++  java
  • 查询对象

    查询对象

    信息系统的查询需求千变万化,在仓储中为每个查询需求创建一个特殊方法,将导致大量乏味而臃肿的接口。

      一种更加可行的办法是,在应用层服务中描述查询需求,并通过仓储执行查询。

      为了能够更好的描述查询需求,可以将查询功能从仓储中抽取出来,专门创建一个查询对象。

      查询最复杂的部分是条件过滤,这也是查询对象的主要职责。查询对象可以认为是规约模式的一个变种,允许查询对象动态创建查询条件。

      在Util.Domains项目Repositories目录中,创建查询对象基接口IQueryBase,代码如下。

    复制代码
    using System;
    using System.Linq.Expressions;
    
    namespace Util.Domains.Repositories {
        /// <summary>
        /// 查询对象
        /// </summary>
        /// <typeparam name="TEntity">实体类型</typeparam>
        public interface IQueryBase<TEntity> : IPager where TEntity : class, IAggregateRoot {
            /// <summary>
            /// 获取谓词
            /// </summary>
            Expression<Func<TEntity, bool>> GetPredicate();
            /// <summary>
            /// 获取排序
            /// </summary>
            string GetOrderBy();
        }
    }
    复制代码

      IQueryBase接口主要用来支持将查询对象传入仓储中。

      在仓储接口IRepository中增加两个方法,代码如下。

    复制代码
            /// <summary>
            /// 查询
            /// </summary>
            /// <param name="query">查询对象</param>
            IQueryable<TEntity> Query( IQueryBase<TEntity> query );
            /// <summary>
            /// 分页查询
            /// </summary>
            /// <param name="query">查询对象</param>
            PagerList<TEntity> PagerQuery( IQueryBase<TEntity> query );
    复制代码

      在仓储类Repository中实现这两个方法,代码如下。

    复制代码
            /// <summary>
            /// 查询
            /// </summary>
            /// <param name="query">查询对象</param>
            public IQueryable<TEntity> Query( IQueryBase<TEntity> query ) {
                return FilterBy( Find(), query );
            }
    
            /// <summary>
            /// 过滤
            /// </summary>
            protected IQueryable<TEntity> FilterBy( IQueryable<TEntity> queryable, IQueryBase<TEntity> query ) {
                var predicate = query.GetPredicate();
                if ( predicate == null )
                    return queryable;
                return queryable.Where( predicate );
            }
    
            /// <summary>
            /// 分页查询
            /// </summary>
            /// <param name="query">查询对象</param>
            public virtual PagerList<TEntity> PagerQuery( IQueryBase<TEntity> query ) {
                return Query( query ).PagerResult( query );
            }
    复制代码

      以上代码完成了将查询对象传入仓储并获取结果,下面开始实现查询对象。

      在Util.Datas项目Queries目录中,创建IQuery接口,代码如下。

    复制代码
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Linq.Expressions;
    using Util.Domains;
    using Util.Domains.Repositories;
    
    namespace Util.Datas.Queries {
        /// <summary>
        /// 查询对象
        /// </summary>
        /// <typeparam name="TEntity">实体类型</typeparam>
        /// <typeparam name="TKey">实体标识类型</typeparam>
        public interface IQuery<TEntity, TKey> : IQueryBase<TEntity> where TEntity : class,IAggregateRoot<TKey> {
            /// <summary>
            /// 添加谓词,仅能添加一个条件,如果参数值为空,则忽略该条件
            /// </summary>
            /// <param name="predicate">谓词</param>
            /// <param name="isOr">是否使用Or连接</param>
            IQuery<TEntity, TKey> Filter( Expression<Func<TEntity, bool>> predicate, bool isOr = false );
    
            /// <summary>
            /// 过滤条件
            /// </summary>
            /// <param name="propertyName">属性名</param>
            /// <param name="value">值</param>
            /// <param name="operator">运算符</param>
            IQuery<TEntity,TKey> Filter( string propertyName, object value, Operator @operator = Operator.Equal );
    
            /// <summary>
            /// 添加查询条件
            /// </summary>
            /// <param name="criteria">查询条件</param>
            IQuery<TEntity,TKey> Filter( ICriteria<TEntity> criteria );
    
            /// <summary>
            /// 过滤int数值段
            /// </summary>
            /// <typeparam name="TProperty">属性类型</typeparam>
            /// <param name="propertyExpression">属性表达式,范例:t => t.Age</param>
            /// <param name="min">最小值</param>
            /// <param name="max">最大值</param>
            IQuery<TEntity,TKey> FilterInt<TProperty>( Expression<Func<TEntity, TProperty>> propertyExpression, int? min,int? max );
    
            /// <summary>
            /// 过滤double数值段
            /// </summary>
            /// <typeparam name="TProperty">属性类型</typeparam>
            /// <param name="propertyExpression">属性表达式,范例:t => t.Age</param>
            /// <param name="min">最小值</param>
            /// <param name="max">最大值</param>
            IQuery<TEntity,TKey> FilterDouble<TProperty>( Expression<Func<TEntity, TProperty>> propertyExpression, double? min,
                double? max );
    
            /// <summary>
            /// 过滤日期段,不包含时间
            /// </summary>
            /// <typeparam name="TProperty">属性类型</typeparam>
            /// <param name="propertyExpression">属性表达式,范例:t => t.Age</param>
            /// <param name="min">最小值</param>
            /// <param name="max">最大值</param>
            IQuery<TEntity,TKey> FilterDate<TProperty>( Expression<Func<TEntity, TProperty>> propertyExpression, DateTime? min,
                DateTime? max );
    
            /// <summary>
            /// 过滤日期时间段,包含时间
            /// </summary>
            /// <typeparam name="TProperty">属性类型</typeparam>
            /// <param name="propertyExpression">属性表达式,范例:t => t.Age</param>
            /// <param name="min">最小值</param>
            /// <param name="max">最大值</param>
            IQuery<TEntity,TKey> FilterDateTime<TProperty>( Expression<Func<TEntity, TProperty>> propertyExpression,
                DateTime? min, DateTime? max );
    
            /// <summary>
            /// 过滤decimal数值段
            /// </summary>
            /// <typeparam name="TProperty">属性类型</typeparam>
            /// <param name="propertyExpression">属性表达式,范例:t => t.Age</param>
            /// <param name="min">最小值</param>
            /// <param name="max">最大值</param>
            IQuery<TEntity,TKey> FilterDecimal<TProperty>( Expression<Func<TEntity, TProperty>> propertyExpression, decimal? min,
                decimal? max );
    
            /// <summary>
            /// 与连接,将传入的查询条件合并到当前对象
            /// </summary>
            /// <param name="query">查询对象</param>
            IQuery<TEntity,TKey> And( IQuery<TEntity,TKey> query );
    
            /// <summary>
            /// 与连接,将传入的查询条件合并到当前对象
            /// </summary>
            /// <param name="predicate">谓词</param>
            IQuery<TEntity,TKey> And( Expression<Func<TEntity, bool>> predicate );
    
            /// <summary>
            /// 或连接,将传入的查询条件合并到当前对象
            /// </summary>
            /// <param name="query">查询对象</param>
            IQuery<TEntity,TKey> Or( IQuery<TEntity,TKey> query );
    
            /// <summary>
            /// 或连接,将传入的查询条件合并到当前对象
            /// </summary>
            /// <param name="predicate">谓词</param>
            IQuery<TEntity,TKey> Or( Expression<Func<TEntity, bool>> predicate );
    
            /// <summary>
            /// 添加排序,支持多次调用OrderBy创建多级排序
            /// </summary>
            /// <typeparam name="TProperty">属性类型</typeparam>
            /// <param name="expression">属性表达式</param>
            /// <param name="desc">是否降序</param>
            IQuery<TEntity,TKey> OrderBy<TProperty>( Expression<Func<TEntity, TProperty>> expression, bool desc = false );
    
            /// <summary>
            /// 添加排序,支持多次调用OrderBy创建多级排序
            /// </summary>
            /// <param name="propertyName">排序属性</param>
            /// <param name="desc">是否降序</param>
            IQuery<TEntity,TKey> OrderBy( string propertyName, bool desc = false );
    
            /// <summary>
            /// 获取列表
            /// </summary>
            /// <param name="queryable">数据源</param>
            List<TEntity> GetList( IQueryable<TEntity> queryable );
    
            /// <summary>
            /// 获取分页列表
            /// </summary>
            /// <param name="queryable">数据源</param>
            PagerList<TEntity> GetPagerList( IQueryable<TEntity> queryable );
        }
    }
    复制代码

      查询对象中定义的过滤方法默认都是以And方式连接,所以需要增加专门的Or连接方法。当查询需求比较复杂时,可以创建多个查询对象进行合并,从而创建更为复杂的查询条件。

      为了使用方便,查询对象本身还提供了获取数据的方法,需要传入IQueryable 对象,以便执行实际的查询操作。

      在Util.Datas项目Queries目录中,创建查询对象实现类Query,代码如下。

    复制代码
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Linq.Expressions;
    using Util.Datas.Queries.Criterias;
    using Util.Datas.Queries.OrderBys;
    using Util.Domains;
    using Util.Domains.Repositories;
    
    namespace Util.Datas.Queries {
        /// <summary>
        /// 查询对象
        /// </summary>
        /// <typeparam name="TEntity">实体类型</typeparam>
        /// <typeparam name="TKey">实体标识类型</typeparam>
        public class Query<TEntity, TKey> : Pager, IQuery<TEntity, TKey> where TEntity : class ,IAggregateRoot<TKey> {
    
            #region 构造方法
    
            /// <summary>
            /// 初始化查询对象
            /// </summary>
            public Query() {
                OrderBuilder = new OrderByBuilder();
            }
    
            /// <summary>
            /// 初始化查询对象
            /// </summary>
            /// <param name="pager">分页对象</param>
            public Query( IPager pager ) : this() {
                Page = pager.Page;
                PageSize = pager.PageSize;
                TotalCount = pager.TotalCount;
                OrderBy( pager.Order );
            }
    
            #endregion
    
            #region 属性
    
            /// <summary>
            /// 查询条件
            /// </summary>
            private ICriteria<TEntity> Criteria { get; set; }
    
            /// <summary>
            /// 排序生成器
            /// </summary>
            private OrderByBuilder OrderBuilder { get; set; }
    
            #endregion
    
            #region GetPredicate(获取谓词)
    
            /// <summary>
            /// 获取谓词
            /// </summary>
            public Expression<Func<TEntity, bool>> GetPredicate() {
                if ( Criteria == null )
                    return null;
                return Criteria.GetPredicate();
            }
    
            #endregion
    
            #region GetOrderBy(获取排序)
    
            /// <summary>
            /// 获取排序
            /// </summary>
            public string GetOrderBy() {
                Order = OrderBuilder.Generate();
                if ( string.IsNullOrWhiteSpace( Order ) )
                    Order = "Id desc";
                return Order;
            }
    
            #endregion
    
            #region 过滤条件
    
            /// <summary>
            /// 添加谓词,仅能添加一个条件,如果参数值为空,则忽略该条件
            /// </summary>
            /// <param name="predicate">谓词</param>
            /// <param name="isOr">是否使用Or连接</param>
            public IQuery<TEntity, TKey> Filter( Expression<Func<TEntity, bool>> predicate,bool isOr = false ) {
                predicate = QueryHelper.ValidatePredicate( predicate );
                if ( predicate == null )
                    return this;
                if ( isOr )
                    Or( predicate );
                else 
                    And( predicate );
                return this;
            }
    
            /// <summary>
            /// 过滤条件
            /// </summary>
            /// <param name="propertyName">属性名</param>
            /// <param name="value">值</param>
            /// <param name="operator">运算符</param>
            public IQuery<TEntity, TKey> Filter( string propertyName, object value, Operator @operator = Operator.Equal ) {
                return Filter( Lambda.ParsePredicate<TEntity>( propertyName, value, @operator ) );
            }
    
            /// <summary>
            /// 添加查询条件
            /// </summary>
            /// <param name="criteria">查询条件</param>
            public IQuery<TEntity, TKey> Filter( ICriteria<TEntity> criteria ) {
                And( criteria.GetPredicate() );
                return this;
            }
    
            /// <summary>
            /// 过滤int数值段
            /// </summary>
            /// <typeparam name="TProperty">属性类型</typeparam>
            /// <param name="propertyExpression">属性表达式,范例:t => t.Age</param>
            /// <param name="min">最小值</param>
            /// <param name="max">最大值</param>
            public IQuery<TEntity, TKey> FilterInt<TProperty>( Expression<Func<TEntity, TProperty>> propertyExpression, int? min, int? max ) {
                return Filter( new IntSegmentCriteria<TEntity, TProperty>( propertyExpression, min, max ) );
            }
    
            /// <summary>
            /// 过滤double数值段
            /// </summary>
            /// <typeparam name="TProperty">属性类型</typeparam>
            /// <param name="propertyExpression">属性表达式,范例:t => t.Age</param>
            /// <param name="min">最小值</param>
            /// <param name="max">最大值</param>
            public IQuery<TEntity, TKey> FilterDouble<TProperty>( Expression<Func<TEntity, TProperty>> propertyExpression, double? min, double? max ) {
                return Filter( new DoubleSegmentCriteria<TEntity, TProperty>( propertyExpression, min, max ) );
            }
    
            /// <summary>
            /// 过滤日期段,不包含时间
            /// </summary>
            /// <typeparam name="TProperty">属性类型</typeparam>
            /// <param name="propertyExpression">属性表达式,范例:t => t.Age</param>
            /// <param name="min">最小值</param>
            /// <param name="max">最大值</param>
            public IQuery<TEntity, TKey> FilterDate<TProperty>( Expression<Func<TEntity, TProperty>> propertyExpression, DateTime? min, DateTime? max ) {
                return Filter( new DateSegmentCriteria<TEntity, TProperty>( propertyExpression, min, max ) );
            }
    
            /// <summary>
            /// 过滤日期时间段,包含时间
            /// </summary>
            /// <typeparam name="TProperty">属性类型</typeparam>
            /// <param name="propertyExpression">属性表达式,范例:t => t.Age</param>
            /// <param name="min">最小值</param>
            /// <param name="max">最大值</param>
            public IQuery<TEntity, TKey> FilterDateTime<TProperty>( Expression<Func<TEntity, TProperty>> propertyExpression, DateTime? min, DateTime? max ) {
                return Filter( new DateTimeSegmentCriteria<TEntity, TProperty>( propertyExpression, min, max ) );
            }
    
            /// <summary>
            /// 过滤decimal数值段
            /// </summary>
            /// <typeparam name="TProperty">属性类型</typeparam>
            /// <param name="propertyExpression">属性表达式,范例:t => t.Age</param>
            /// <param name="min">最小值</param>
            /// <param name="max">最大值</param>
            public IQuery<TEntity, TKey> FilterDecimal<TProperty>( Expression<Func<TEntity, TProperty>> propertyExpression, decimal? min, decimal? max ) {
                return Filter( new DecimalSegmentCriteria<TEntity, TProperty>( propertyExpression, min, max ) );
            }
    
            #endregion
    
            #region 连接
    
            /// <summary>
            /// 与连接,将传入的查询条件合并到当前对象
            /// </summary>
            /// <param name="query">查询对象</param>
            public IQuery<TEntity, TKey> And( IQuery<TEntity, TKey> query ) {
                return And( query.GetPredicate() );
            }
    
            /// <summary>
            /// 与连接,将传入的查询条件合并到当前对象
            /// </summary>
            /// <param name="predicate">谓词</param>
            public IQuery<TEntity, TKey> And( Expression<Func<TEntity, bool>> predicate ) {
                if ( Criteria == null ) {
                    Criteria = new Criteria<TEntity>( predicate );
                    return this;
                }
                Criteria = new AndCriteria<TEntity>( Criteria.GetPredicate(), predicate );
                return this;
            }
    
            /// <summary>
            /// 或连接,将传入的查询条件合并到当前对象
            /// </summary>
            /// <param name="query">查询对象</param>
            public IQuery<TEntity, TKey> Or( IQuery<TEntity, TKey> query ) {
                return Or( query.GetPredicate() );
            }
    
            /// <summary>
            /// 或连接,将传入的查询条件合并到当前对象
            /// </summary>
            /// <param name="predicate">谓词</param>
            public IQuery<TEntity, TKey> Or( Expression<Func<TEntity, bool>> predicate ) {
                if ( Criteria == null ) {
                    Criteria = new Criteria<TEntity>( predicate );
                    return this;
                }
                Criteria = new OrCriteria<TEntity>( Criteria.GetPredicate(), predicate );
                return this;
            }
    
            #endregion
    
            #region OrderBy(排序)
    
            /// <summary>
            /// 添加排序,支持多次调用OrderBy创建多级排序
            /// </summary>
            /// <typeparam name="TProperty">属性类型</typeparam>
            /// <param name="expression">属性表达式</param>
            /// <param name="desc">是否降序</param>
            public IQuery<TEntity, TKey> OrderBy<TProperty>( Expression<Func<TEntity, TProperty>> expression, bool desc = false ) {
                return OrderBy( Lambda.GetName( expression ), desc );
            }
    
            /// <summary>
            /// 添加排序,支持多次调用OrderBy创建多级排序
            /// </summary>
            /// <param name="propertyName">排序属性</param>
            /// <param name="desc">是否降序</param>
            public IQuery<TEntity, TKey> OrderBy( string propertyName, bool desc = false ) {
                OrderBuilder.Add( propertyName, desc );
                GetOrderBy();
                return this;
            }
    
            #endregion
    
            #region Clear(清理)
    
            /// <summary>
            /// 清理
            /// </summary>
            public void Clear() {
                Criteria = null;
                OrderBuilder = new OrderByBuilder();
            }
    
            #endregion
    
            #region GetList(获取列表)
    
            /// <summary>
            /// 获取列表
            /// </summary>
            /// <param name="queryable">数据源</param>
            public List<TEntity> GetList( IQueryable<TEntity> queryable ) {
                return Execute( queryable ).OrderBy( Order ).ToList();
            }
    
            /// <summary>
            /// 执行过滤和分页
            /// </summary>
            private IQueryable<TEntity> Execute( IQueryable<TEntity> queryable ) {
                queryable.CheckNull( "queryable" );
                queryable = FilterBy( queryable );
                GetOrderBy();
                return queryable;
            }
    
            /// <summary>
            /// 过滤
            /// </summary>
            private IQueryable<TEntity> FilterBy( IQueryable<TEntity> queryable ) {
                if ( Criteria == null )
                    return queryable;
                return queryable.Where( Criteria.GetPredicate() );
            }
    
            #endregion
    
            #region GetPagerList(获取分页列表)
    
            /// <summary>
            /// 获取分页列表
            /// </summary>
            /// <param name="queryable">数据源</param>
            public PagerList<TEntity> GetPagerList( IQueryable<TEntity> queryable ) {
                return Execute( queryable ).PagerResult( this );
            }
    
            #endregion
        }
    }
    复制代码

      应用层服务可以这样查询。

    复制代码
            public PagerList<ApplicationDto> Query( ApplicationQuery query ) {
                return new Query<Application>(query)
                    .Filter( t => t.Code == query.Code )
                    .Filter( t => t.Name.Contains( query.Name ) )
                    .Filter( t => t.Enabled == query.Enabled )
                    .FilterDate( t => t.CreateTime, query.BeginCreateTime, query.EndCreateTime )
                    .GetPagerList( Repository.Find() ).Convert( t => t.ToDto() );
            }
    复制代码

    复制代码
            public PagerList<ApplicationDto> Query2( ApplicationQuery query ) {
                var queryObject = new Query<Application>( query )
                    .Filter( t => t.Code == query.Code )
                    .Filter( t => t.Name.Contains( query.Name ) )
                    .Filter( t => t.Enabled == query.Enabled )
                    .FilterDate( t => t.CreateTime, query.BeginCreateTime, query.EndCreateTime );
                return Repository.PagerQuery( queryObject ).Convert( t => t.ToDto() );
            }
    复制代码

      .Net应用程序框架交流QQ群: 386092459,欢迎有兴趣的朋友加入讨论。

      谢谢大家的持续关注,我的博客地址:http://www.cnblogs.com/xiadao521/

  • 相关阅读:
    linux查看CPU性能及工作状态的指令mpstat,vmstat,iostat,sar,top
    Linux vmstat命令实战详解
    dstat 性能监测工具
    sysstat 工具
    Linux命令详解----iostat
    Linux CPU实时监控mpstat命令详解
    Linux Top 命令解析 比较详细
    Linux统计/监控工具SAR详细介绍
    ubuntu 添加用户到已存在的组
    Ubuntu 14.04 使用速度极快的Genymotion 取代蜗牛速度的原生AVD模拟器
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/4237698.html
Copyright © 2011-2022 走看看