【问题标题】:Create DateTime within LINQ query在 LINQ 查询中创建 DateTime
【发布时间】:2017-12-23 00:43:58
【问题描述】:

我收到以下错误:

LINQ 仅支持无参数构造函数和初始化程序 到实体。

我正在尝试从结果集中查询数据,新结果集中的一部分返回了新的日期字段。

var result = debts.Select(x => new 
             { 
                 x.Snowball.User.Email, 
                 x.SnowballID, 
                 x.Description, 
                 x.ID, 
                 x.DueDayOfMonth, 
                 Due = new DateTime(ExecutionDate.Year, 
                                    ExecutionDate.Month, 
                                    x.DueDayOfMonth) 
             }).ToList();

有没有办法可以创建这个推断的日期时间?

【问题讨论】:

  • 在查询之外构造日期。在其中引用该变量。
  • 不确定如何做到这一点。日期时间由结果集中的字段创建。
  • DateTime.Parse(...)
  • 将 DateTime.Parse 放入 linq 语句中,替换 Due = new DateTime... 吗?

标签: c# linq datetime


【解决方案1】:

我来这里是为了寻找同样的东西,但在进一步的研究中发现了另一种在 System.Data.Entity 中使用 DbFunctions.CreateDateTime 的方法。使用此方法,您的查询将如下所示:

var result = debts.Select(x => new 
             { 
                 x.Snowball.User.Email, 
                 x.SnowballID, 
                 x.Description, 
                 x.ID, 
                 x.DueDayOfMonth, 
                 Due = DbFunctions.CreateDateTime(ExecutionDate.Year, 
                                    ExecutionDate.Month, 
                                    x.DueDayOfMonth, 0,0,0) 
             }).ToList();

编辑:这适用于 EF6 及更高版本,早期版本的 EF 使用 System.Data.Entity.Core.Objects.EntityFunctions 而不是 DbFunctions

【讨论】:

    【解决方案2】:

    LINQ to Entities 有一个查询边界。

    如果您愿意,IQueryable 结果允许逐步添加一个或多个过滤器和选择等。

    当查询被添加到数据库中时,还没有任何内容;只有当您访问结果集时,查询才会由 LINQ 提供程序(例如单个 Transact SQL 查询)构造,然后在数据库上运行,并返回其结果。

    在您展示的情况下,您正尝试在数据库的结果集中创建一个新对象(Date - 但也可能是您自己的类之一)。

    因此,对于从数据库查询返回的每一行,您都在尝试从每行不同的对象(来自您的代码库)创建一列(需要将参数传递给构造函数)。 因为底层提供者不能保证能够从外部源动态创建任意对象,所以这是不允许的(被 LINQ 提供者阻止)。

    将对数据库运行的查询是“debts”。这将返回未过滤的查询中的所有行(因为没有WHERE 子句)。

    下一个查询将在您的代码中运行。在您的代码中,您可以使用参数化构造函数 - 现在是 LINQ To Objects。

    所以区分查询的各个阶段并做你想做的事情的方法是将ToList()放在针对数据库运行的查询的末尾,以便生成查询,运行,并返回结果。 然后对这些结果构建并运行下一个查询(在您的代码中)。

    var result = debts.ToList().Select(x => new 
    { 
        x.Snowball.User.Email, 
        x.SnowballID, 
        x.Description, 
        x.ID, 
        x.DueDayOfMonth, 
        Due = new DateTime(ExecutionDate.Year, ExecutionDate.Month, x.DueDayOfMonth) 
    });
    

    【讨论】:

    • 解释得非常好。谢谢,如果可以的话,我会加分。
    【解决方案3】:

    您可以使用无参数构造函数创建自己的 Date 类,并使用属性初始化器语法进行设置,例如

    Due = new Date(){Year = ExecutionDate.Year, Month = ExecutionDate.Month, Day = x.DueDayOfMonth}
    

    然后只需定义从 Date 到 DateTime 的转换。

    【讨论】:

      【解决方案4】:

      你可以试试这个:

      var result = debts.Select(x =>
          new 
          { 
          x.Snowball.User.Email, x.SnowballID, x.Description, x.ID, 
          x.DueDayOfMonth, 
          exY = ExecutionDate.Year, 
          exM = ExecutionDate.Month, 
          exD = x.DueDayOfMonth) 
          }).ToList()
          .Select(a => new {Email, SnowballID, Description, ID, Due=new DateTime(exY, exM, exD)})
          .ToList()
      

      【讨论】:

      • 你试过这个代码吗?我希望它与原始代码有相同的问题。您正在尝试在 LINQ 查询中使用带有参数的构造函数.....
      • 不,我没有尝试。但是,问题似乎出在 Linq for Entities(即实体框架)中。第一个 ToList() 应该执行查询,第二个使用 Linq 到对象,这应该可以工作。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-04-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-01
      • 2011-02-18
      相关资源
      最近更新 更多