Как сравнить только компоненты даты из 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;
попробуйте это... Он отлично работает, чтобы сравнить свойства даты между двумя типами DateTimes:
PS. Это временное решение и действительно плохая практика, никогда не следует использовать, когда вы знаете, что база данных может принести тысячи записей...
query = query.ToList()
.Where(x => x.FirstDate.Date == SecondDate.Date)
.AsQueryable();