1313/// <summary>
1414/// A generic query executor that can be used to execute queries on IQueryable data sources.
1515/// </summary>
16- [ SuppressMessage ( "StyleCop.CSharp.SpacingRules" , "SA1009:Closing parenthesis should be spaced correctly" , Justification = "..." ) ]
1716[ SuppressMessage ( "StyleCop.CSharp.SpacingRules" , "SA1025:Code should not contain multiple whitespace in a row" , Justification = "..." ) ]
1817public static class QueryExecutor
1918{
@@ -80,6 +79,7 @@ private static Expression BuildConditionExpression<TEntity>(DataContext db, IQue
8079 var targetType = property . PropertyType ;
8180 var searchValue = GetSearchValue ( filter . SearchVal , targetType ) ;
8281 var emptyValue = GetEmptyValue ( targetType ) ;
82+ var now = DateTime . Now . Date ;
8383 Expression condition = filter . Condition . Name switch
8484 {
8585 "null" => targetType . IsNullableType ( ) ? Expression . Equal ( field , Expression . Constant ( targetType . GetDefaultValue ( ) ) ) : Expression . Constant ( false ) ,
@@ -90,28 +90,28 @@ private static Expression BuildConditionExpression<TEntity>(DataContext db, IQue
9090 "doesNotEqual" => Expression . NotEqual ( field , searchValue ) ,
9191 "inQuery" => BuildInExpression ( db , filter . SearchTree , field ) ,
9292 "notInQuery" => Expression . Not ( BuildInExpression ( db , filter . SearchTree , field ) ) ,
93- "contains" => Expression . Call ( field , typeof ( string ) . GetMethod ( "Contains" , new [ ] { typeof ( string ) } ) ! , searchValue ) ,
94- "doesNotContain" => Expression . Not ( Expression . Call ( field , typeof ( string ) . GetMethod ( "Contains" , new [ ] { typeof ( string ) } ) ! , searchValue ) ) ,
95- "startsWith" => Expression . Call ( field , typeof ( string ) . GetMethod ( "StartsWith" , new [ ] { typeof ( string ) } ) ! , searchValue ) ,
96- "endsWith" => Expression . Call ( field , typeof ( string ) . GetMethod ( "EndsWith" , new [ ] { typeof ( string ) } ) ! , searchValue ) ,
93+ "contains" => CallContains ( field , searchValue ) ,
94+ "doesNotContain" => Expression . Not ( CallContains ( field , searchValue ) ) ,
95+ "startsWith" => CallStartsWith ( field , searchValue ) ,
96+ "endsWith" => CallEndsWith ( field , searchValue ) ,
9797 "greaterThan" => Expression . GreaterThan ( field , searchValue ) ,
9898 "lessThan" => Expression . LessThan ( field , searchValue ) ,
9999 "greaterThanOrEqualTo" => Expression . GreaterThanOrEqual ( field , searchValue ) ,
100100 "lessThanOrEqualTo" => Expression . LessThanOrEqual ( field , searchValue ) ,
101- "before" => Expression . LessThan ( Expression . Call ( field , typeof ( string ) . GetMethod ( "CompareTo" , new [ ] { typeof ( string ) } ) ! , searchValue ) , Expression . Constant ( 0 ) ) ,
102- "after" => Expression . GreaterThan ( Expression . Call ( field , typeof ( string ) . GetMethod ( "CompareTo" , new [ ] { typeof ( string ) } ) ! , searchValue ) , Expression . Constant ( 0 ) ) ,
103- "today" => Expression . Call ( field , typeof ( string ) . GetMethod ( "StartsWith" , new [ ] { typeof ( string ) } ) ! , Expression . Constant ( DateTime . Now . Date . ToString ( "yyyy-MM-dd" , CultureInfo . InvariantCulture ) ) ) ,
104- "yesterday" => Expression . Call ( field , typeof ( string ) . GetMethod ( "StartsWith" , new [ ] { typeof ( string ) } ) ! , Expression . Constant ( DateTime . Now . Date . AddDays ( - 1 ) . ToString ( "yyyy-MM-dd" , CultureInfo . InvariantCulture ) ) ) ,
105- "thisMonth" => Expression . Call ( field , typeof ( string ) . GetMethod ( "StartsWith" , new [ ] { typeof ( string ) } ) ! , Expression . Constant ( DateTime . Now . Date . ToString ( "yyyy-MM" , CultureInfo . InvariantCulture ) ) ) ,
106- "lastMonth" => Expression . Call ( field , typeof ( string ) . GetMethod ( "StartsWith" , new [ ] { typeof ( string ) } ) ! , Expression . Constant ( DateTime . Now . Date . AddMonths ( - 1 ) . ToString ( "yyyy-MM" , CultureInfo . InvariantCulture ) ) ) ,
107- "nextMonth" => Expression . Call ( field , typeof ( string ) . GetMethod ( "StartsWith" , new [ ] { typeof ( string ) } ) ! , Expression . Constant ( DateTime . Now . Date . AddMonths ( 1 ) . ToString ( "yyyy-MM" , CultureInfo . InvariantCulture ) ) ) ,
108- "thisYear" => Expression . Call ( field , typeof ( string ) . GetMethod ( "StartsWith" , new [ ] { typeof ( string ) } ) ! , Expression . Constant ( DateTime . Now . Date . ToString ( "yyyy" , CultureInfo . InvariantCulture ) ) ) ,
109- "lastYear" => Expression . Call ( field , typeof ( string ) . GetMethod ( "StartsWith" , new [ ] { typeof ( string ) } ) ! , Expression . Constant ( DateTime . Now . Date . AddYears ( - 1 ) . ToString ( "yyyy" , CultureInfo . InvariantCulture ) ) ) ,
110- "nextYear" => Expression . Call ( field , typeof ( string ) . GetMethod ( "StartsWith" , new [ ] { typeof ( string ) } ) ! , Expression . Constant ( DateTime . Now . Date . AddYears ( 1 ) . ToString ( "yyyy" , CultureInfo . InvariantCulture ) ) ) ,
101+ "before" => Expression . LessThan ( CallCompare ( field , searchValue ) , Expression . Constant ( 0 ) ) ,
102+ "after" => Expression . GreaterThan ( CallCompare ( field , searchValue ) , Expression . Constant ( 0 ) ) ,
103+ "today" => CallStartsWith ( field , now . ToString ( "yyyy-MM-dd" , CultureInfo . InvariantCulture ) ) ,
104+ "yesterday" => CallStartsWith ( field , now . AddDays ( - 1 ) . ToString ( "yyyy-MM-dd" , CultureInfo . InvariantCulture ) ) ,
105+ "thisMonth" => CallStartsWith ( field , now . ToString ( "yyyy-MM" , CultureInfo . InvariantCulture ) ) ,
106+ "lastMonth" => CallStartsWith ( field , now . AddMonths ( - 1 ) . ToString ( "yyyy-MM" , CultureInfo . InvariantCulture ) ) ,
107+ "nextMonth" => CallStartsWith ( field , now . AddMonths ( 1 ) . ToString ( "yyyy-MM" , CultureInfo . InvariantCulture ) ) ,
108+ "thisYear" => CallStartsWith ( field , now . ToString ( "yyyy" , CultureInfo . InvariantCulture ) ) ,
109+ "lastYear" => CallStartsWith ( field , now . AddYears ( - 1 ) . ToString ( "yyyy" , CultureInfo . InvariantCulture ) ) ,
110+ "nextYear" => CallStartsWith ( field , now . AddYears ( 1 ) . ToString ( "yyyy" , CultureInfo . InvariantCulture ) ) ,
111111 "at" => Expression . Equal ( field , searchValue ) ,
112112 "not_at" => Expression . NotEqual ( field , searchValue ) ,
113- "at_before" => Expression . LessThan ( Expression . Call ( field , typeof ( string ) . GetMethod ( "CompareTo" , new [ ] { typeof ( string ) } ) ! , searchValue ) , Expression . Constant ( 0 ) ) ,
114- "at_after" => Expression . GreaterThan ( Expression . Call ( field , typeof ( string ) . GetMethod ( "CompareTo" , new [ ] { typeof ( string ) } ) ! , searchValue ) , Expression . Constant ( 0 ) ) ,
113+ "at_before" => Expression . LessThan ( CallCompare ( field , searchValue ) , Expression . Constant ( 0 ) ) ,
114+ "at_after" => Expression . GreaterThan ( CallCompare ( field , searchValue ) , Expression . Constant ( 0 ) ) ,
115115 "all" => Expression . Constant ( true ) ,
116116 "true" => Expression . IsTrue ( field ) ,
117117 "false" => Expression . IsFalse ( field ) ,
@@ -138,6 +138,40 @@ private static Expression BuildConditionExpression<TEntity>(DataContext db, IQue
138138 }
139139 }
140140
141+ private static Expression CallContains ( Expression field , Expression searchValue )
142+ {
143+ var containsMethod = typeof ( string ) . GetMethod ( "Contains" , new [ ] { typeof ( string ) } ) ;
144+ return Expression . Call ( field , containsMethod ! , searchValue ) ;
145+ }
146+
147+ private static Expression CallStartsWith ( Expression field , Expression searchValue )
148+ {
149+ var startsWithMethod = typeof ( string ) . GetMethod ( "StartsWith" , new [ ] { typeof ( string ) } ) ;
150+ return Expression . Call ( field , startsWithMethod ! , searchValue ) ;
151+ }
152+
153+ private static Expression CallStartsWith ( Expression field , string dateLiteral )
154+ {
155+ return CallStartsWith ( field , Expression . Constant ( dateLiteral ) ) ;
156+ }
157+
158+ private static Expression CallEndsWith ( Expression field , Expression searchValue )
159+ {
160+ var endsWithMethod = typeof ( string ) . GetMethod ( "EndsWith" , new [ ] { typeof ( string ) } ) ;
161+ return Expression . Call ( field , endsWithMethod ! , searchValue ) ;
162+ }
163+
164+ private static Expression CallEndsWith ( Expression field , string dateLiteral )
165+ {
166+ return CallEndsWith ( field , Expression . Constant ( dateLiteral ) ) ;
167+ }
168+
169+ private static Expression CallCompare ( Expression field , Expression searchValue )
170+ {
171+ var compareMethod = typeof ( string ) . GetMethod ( "Compare" , new [ ] { typeof ( string ) , typeof ( string ) } ) ;
172+ return Expression . Call ( compareMethod ! , field , searchValue ) ;
173+ }
174+
141175 private static Expression BuildInExpression ( DataContext db , Query ? query , MemberExpression field )
142176 {
143177 return field . Type switch
0 commit comments