When using:
DateTime.ToString().Contains("2016")
Entity Framework produces:
CAST(DateValue AS nvarchar(max)) LIKE '%2016%'
This uses the default date-format "mon dd yyyy hh:miAM (or PM)"
I would like to user "yyyy-mm-dd hh:mi:ss (24h)" which is obtainable with something like:
CONVERT(VARCHAR(max), DateValue, 20) LIKE '%2016%'
I need help implementing this format to an existing generic method.
static Expression<Func<T, TResult>> Expr<T, TResult>(Expression<Func<T, TResult>> source) { return source; }
static MethodInfo GetMethod(this LambdaExpression source) { return ((MethodCallExpression)source.Body).Method; }
static readonly MethodInfo Object_ToString = Expr((object x) => x.ToString()).GetMethod();
static readonly MethodInfo String_Contains = Expr((string x) => x.Contains("y")).GetMethod();
public static IQueryable<T> Filter<T>(this IQueryable<T> query, List<SearchFilterDto> filters)
where T : BaseEntity
{
if (filters != null && filters.Count > 0 && !filters.Any(f => string.IsNullOrEmpty(f.Filter)))
{
var item = Expression.Parameter(query.ElementType, "item");
var body = filters.Select(f =>
{
var value = f.Column.Split('.').Aggregate((Expression)item, Expression.PropertyOrField);
if (value.Type != typeof(string))
{
value = Expression.Call(value, Object_ToString);
}
return (Expression)Expression.Call(value, String_Contains, Expression.Constant(f.Filter));
})
.Where(r => r != null)
.Aggregate(Expression.AndAlso);
var predicate = Expression.Lambda(body, item);
MethodInfo whereCall = (typeof(Queryable).GetMethods().First(mi => mi.Name == "Where" && mi.GetParameters().Length == 2).MakeGenericMethod(query.ElementType));
MethodCallExpression call = Expression.Call(whereCall, new Expression[] { query.Expression, predicate });
query = query.Provider.CreateQuery<T>(call);
}
return query;
}
Please note, this is an example - it will not always be "2016" and not always be a year. The user may type the time, or "01" to recall all records either on the 1st day of the month, January or in 2001. It's a very flexible filter.
I also understand that many people will not like this situation, but I am really looking for a solution here and not be told "don't do this"
The solution also needs to cater for LINQ to Entities, so I cant simply .ToString("MMM d yyyy H:mm tt") as this will result in:
"LINQ to Entities does not recognize the method 'System.String ToString(System.String)' method, and this method cannot be translated into a store expression."
The code works with the default date-format. The reason for my question is to change the date-format at SQL level, by manipulating the query in Entity Framework.