При использовании:C# Generic DateTime.ToString() с пользовательским форматом
DateTime.ToString().Contains("2016")
Entity Framework производит:
CAST(DateValue AS nvarchar(max)) LIKE '%2016%'
Это используется по умолчанию дата в формате «гггг чч в пн дд: Miam (или PM)»
Я хотел бы пользователь„гггг-мм-дд чч: ми: сс (24 часа)“, который можно получить что-то вроде:
CONVERT(VARCHAR(max), DateValue, 20) LIKE '%2016%'
Мне нужна помощь в реализации этого формата для существующего общего метода.
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;
}
Пожалуйста, обратите внимание, что это пример - это не всегда будет «2016», и не всегда в год. Пользователь может ввести время или «01», чтобы вызвать все записи либо в первый день месяца, январь, либо в 2001 году. Это очень гибкий фильтр.
Я также понимаю, что многие люди не нравится эта ситуация, но я действительно ищет решения здесь и не сказали «не делать этого»
Решение также необходимо для удовлетворения LINQ для лиц , поэтому я не могу просто. ToString («MMM d yyyy H: mm tt»), так как это приведет к:
«LINQ to Entities не распознает метод« System.String ToString (System.String) », и этот метод не может быть переведен в выражение хранилища ».
Код работает со стандартным форматом даты. Причина моего вопроса - изменить формат даты на уровне SQL, манипулируя запросом в Entity Framework.
Я не думаю, что с помощью LIKE с датами такая хорошая идея. Вероятно, вы могли бы получить более эффективный запрос, не преобразовывая дату в строку. Что вы на самом деле пытаетесь достичь, т. Е. Что бы вы использовали вместо «xyz» на практике? –
@MattiVirkkunen, я заменил xyz лучшим примером - 2016. Текст поступает из открытого текстового поля. Если у вас есть лучший способ работать с датами, я все для этого! Он просто должен быть гибким и точным, независимо от того, что содержит строка/фильтр. –
Вы не должны смешивать код и данные. Вероятно, вы должны разобрать текстовое поле в целое число (чтобы получить год). SQL имеет функцию DATEPART, вероятно, EF переведет DateTime.Year == значение в DATEPART. –