Как сравнить только компоненты даты из DateTime в EF?


У меня есть два значения даты, один уже хранится в базе данных, а другой выбран пользователем с помощью DatePicker. Вариант использования заключается в поиске определенной даты из базы данных.

значение, ранее введенное в базу данных, всегда имеет компонент времени 12: 00: 00, Где в качестве даты, введенной из средства выбора, имеет другой компонент времени.

меня интересуют только компоненты даты и я хотел бы игнорировать компонент времени.

что способов сделать это сравнение в C#?

кроме того, как это сделать в LINQ?

обновление: В LINQ to Entities отлично работает следующее.

e => DateTime.Compare(e.FirstDate.Value, SecondDate) >= 0
15 110

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();

Источник: http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/84d4e18b-7545-419b-9826-53ff1a0e2a62/

обновление

начиная с 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

Я думаю, что это должно работать

вы также можете использовать это:

DbFunctions.DiffDays(date1, date2) == 0

просто всегда сравниваю дата свойство DateTime, вместо полного времени даты.

при создании запроса LINQ используйте date.Дата в запросе, т. е.:

var results = from c in collection
              where c.Date == myDateTime.Date
              select c;

просто если кто-то приходит сюда гуглить или бинговать... скомпилированные обходные пути:

http://blog.integratedsolution.eu/post/2011/02/06/The-specified-type-member-Date-is-not-supported-in-LINQ-to-Entities.aspx

вот как я это делаю.

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();