LINQ 查询以从分组中查找最小值 - 无法创建类型为“X”的常量

Posted

技术标签:

【中文标题】LINQ 查询以从分组中查找最小值 - 无法创建类型为“X”的常量【英文标题】:LINQ Query to find minumum value from a grouping - unable to create constant of type 'X' 【发布时间】:2016-06-12 21:38:12 【问题描述】:

作为复杂查询的一部分,我需要找到一组按 ID 分组的实体框架记录的最短日期。

所以我的 EF 类可能是:

public MyClass 
    public int Id  get; set; 
    public DateTime CreatedDate  get; set; 

我的数据可能如下所示:

Id     CreatedDate
1      2012-01-01
1      2012-02-01
2      2013-01-01
2      2015-05-01

我正在尝试按Id 属性对数据进行分组,然后为每个分组选择最小的CreatedDate

我认为这应该很简单!并写道:

var firstThing = (from r in records
                 group r by r.Id into grp
                 select new  
                     Id = grp.Key, 
                     CreatedDate = grp.Min(x => x.CreatedDate) 
                 ).ToList();

但在我使用 .ToList() 实现集合时,我看到了以下异常:

抛出异常:System.Data.Entity.dll 中的“System.NotSupportedException”

附加信息:无法创建类型的常量值 '我的课'。只有原始类型或枚举类型是 在这种情况下支持。

我进行了一番挖掘,并认为我理解 EF 在比较“MyClass”时遇到了问题,因为它无法将其转换为 SQL'y。但我不确定这个查询的哪个方面导致了问题。

我看过一些类似的帖子,但不是一个真正点头的例子,我想更好地了解解决问题的原因。

【问题讨论】:

您确定这是您的错误所在吗? records 是原始表数据还是后续查询? 我无法重现该问题,因为此代码对我来说很好!你能展示你如何初始化records 吗? 就我而言,records 是一个 IQueryable,我将它作为参数传递给方法。我在方法外创建了记录 var,方法是在传入之前简单地执行 context.MyClasses context.MyClasses 的类型,它是来自 EF 上下文的 ObjectSet 【参考方案1】:

我认为您不能在 Linq-to-Entities 查询中使用像 Min 这样的函数。

我解决这个问题的方法是按CreatedDate 对每个组进行排序,然后选择第一项。我最熟悉 Fluent 语法,所以这就是它的样子,应该很容易转换为你的:

var firstThing = records
    .GroupBy(r => r.ID)
    .Select(grp => grp.OrderBy(r => r.CreatedDate).FirstOrDefault())
    .ToList()

【讨论】:

这似乎是一个明智的想法。我已将查询切换到您的建议,但不幸的是我看到了同样的错误:(var firstThing = (from r in records group r by r.Id into grp select grp.OrderBy(x => x.CreatedDate).FirstOrDefault()).ToList(); 在使用 .Min 测试了它对我有用的代码之后,所以我认为 D Stanley 是对的,您的问题出在其他地方。您能否发布更多代码来显示您如何初始化记录?我尝试设置一个类似于您描述的场景,将 IQueryable 传递给该方法,但它对我来说仍然很好。

以上是关于LINQ 查询以从分组中查找最小值 - 无法创建类型为“X”的常量的主要内容,如果未能解决你的问题,请参考以下文章

具有内部联接、多个分组依据和最小最大值的 Linq 查询

使用LINQ在数组中查找最小和最大日期?

LINQ 分组查询

如何对C#类对象值进行分组。 LINQ可以吗?

具有匿名类型和用户定义类型的 LINQ 选择查询

Linq 中的 Groupby 和 where 子句