<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      應用程序框架實戰二十五:查詢條件(規約模式應用)

        前面已經做了一些準備工作,本篇將介紹查詢條件的封裝,它是規約模式的一個應用。

        規約使用一個對象來封裝謂詞,我之前已經介紹過它在驗證方面的應用,本篇是規約模式在查詢方面的應用。

        規約的強大之處在于,能夠將一堆雜亂無章的條件判斷或查詢條件封裝起來,以一個清晰的概念來表達,并使得這些謂詞具備了可復用的能力。

        首先在Util.Domains項目的Repositories目錄中創建ICriteria接口,這個接口表示一個查詢條件,代碼如下。

      using System;
      using System.Linq.Expressions;
      
      namespace Util.Domains.Repositories {
          /// <summary>
          /// 查詢條件
          /// </summary>
          /// <typeparam name="TEntity">實體類型</typeparam>
          public interface ICriteria<TEntity> where TEntity : class,IAggregateRoot {
              /// <summary>
              /// 獲取謂詞
              /// </summary>
              Expression<Func<TEntity, bool>> GetPredicate();
          }
      }

        由于我們使用了EF這種ORM框架,查詢條件的結果是一個Expression<Func<TEntity, bool>>的謂詞表達式。

        在Util.Datas項目中,打開Extensions.Query.cs文件,增加以下代碼。

              /// <summary>
              /// 過濾
              /// </summary>
              /// <typeparam name="T">實體類型</typeparam>
              /// <param name="source">數據源</param>
              /// <param name="criteria">查詢條件</param>
              public static IQueryable<T> Filter<T>( this IQueryable<T> source, ICriteria<T> criteria ) where T : class,IAggregateRoot {
                  if ( criteria == null )
                      return source;
                  var predicate = criteria.GetPredicate();
                  if ( predicate == null )
                      return source;
                  return source.Where( predicate );
              }

        我們在IQueryable對象上擴展了一個Filter方法,該方法接收一個查詢條件,如果查詢條件有效,就使用Where方法添加過濾條件。

        基礎工作就這么多,下面來看幾個范例。

        在信息系統中,經常會進行范圍查詢,比如一個日期段的查詢。這看起來是一個簡單的需求,初學者一般這樣寫,t => t.Date >= BeginDate && t.Date <= EndDate,其結果可能是錯誤的,這是由于從表現層傳入的查詢條件是可選的,如果客戶沒有進行輸入,結果就是錯的。

        對于范圍查詢來講,還有更多的細節需要思考,比如,起始日期和結束日期都沒有輸入,或只輸入了起始日期或結束日期,也可能客戶輸入的起始日期比結束日期還大。為了獲得健壯性,我們會對查詢條件進行各種判斷,從而導致雜亂無章的代碼。更要命的是,這些代碼無法復用,在另一個范圍查詢的位置,我們必須把之前的代碼復制過去進行修改。

        一個更好的辦法是把范圍查詢邏輯封裝到查詢條件對象中,以后需要進行范圍查詢時,即可隨手拈來。

        在Util.Datas項目Queries目錄中,新建Criterias目錄,創建一個查詢條件基類CriteriaBase,代碼如下。

      using System;
      using System.Linq.Expressions;
      using Util.Domains;
      using Util.Domains.Repositories;
      
      namespace Util.Datas.Queries.Criterias {
          /// <summary>
          /// 查詢條件
          /// </summary>
          /// <typeparam name="TEntity">實體類型</typeparam>
          public abstract class CriteriaBase<TEntity> : ICriteria<TEntity> where TEntity : class, IAggregateRoot {
              /// <summary>
              /// 謂詞
              /// </summary>
              protected Expression<Func<TEntity, bool>> Predicate { get; set; }
      
              /// <summary>
              /// 獲取謂詞
              /// </summary>
              public virtual Expression<Func<TEntity, bool>> GetPredicate() {
                  return Predicate;
              }
          }
      }

        根據數據類型不同,范圍查詢有很多種類,比如日期范圍查詢、日期時間范圍查詢、整數范圍查詢、浮點數范圍查詢等。我們需要為范圍查詢條件創建一個基類SegmentCriteria,代碼如下。

      using System;
      using System.Linq.Expressions;
      using Util.Domains;
      using Util.Lambdas;
      
      namespace Util.Datas.Queries.Criterias {
          /// <summary>
          /// 段過濾條件
          /// </summary>
          /// <typeparam name="TEntity">實體類型</typeparam>
          /// <typeparam name="TProperty">屬性類型</typeparam>
          /// <typeparam name="TValue">值類型</typeparam>
          public abstract class SegmentCriteria<TEntity, TProperty, TValue> : CriteriaBase<TEntity>
              where TEntity : class, IAggregateRoot
              where TValue : struct {
              /// <summary>
              /// 初始化段過濾條件
              /// </summary>
              /// <param name="propertyExpression">屬性表達式</param>
              /// <param name="min">最小值</param>
              /// <param name="max">最大值</param>
              protected SegmentCriteria( Expression<Func<TEntity, TProperty>> propertyExpression, TValue? min, TValue? max ) {
                  Builder = new ExpressionBuilder<TEntity>();
                  PropertyExpression = propertyExpression;
                  Min = min;
                  Max = max;
                  if ( IsMinGreaterMax( min, max ) ) {
                      Min = max;
                      Max = min;
                  }
              }
      
              /// <summary>
              /// 最小值是否大于最大值
              /// </summary>
              /// <param name="min">最小值</param>
              /// <param name="max">最大值</param>
              protected abstract bool IsMinGreaterMax( TValue? min, TValue? max );
      
              /// <summary>
              /// 屬性表達式
              /// </summary>
              public Expression<Func<TEntity, TProperty>> PropertyExpression { get; set; }
      
              /// <summary>
              /// 表達式生成器
              /// </summary>
              private ExpressionBuilder<TEntity> Builder { get; set; }
      
              /// <summary>
              /// 最小值
              /// </summary>
              public TValue? Min { get; set; }
      
              /// <summary>
              /// 最大值
              /// </summary>
              public TValue? Max { get; set; }
      
              /// <summary>
              /// 獲取謂詞
              /// </summary>
              public override Expression<Func<TEntity, bool>> GetPredicate() {
                  var first = CreateLeftExpression();
                  var second = CreateRightExpression();
                  return Builder.ToLambda( first.And( second ) );
              }
      
              /// <summary>
              /// 創建左操作數,即 t => t.Property >= Min
              /// </summary>
              private Expression CreateLeftExpression() {
                  if ( Min == null )
                      return null;
                  return Builder.Create( PropertyExpression, Operator.GreaterEqual, GetMinValue() );
              }
      
              /// <summary>
              /// 獲取最小值
              /// </summary>
              protected virtual TValue? GetMinValue() {
                  return Min;
              }
      
              /// <summary>
              /// 創建右操作數,即 t => t.Property &lt;= Max
              /// </summary>
              private Expression CreateRightExpression() {
                  if ( Max == null )
                      return null;
                  return Builder.Create( PropertyExpression, GetMaxOperator(), GetMaxValue() );
              }
      
              /// <summary>
              /// 獲取最大值相關的運算符
              /// </summary>
              protected virtual Operator GetMaxOperator() {
                  return Operator.LessEqual;
              }
      
              /// <summary>
              /// 獲取最大值
              /// </summary>
              protected virtual TValue? GetMaxValue() {
                  return Max;
              }
          }
      }

        對于日期范圍查詢,日期是否包含時間非常重要,它們在行為上是不同的。如果日期不包含時間,那么需要為結束日期加一天,并修改運算符為小于。

        日期時間范圍查詢條件DateTimeSegmentCriteria,代碼如下。

      using System;
      using System.Linq.Expressions;
      using Util.Domains;
      
      namespace Util.Datas.Queries.Criterias {
          /// <summary>
          /// 日期時間段過濾條件 - 包含時間
          /// </summary>
          /// <typeparam name="TEntity">實體類型</typeparam>
          /// <typeparam name="TProperty">屬性類型</typeparam>
          public class DateTimeSegmentCriteria<TEntity, TProperty> : SegmentCriteria<TEntity, TProperty, DateTime> where TEntity : class,IAggregateRoot {
              /// <summary>
              /// 初始化日期時間段過濾條件
              /// </summary>
              /// <param name="propertyExpression">屬性表達式</param>
              /// <param name="min">最小值</param>
              /// <param name="max">最大值</param>
              public DateTimeSegmentCriteria( Expression<Func<TEntity, TProperty>> propertyExpression, DateTime? min, DateTime? max )
                  : base( propertyExpression, min, max ) {
              }
      
              /// <summary>
              /// 最小值是否大于最大值
              /// </summary>
              protected override bool IsMinGreaterMax( DateTime? min, DateTime? max ) {
                  return min > max;
              }
          }
      }

        日期范圍查詢條件DateSegmentCriteria,代碼如下。

      using System;
      using System.Linq.Expressions;
      using Util.Domains;
      
      namespace Util.Datas.Queries.Criterias {
          /// <summary>
          /// 日期段過濾條件 - 不包含時間
          /// </summary>
          /// <typeparam name="TEntity">實體類型</typeparam>
          /// <typeparam name="TProperty">屬性類型</typeparam>
          public class DateSegmentCriteria<TEntity, TProperty> : SegmentCriteria<TEntity, TProperty, DateTime> where TEntity : class,IAggregateRoot {
              /// <summary>
              /// 初始化日期段過濾條件
              /// </summary>
              /// <param name="propertyExpression">屬性表達式</param>
              /// <param name="min">最小值</param>
              /// <param name="max">最大值</param>
              public DateSegmentCriteria( Expression<Func<TEntity, TProperty>> propertyExpression, DateTime? min, DateTime? max )
                  : base( propertyExpression, min, max ) {
              }
      
              /// <summary>
              /// 最小值是否大于最大值
              /// </summary>
              protected override bool IsMinGreaterMax( DateTime? min, DateTime? max ) {
                  return min > max;
              }
      
              /// <summary>
              /// 獲取最小值
              /// </summary>
              protected override DateTime? GetMinValue() {
                  return base.GetMinValue().SafeValue().Date;
              }
      
              /// <summary>
              /// 獲取最大值
              /// </summary>
              protected override DateTime? GetMaxValue() {
                  return base.GetMaxValue().SafeValue().Date.AddDays( 1 );
              }
      
              /// <summary>
              /// 獲取最大值相關的運算符
              /// </summary>
              protected override Operator GetMaxOperator() {
                  return Operator.Less;
              }
          }
      }

        整數范圍查詢條件IntSegmentCriteria,代碼如下。

      using System;
      using System.Linq.Expressions;
      using Util.Domains;
      
      namespace Util.Datas.Queries.Criterias {
          /// <summary>
          /// 整數段過濾條件
          /// </summary>
          /// <typeparam name="TEntity">實體類型</typeparam>
          /// <typeparam name="TProperty">屬性類型</typeparam>
          public class IntSegmentCriteria<TEntity, TProperty> : SegmentCriteria<TEntity, TProperty,int> where TEntity : class,IAggregateRoot {
              /// <summary>
              /// 初始化整數段過濾條件
              /// </summary>
              /// <param name="propertyExpression">屬性表達式</param>
              /// <param name="min">最小值</param>
              /// <param name="max">最大值</param>
              public IntSegmentCriteria( Expression<Func<TEntity, TProperty>> propertyExpression, int? min, int? max ) 
                  : base( propertyExpression,min,max){
              }
      
              /// <summary>
              /// 最小值是否大于最大值
              /// </summary>
              protected override bool IsMinGreaterMax( int? min, int? max ) {
                  return min > max;
              }
          }
      }

        double范圍查詢條件DoubleSegmentCriteria,代碼如下。

      using System;
      using System.Linq.Expressions;
      using Util.Domains;
      
      namespace Util.Datas.Queries.Criterias {
          /// <summary>
          /// double數值段過濾條件
          /// </summary>
          /// <typeparam name="TEntity">實體類型</typeparam>
          /// <typeparam name="TProperty">屬性類型</typeparam>
          public class DoubleSegmentCriteria<TEntity, TProperty> : SegmentCriteria<TEntity, TProperty, double> where TEntity : class,IAggregateRoot {
              /// <summary>
              /// 初始化double數值段過濾條件
              /// </summary>
              /// <param name="propertyExpression">屬性表達式</param>
              /// <param name="min">最小值</param>
              /// <param name="max">最大值</param>
              public DoubleSegmentCriteria( Expression<Func<TEntity, TProperty>> propertyExpression, double? min, double? max )
                  : base( propertyExpression, min, max ) {
              }
      
              /// <summary>
              /// 最小值是否大于最大值
              /// </summary>
              protected override bool IsMinGreaterMax( double? min, double? max ) {
                  return min > max;
              }
          }
      }

        decimal范圍查詢條件DecimalSegmentCriteria,代碼如下。

      using System;
      using System.Linq.Expressions;
      using Util.Domains;
      
      namespace Util.Datas.Queries.Criterias {
          /// <summary>
          /// decimal數值段過濾條件
          /// </summary>
          /// <typeparam name="TEntity">實體類型</typeparam>
          /// <typeparam name="TProperty">屬性類型</typeparam>
          public class DecimalSegmentCriteria<TEntity, TProperty> : SegmentCriteria<TEntity, TProperty, decimal> where TEntity : class,IAggregateRoot {
              /// <summary>
              /// 初始化decimal數值段過濾條件
              /// </summary>
              /// <param name="propertyExpression">屬性表達式</param>
              /// <param name="min">最小值</param>
              /// <param name="max">最大值</param>
              public DecimalSegmentCriteria( Expression<Func<TEntity, TProperty>> propertyExpression, decimal? min, decimal? max )
                  : base( propertyExpression, min, max ) {
              }
      
              /// <summary>
              /// 最小值是否大于最大值
              /// </summary>
              protected override bool IsMinGreaterMax( decimal? min, decimal? max ) {
                  return min > max;
              }
          }
      }

        我們現在進行日期范圍查詢,就比較簡單了,代碼如下。

      queryable.Filter( new DateSegmentCriteria<Test, DateTime>( t => t.Date, BeginDate,EndDate ) );

        不過上面的代碼用起來還不是太順手,可以將范圍查詢擴展到IQueryable,代碼如下。

      /// <summary>
              /// 過濾整數段
              /// </summary>
              /// <typeparam name="T">實體類型</typeparam>
              /// <typeparam name="TProperty">屬性類型</typeparam>
              /// <param name="source">數據源</param>
              /// <param name="propertyExpression">屬性表達式,范例:t => t.Age</param>
              /// <param name="min">最小值</param>
              /// <param name="max">最大值</param>
              public static IQueryable<T> FilterInt<T, TProperty>( this IQueryable<T> source,
                  Expression<Func<T, TProperty>> propertyExpression, int? min, int? max ) where T : class,IAggregateRoot {
                  return source.Filter( new IntSegmentCriteria<T, TProperty>( propertyExpression, min, max ) );
              }
      
              /// <summary>
              /// 過濾double數值段
              /// </summary>
              /// <typeparam name="T">實體類型</typeparam>
              /// <typeparam name="TProperty">屬性類型</typeparam>
              /// <param name="source">數據源</param>
              /// <param name="propertyExpression">屬性表達式,范例:t => t.Age</param>
              /// <param name="min">最小值</param>
              /// <param name="max">最大值</param>
              public static IQueryable<T> FilterDouble<T, TProperty>( this IQueryable<T> source,
                  Expression<Func<T, TProperty>> propertyExpression, double? min, double? max ) where T : class,IAggregateRoot {
                  return source.Filter( new DoubleSegmentCriteria<T, TProperty>( propertyExpression, min, max ) );
              }
      
              /// <summary>
              /// 過濾decimal數值段
              /// </summary>
              /// <typeparam name="T">實體類型</typeparam>
              /// <typeparam name="TProperty">屬性類型</typeparam>
              /// <param name="source">數據源</param>
              /// <param name="propertyExpression">屬性表達式,范例:t => t.Age</param>
              /// <param name="min">最小值</param>
              /// <param name="max">最大值</param>
              public static IQueryable<T> FilterDecimal<T, TProperty>( this IQueryable<T> source,
                  Expression<Func<T, TProperty>> propertyExpression, decimal? min, decimal? max ) where T : class,IAggregateRoot {
                  return source.Filter( new DecimalSegmentCriteria<T, TProperty>( propertyExpression, min, max ) );
              }
      
              /// <summary>
              /// 過濾日期段,不包含時間
              /// </summary>
              /// <typeparam name="T">實體類型</typeparam>
              /// <typeparam name="TProperty">屬性類型</typeparam>
              /// <param name="source">數據源</param>
              /// <param name="propertyExpression">屬性表達式,范例:t => t.Age</param>
              /// <param name="min">最小值</param>
              /// <param name="max">最大值</param>
              public static IQueryable<T> FilterDate<T, TProperty>( this IQueryable<T> source,
                  Expression<Func<T, TProperty>> propertyExpression, DateTime? min, DateTime? max ) where T : class,IAggregateRoot {
                  return source.Filter( new DateSegmentCriteria<T, TProperty>( propertyExpression, min, max ) );
              }
      
              /// <summary>
              /// 過濾日期時間段,包含時間
              /// </summary>
              /// <typeparam name="T">實體類型</typeparam>
              /// <typeparam name="TProperty">屬性類型</typeparam>
              /// <param name="source">數據源</param>
              /// <param name="propertyExpression">屬性表達式,范例:t => t.Age</param>
              /// <param name="min">最小值</param>
              /// <param name="max">最大值</param>
              public static IQueryable<T> FilterDateTime<T, TProperty>( this IQueryable<T> source,
                  Expression<Func<T, TProperty>> propertyExpression, DateTime? min, DateTime? max ) where T : class,IAggregateRoot {
                  return source.Filter( new DateTimeSegmentCriteria<T, TProperty>( propertyExpression, min, max ) );
              }

        日期范圍查詢的調用代碼簡化為如下代碼。 

      queryable.FilterDate( t => t.Date, BeginDate, EndDate)

        本文介紹了如何使用查詢條件對象封裝范圍查詢,當然你可以用類似的方法將業務中的查詢條件封裝起來。

        規約模式還有其它用法,更強大的用法,請參考陳晴陽老兄的這篇http://www.rzrgm.cn/daxnet/p/3925426.html

       

        .Net應用程序框架交流QQ群: 386092459,歡迎有興趣的朋友加入討論。

        謝謝大家的持續關注,我的博客地址:http://www.rzrgm.cn/xiadao521/

       

      posted @ 2015-01-20 01:26  何鎮汐  閱讀(4217)  評論(14)    收藏  舉報
      主站蜘蛛池模板: 少妇激情a∨一区二区三区| 小伙无套内射老熟女精品| 五月天天天综合精品无码| 亚洲综合精品中文字幕| 国产精品人妻一码二码尿失禁| 久热这里只有精品在线观看| 一区二区中文字幕av| 中文无码乱人伦中文视频在线| 欧美乱大交aaaa片if| 东京热大乱系列无码| 久久羞羞色院精品全部免费| 国产av一区二区三区| 美女午夜福利视频一区二区| 国产午夜福利视频合集| 亚洲男女羞羞无遮挡久久丫| 在线亚洲午夜片av大片| 亚洲中文字幕无码爆乳APP| 日韩丝袜亚洲国产欧美一区| 色偷偷亚洲男人的天堂| 国产精品一线天在线播放| 99精品国产综合久久久久五月天| 久久综合久中文字幕青草| 国产色悠悠视频在线观看| 久久av色欲av久久蜜桃网| 高清无打码一区二区三区| 崇文区| 色婷婷日日躁夜夜躁| 久久一日本道色综合久久| 亚洲国产v高清在线观看| 国产丝袜肉丝视频在线| 漂亮人妻被中出中文字幕| 亚洲综合一区二区三区不卡| 国产精品一区中文字幕| 人妻中出无码中字在线| 熟女精品国产一区二区三区| 日日碰狠狠躁久久躁96avv| 天天噜噜日日久久综合网| 精品不卡一区二区三区| 中文字幕永久精品国产| 国产美女久久久亚洲综合| 精品国产熟女一区二区三区|