Как сравнить только компоненты даты с 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;

Ответ 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;