Как сравнить только компоненты даты из DateTime в EF?
У меня есть два значения даты, один уже хранится в базе данных, а другой выбран пользователем с помощью DatePicker. Вариант использования заключается в поиске определенной даты из базы данных.
значение, ранее введенное в базу данных, всегда имеет компонент времени 12: 00: 00, Где в качестве даты, введенной из средства выбора, имеет другой компонент времени.
меня интересуют только компоненты даты и я хотел бы игнорировать компонент времени.
что способов сделать это сравнение в C#?
кроме того, как это сделать в LINQ?
обновление: В LINQ to Entities отлично работает следующее.
e => DateTime.Compare(e.FirstDate.Value, SecondDate) >= 0
15 ответов:
Примечание: на момент написания этого ответа отношение EF было неясным (которое было отредактировано в вопрос после того, как это было написано). Для правильного подхода с EF, проверьте Mandeeps ответ.
можно использовать
DateTime.Date
свойство для выполнения сравнения только по дате.DateTime a = GetFirstDate(); DateTime b = GetSecondDate(); if (a.Date.Equals(b.Date)) { // the dates are equal }
использовать класс
EntityFunctions
для обрезки временной части.using System.Data.Objects; var bla = (from log in context.Contacts where EntityFunctions.TruncateTime(log.ModifiedDate) == EntityFunctions.TruncateTime(today.Date) select log).FirstOrDefault();
обновление
начиная с EF 6.0 и более поздних EntityFunctions заменяется на DbFunctions.
Я думаю, это может помочь вам.
Я сделал расширение, так как мне нужно сравнить даты в репозиториях, заполненных данными EF, и так далее .Дата не была опцией, так как она не реализована в переводе LinqToEntities.
вот код:
/// <summary> /// Check if two dates are same /// </summary> /// <typeparam name="TElement">Type</typeparam> /// <param name="valueSelector">date field</param> /// <param name="value">date compared</param> /// <returns>bool</returns> public Expression<Func<TElement, bool>> IsSameDate<TElement>(Expression<Func<TElement, DateTime>> valueSelector, DateTime value) { ParameterExpression p = valueSelector.Parameters.Single(); var antes = Expression.GreaterThanOrEqual(valueSelector.Body, Expression.Constant(value.Date, typeof(DateTime))); var despues = Expression.LessThan(valueSelector.Body, Expression.Constant(value.AddDays(1).Date, typeof(DateTime))); Expression body = Expression.And(antes, despues); return Expression.Lambda<Func<TElement, bool>>(body, p); }
затем вы можете использовать его таким образом.
var today = DateTime.Now; var todayPosts = from t in turnos.Where(IsSameDate<Turno>(t => t.MyDate, today)) select t);
Если вы используете
Date
свойство для объектов БД вы получите исключение:"The specified type member 'Date' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported."
вы можете использовать что-то вроде этого:
DateTime date = DateTime.Now.Date; var result = from client in context.clients where client.BirthDate >= date && client.BirthDate < date.AddDays(1) select client;
чтобы сделать это в LINQ to Entities, вы должны использовать поддерживаемые способы:
var year = someDate.Year; var month = ... var q = from r in Context.Records where Microsoft.VisualBasic.DateAndTime.Year(r.SomeDate) == year && // month and day
некрасиво, но это работает, и это делается на сервере БД.
вот другой способ сделать это, но это полезно только в том случае, если SecondDate-это переменная, которую вы передаете:
DateTime startDate = SecondDate.Date; DateTime endDate = startDate.AddDays(1).AddTicks(-1); ... e => e.FirstDate.Value >= startDate && e.FirstDate.Value <= endDate
Я думаю, что это должно работать
просто всегда сравниваю дата свойство DateTime, вместо полного времени даты.
при создании запроса LINQ используйте date.Дата в запросе, т. е.:
var results = from c in collection where c.Date == myDateTime.Date select c;
вот как я это делаю.
DateTime date_time_to_compare = DateTime.Now; //Compare only date parts context.YourObject.FirstOrDefault(r => EntityFunctions.TruncateTime(r.date) == EntityFunctions.TruncateTime(date_to_compare));
/ / Примечание Для пользователей Linq / кодеров
Это должно дать вам точное сравнение для проверки того, попадает ли дата в диапазон при работе с вводом из средства выбора даты пользователя, например:
((DateTime)ri.RequestX.DateSatisfied).Date >= startdate.Date && ((DateTime)ri.RequestX.DateSatisfied).Date <= enddate.Date
где startdate и enddate-значения из средства выбора даты.
вы можете использовать DbFunctions.Метод TruncateTime () для этого.
e => DbFunctions.TruncateTime(e.FirstDate.Value) == DbFunctions.TruncateTime(SecondDate);
вы можете пользователь ниже ссылку для сравнения 2 даты без времени:
private bool DateGreaterOrEqual(DateTime dt1, DateTime dt2) { return DateTime.Compare(dt1.Date, dt2.Date) >= 0; } private bool DateLessOrEqual(DateTime dt1, DateTime dt2) { return DateTime.Compare(dt1.Date, dt2.Date) <= 0; }
функция сравнения возвращает 3 различных значения: -1 0 1, Что означает dt1>dt2, dt1=dt2, dt1
без времени, чем попробовать вот так:
TimeSpan ts = new TimeSpan(23, 59, 59); toDate = toDate.Add(ts); List<AuditLog> resultLogs = _dbContext.AuditLogs .Where(al => al.Log_Date >= fromDate && al.Log_Date <= toDate) .ToList(); return resultLogs;
попробуйте это... Он отлично работает для сравнения свойств даты между двумя датами типа:
PS. Это временное решение и действительно плохая практика, никогда не следует использовать, когда вы знаете, что база данных может принести тысячи записей...
query = query.ToList() .Where(x => x.FirstDate.Date == SecondDate.Date) .AsQueryable();