【问题标题】:Issues with DateTime.AddMinutes() in Dynamic LINQ Query动态 LINQ 查询中的 DateTime.AddMinutes() 问题
【发布时间】:2013-10-11 17:44:31
【问题描述】:

我目前在使用 LINQ->Entites w/Entity Framework v 4.2 和 T4 生成的对象上下文时遇到了问题。我相对了解在对数据库执行之前如何将 LINQ 查询转换为存储表达式,但我绝不是专家。据我了解,使用的 .NET 函数在 T-SQL 中被转换为它们的等效函数,而那些没有等效函数(例如,String.Format())的函数将在运行时抛出 System.NotSupportedException

在我的动态 LINQ 查询中,我使用 DateTime.Now.AddMinutes() 过滤掉我的结果集:

public void ExecuteSearch()
{
   var timeElapsedTresholdInMinutes = Convert.ToInt32( ConfigurationManager.AppSettings.Get("TimeElapsedThresholdInMinutes") );

   var resultSet = ( from entity in _dbContext.EntityCollection
                     where /*non-date-related where clause stuff*/
                           && 
                           entity.DateAdded <= DateTime.Now.AddMinutes(-1 * timeElapsedThresholdInMinutes)
                     select entity);

   /* do something with resultSet */
}

在运行时,我收到System.NotSupportedException: LINQ to Entities does not recognize the method DateTime.Now.AddMinutes() method and this method cannot be translated into a store expression.

例如,我的 timeElapsedThreshold 在评估后的值为 -30。有谁知道为什么这不会映射到DATEADD(MINUTE,-30,GETDATE());?我这里有什么遗漏吗?

当然,我可以把我的代码变成:

public void ExecuteSearch()
{
   var maxDateTimeThreshold = DateTime.Now.AddMinutes( -1 * Convert.ToInt32(ConfigurationManager.AppSettings.Get("TimeElapsedThresholdInMinutes"));

   var resultSet = ( from entity in _dbContext.EntityCollection
                     where /*non-date-related where clause stuff*/
                           && 
                           entity.DateAdded <= maxDateTimeThreshold
                     select entity);
}

并克服了我的代码破坏问题,但我真的很想了解为什么 LINQ->Entities 将 DateTime.Now.AddMinutes() 视为没有 T-SQL 等效项的 .NET 方法。非常感谢任何帮助/反馈!

【问题讨论】:

    标签: c# sql linq datetime entity-framework-4


    【解决方案1】:

    LINQ 表达式转换为底层数据源语言,在您的情况下为 SQL,而在 LINQ to Entities 中,DateTime.AddMinutes 没有任何实现可以将查询转换为 SQL 中的相应等效项。这就是提供 .Net 框架的原因。

    System.Data.Objects.EntityFunctions.AddMinutes
    

    你应该看到:Date and Time Canonical Functions

    您的查询可以是:

       var resultSet = ( from entity in _dbContext.EntityCollection
                         where /*non-date-related where clause stuff*/
                               && 
                               entity.DateAdded <= 
                              System.Data.Objects.EntityFunctions.AddMinutes(
                                     DateTime.Now, -1 * timeElapsedThresholdInMinutes)
                         select entity);
    

    但在您的情况下,如果您可以事先计算值,就像在您的第二个代码示例中一样,因为这样可以避免每条记录的转换。

    【讨论】:

    • 这已移至System.Data.Entity.DbFunctions[Obsolete("This class has been replaced by System.Data.Entity.DbFunctions.")]
    【解决方案2】:

    EntityFunctions 已过时 (EF 6.x)。

    请使用DbFunctions 类进行日期时间操作。

    例如从 cmd in context.Commands where cmd.ExecutedOn > DbFunctions.AddMilliseconds(baseDate, millisecondsToAdd) 选择 cmd

    【讨论】:

      【解决方案3】:

      我已经使用DbFunction 很长时间了,直到今天我才意识到……我什至需要为DbFunction 操心。

      这就是我想到的:

      var dateLimit = DateTime.Now.AddMinutes(-20);
      var result = db.TableName.Where(x => x.MyDateTime > dateLimit);
      

      我刚刚从 linq 表达式中取出了 'AddMinutes' 操作。

      【讨论】:

        【解决方案4】:

        我真的很想了解为什么 LINQ->Entities 将 DateTime.Now.AddMinutes() 视为没有 T-SQL 等效项的 .NET 方法

        因为从 .NET 到 T-SQL 的每个映射都必须手动实现,而他们只是没有实现这个...

        【讨论】:

        • 很公平。看起来这个映射太明显了,不容错过,但话说回来,我不是微软。
        猜你喜欢
        • 1970-01-01
        • 2011-04-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-08-21
        • 1970-01-01
        • 2021-10-27
        相关资源
        最近更新 更多