I'm using PredicateBuilder to generate dynamic search clauses. In the sample code below, is there a way that I can modify SetDateTimePredicate so it can be used for any DateTime property on SomeType?
Expression<Func<SomeType, bool>> somePredicate = null;
somePredicate = somePredicate.Or(
SetDateTimePredicate(comparisonOperator, dateTime1, dateTime2));
private Expression<Func<SomeType, bool>> SetDateTimePredicate(
Enums.ComparisonOperator comparison,
DateTime dateTime1,
DateTime dateTime2)
{
switch (comparison)
{
case Enums.ComparisonOperator.IsLessThan:
return p => p.SomeDateProperty < dateTime1;
case Enums.ComparisonOperator.IsLessThanOrEqualTo:
return p => p.SomeDateProperty <= dateTime1;
case Enums.ComparisonOperator.IsGreaterThan:
return p => p.SomeDateProperty > dateTime1;
case Enums.ComparisonOperator.IsGreaterThanOrEqualTo:
return p => p.SomeDateProperty >= dateTime1;
case Enums.ComparisonOperator.IsBetween:
return p => p.SomeDateProperty >= dateTime1
&& p.SomeDateProperty <= dateTime2;
default:
return p => p.SomeDateProperty == dateTime1;
}
}
I tried an extension method but get this error:
System.NotSupportedException occurred
Message="Method 'Boolean Compare(System.DateTime, ComparisonOperator, System.DateTime, System.DateTime)' has no supported translation to SQL."
Extension method:
public static bool Compare(
this DateTime dateToCompare,
Enums.ComparisonOperator comparison,
DateTime dateTime1,
DateTime dateTime2)
{
switch (comparison)
{
case Enums.ComparisonOperator.IsLessThan:
return dateToCompare < dateTime1;
case Enums.ComparisonOperator.IsLessThanOrEqualTo:
return dateToCompare <= dateTime1;
case Enums.ComparisonOperator.IsGreaterThan:
return dateToCompare > dateTime1;
case Enums.ComparisonOperator.IsGreaterThanOrEqualTo:
return dateToCompare >= dateTime1;
case Enums.ComparisonOperator.IsBetween:
return dateToCompare >= dateTime1
&& dateToCompare <= dateTime2;
default:
return dateToCompare == dateTime1;
}
}
Sample with extension method:
somePredicate = somePredicate.Or(
p => p.SomeDateProperty.Compare(comparisonOperator, dateTime1, dateTime2));
Below is a generic solution, that could be used for any type that has the comparison operators defined not just DateTime. I made the methods, extension methods on the Enum.ComparisionOperator type. It would be used like:
Expression<Func<SomeType, bool>> somePredicate = comparisonOperator.Compare(
(SomeType p) => p.SomeDateProperty, dateTime1, dateTime2));
The methods defined as:
public static Expression<Func<TSource, bool>> Compare<TSource, TValue>(
this Enums.ComparisonOperator comparison,
Expression<Func<TSource, TValue>> source,
TValue value1, TValue value2)
{
var value1Expr = Expression.Constant(value1);
var value2Expr = Expression.Constant(value2);
var newExpr = comparison.CompareExpr(source.Body, value1Expr, value2Expr);
return Expression.Lambda<Func<TSource, bool>>(newExpr, source.Parameters);
}
public static Expression CompareExpr(
this Enums.ComparisonOperator comparison,
Expression exprLeft,
Expression exprRight1, Expression exprRight2)
{
switch (comparison)
{
case Enums.ComparisonOperator.IsLessThan:
return Expression.LessThan(exprLeft, exprRight1);
case Enums.ComparisonOperator.IsLessThanOrEqualTo:
return Expression.LessThanOrEqual(exprLeft, exprRight1);
case Enums.ComparisonOperator.IsGreaterThan:
return Expression.GreaterThan(exprLeft, exprRight1);
case Enums.ComparisonOperator.IsGreaterThanOrEqualTo:
return Expression.GreaterThanOrEqual(exprLeft, exprRight1);
case Enums.ComparisonOperator.IsBetween:
return Expression.AndAlso(
Expression.GreaterThanOrEqual(exprLeft, exprRight1),
Expression.LessThanOrEqual(exprLeft, exprRight2));
default:
return Expression.Equal(exprLeft, exprRight1);
}
}
Edit: I changed the methods above to be generic.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With