應用程式框架實戰二十六:查詢物件
阿新 • • 發佈:2018-12-27
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
}
}