Как сравнить только компоненты даты с DateTime в EF?
У меня есть два значения даты, один из которых уже сохранен в базе данных, а другой выбран пользователем, использующим DatePicker. Вариант использования - поиск определенной даты из базы данных.
Значение, ранее введенное в базу данных, всегда имеет компонент времени в 12:00:00, где, когда дата, введенная с помощью сборщика, имеет разную временную составляющую.
Я интересуюсь только компонентами даты и хотел бы игнорировать компонент времени.
Каковы способы сделать это сравнение на С#?
Также, как это сделать в LINQ?
UPDATE:
В LINQ to Entities выполняется следующее:
e => DateTime.Compare(e.FirstDate.Value, SecondDate) >= 0
Ответы
Ответ 1
ПРИМЕЧАНИЕ: во время написания этого ответа отношение EF было неясным (это было отредактировано в вопрос после того, как это было написано). Для правильного подхода с EF, отметьте ответ Mandeeps.
Вы можете использовать свойство DateTime.Date
для сравнения только даты.
DateTime a = GetFirstDate();
DateTime b = GetSecondDate();
if (a.Date.Equals(b.Date))
{
// the dates are equal
}
Ответ 2
Используйте класс EntityFunctions
для обрезки временной части.
using System.Data.Objects;
var bla = (from log in context.Contacts
where EntityFunctions.TruncateTime(log.ModifiedDate) == EntityFunctions.TruncateTime(today.Date)
select log).FirstOrDefault();
Источник: http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/84d4e18b-7545-419b-9826-53ff1a0e2a62/
UPDATE
Начиная с EF 6.0 и более поздних версий EntityFunctions заменяется на DbFunctions.
Ответ 3
Я думаю, это может помочь вам.
Я сделал расширение, так как мне приходится сравнивать даты в репозиториях, заполненных данными EF, и поэтому .Date не был вариантом, поскольку он не реализован в переводе 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);
Ответ 4
Если вы используете свойство Date
для объектов DB, вы получите исключение:
"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;
Ответ 5
Чтобы сделать это в 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
Ужасно, но он работает, и это делается на сервере БД.
Ответ 6
Здесь другой способ сделать это, но это полезно только в том случае, если SecondDate - это переменная, которую вы передаете:
DateTime startDate = SecondDate.Date;
DateTime endDate = startDate.AddDays(1).AddTicks(-1);
...
e => e.FirstDate.Value >= startDate && e.FirstDate.Value <= endDate
Я думаю, что это должно работать
Ответ 7
Вы также можете использовать это:
DbFunctions.DiffDays(date1, date2) == 0
Ответ 8
Просто сравните свойство Date объекта DateTime, а не время полной даты.
Когда вы делаете свой запрос LINQ, используйте date.Date в запросе, то есть:
var results = from c in collection
where c.Date == myDateTime.Date
select c;
Ответ 9
Просто, если кто-то прибыл сюда по поисковому расписанию или бингу... скомпилированные обходные пути:
http://blog.integratedsolution.eu/post/2011/02/06/The-specified-type-member-Date-is-not-supported-in-LINQ-to-Entities.aspx
Ответ 10
Вот как я это делаю.
DateTime date_time_to_compare = DateTime.Now;
//Compare only date parts
context.YourObject.FirstOrDefault(r =>
EntityFunctions.TruncateTime(r.date) == EntityFunctions.TruncateTime(date_to_compare));
Ответ 11
//Примечание для пользователей Linq/Coders
Это должно дать вам точное сравнение для проверки того, попадает ли дата в пределах диапазона при работе с входом от сборщика данных, например:
((DateTime)ri.RequestX.DateSatisfied).Date >= startdate.Date &&
((DateTime)ri.RequestX.DateSatisfied).Date <= enddate.Date
где startdate и enddate являются значениями из элемента выбора даты.
Ответ 12
для этого можно использовать метод DbFunctions.TruncateTime().
e => DbFunctions.TruncateTime(e.FirstDate.Value) == DbFunctions.TruncateTime(SecondDate);
Ответ 13
Вы можете использовать ссылку ниже для сравнения 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
Ответ 14
Попробуйте это... Он отлично работает, чтобы сравнить свойства Date между двумя типами DateTimes:
PS. Это временное решение и очень плохая практика, никогда не следует использовать, когда вы знаете, что база данных может принести тысячи записей...
query = query.ToList()
.Where(x => x.FirstDate.Date == SecondDate.Date)
.AsQueryable();
Ответ 15
Без времени, чем попытка:
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;