如何只比较EF中DateTime的日期组件?

pen*_*ate 115 c# linq linq-to-entities entity-framework datetime-comparison

我有两个日期值,一个已存储在数据库中,另一个由用户使用DatePicker选择.用例是从数据库中搜索特定日期.

先前在数据库中输入的值始终具有12:00:00的时间分量,其中从选择器输入的日期具有不同的时间分量.

我只对日期组件感兴趣,并且想要忽略时间组件.

在C#中进行这种比较的方法有哪些?

另外,如何在LINQ中执行此操作?

更新:在LINQ to Entities上,以下工作正常.

e => DateTime.Compare(e.FirstDate.Value, SecondDate) >= 0
Run Code Online (Sandbox Code Playgroud)

Man*_*jua 131

使用该类EntityFunctions修剪时间部分.

using System.Data.Objects;    

var bla = (from log in context.Contacts
           where EntityFunctions.TruncateTime(log.ModifiedDate) ==  EntityFunctions.TruncateTime(today.Date)
           select log).FirstOrDefault();
Run Code Online (Sandbox Code Playgroud)

来源:http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/84d4e18b-7545-419b-9826-53ff1a0e2a62/

UPDATE

由于EF 6.0及更高版本EntityFunctions被替换DbFunctions.

  • 只有一个注释`EntityFunctions`已被弃用,以支持(至少)EF6的`System.Data.Entity.DbFunctions`.它可能早于此. (36认同)
  • 我不会很快跳到这个解决方案,因为它真的很慢,更多信息:http://stackoverflow.com/questions/22776843/table-join-performance-issue-with-entity-framework (4认同)

Fre*_*örk 121

注意:在撰写此答案时,EF关系不清楚(在编写完成后编辑成问题).要获得EF的正确方法,请检查Mandeeps的答案.


您可以使用该DateTime.Date属性执行仅日期比较.

DateTime a = GetFirstDate();
DateTime b = GetSecondDate();

if (a.Date.Equals(b.Date))
{
    // the dates are equal
}
Run Code Online (Sandbox Code Playgroud)

  • 比较日期很容易,但问题与无法将.Date属性转换为SQL的LINQ to Entities有关. (34认同)
  • @Marchy是的,`EntityFunctions.TruncateTime`肯定似乎是现在的方式(它在.NET 4中可用,它是在问到这个问题后的一年发布的). (6认同)
  • 这不会查询数据库,而是在事后处理CLR /应用程序层中的数据.真正的解决方案是使用下面答案中指定的EntityFunctions.TruncateTime(..)函数,因为它将查询发送到数据库并允许在存储层完成处理.如果没有这个,你就不能在Where/Count子句中使用日期比较逻辑,然后进一步查询过滤后的数据,因为你必须首先将部分结果拉入应用程序层,这可能是情景中的交易破坏者处理大量数据. (5认同)

小智 24

我想这可以帮到你.

我做了一个扩展,因为我必须比较填充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);
    }
Run Code Online (Sandbox Code Playgroud)

然后你可以这样使用它.

 var today = DateTime.Now;
 var todayPosts = from t in turnos.Where(IsSameDate<Turno>(t => t.MyDate, today))
                                      select t);
Run Code Online (Sandbox Code Playgroud)


alg*_*eat 10

如果您使用DateDB Entities 的属性,您将获得异常:

"The specified type member 'Date' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported."
Run Code Online (Sandbox Code Playgroud)

你可以使用这样的东西:

  DateTime date = DateTime.Now.Date;

  var result = from client in context.clients
               where client.BirthDate >= date
                     && client.BirthDate < date.AddDays(1)
               select client;
Run Code Online (Sandbox Code Playgroud)


Cra*_*ntz 8

要在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
Run Code Online (Sandbox Code Playgroud)

丑陋,但它的工作原理,它在数据库服务器上完成.


Joh*_*ter 8

这是一种不同的方法,但只有在SecondDate是您传入的变量时它才有用:

DateTime startDate = SecondDate.Date;
DateTime endDate = startDate.AddDays(1).AddTicks(-1);
...
e => e.FirstDate.Value >= startDate && e.FirstDate.Value <= endDate
Run Code Online (Sandbox Code Playgroud)

我认为这应该有效


use*_*854 6

你也可以用这个:

DbFunctions.DiffDays(date1, date2) == 0


小智 5

您可以为此使用 DbFunctions.TruncateTime() 方法。

e => DbFunctions.TruncateTime(e.FirstDate.Value) == DbFunctions.TruncateTime(SecondDate);
Run Code Online (Sandbox Code Playgroud)