c# - 通过 lambdada 表达式在组中选择当前记录
问题描述
我有这个表
,我想按lifeplusecaseId
字段分组并返回所有字段分组
我试过这个
var query = db.ApplicantCenterDistance.GroupBy(a => a.LifeplusCaseId)
.Select(s => new {
Id = s.Key,
MinDistance = s.Min(m => m.Distance),
Duration = s.Min(m => m.Duration),
items=s.ToList(),
}).Where(x=>x.MinDistance!=" ").ToList();
但我遇到了一个问题:
"System.InvalidOperationException: 'The LINQ expression '(GroupByShaperExpression:
KeySelector: (a.LifeplusCaseId),
ElementSelector:(EntityShaperExpression: "
我不知道如何返回所有记录。
错误是:
System.InvalidOperationException:'LINQ 表达式'(GroupByShaperExpression:KeySelector:(a.LifeplusCaseId),ElementSelector:(EntityShaperExpression:EntityType:ApplicantCenterDistance ValueBufferExpression:(ProjectionBindingExpression:EmptyProjectionMember)IsNullable:False)).ToList()'无法翻译。以可翻译的形式重写查询,或通过插入对 AsEnumerable()、AsAsyncEnumerable()、ToList() 或 ToListAsync() 的调用显式切换到客户端评估。有关详细信息,请参阅https://go.microsoft.com/fwlink/?linkid=2101038。
解决方案
此类错误在旧版本的 EF 中很常见,我在 EF 6.4.4 中测试了此语法并没有发现任何问题,但是您的类型结构可能存在其他问题,这些问题可能会影响Linq to SQL表达式评估。
您的错误消息与 EF 6.4.4 命名法不匹配,这表明这里还有其他东西在起作用,但是此错误与 EF Core 3.1+ 匹配。
首先,由于错误是专门围绕您使用 的.ToList()
,所以将其从表达式中删除,EF6 将支持通过返回分组表达式和投影AsEnumerable<>
。以下任一项都适用于 EF6:
.Select(s => new {
Id = s.Key,
MinDistance = s.Min(m => m.Distance),
Duration = s.Min(m => m.Duration),
items = s
})
或通过投影.AsEnumerable<ApplicantCenterDistance>()
.Select(s => new {
Id = s.Key,
MinDistance = s.Min(m => m.Distance),
Duration = s.Min(m => m.Duration),
items = s.AsEnumerable<ApplicantCenterDistance>()
})
如果您仍然遇到问题,您还可以将过滤条件移动到投影之前,这允许在.ToList()
客户端评估投影(以及之前的),这就是异常消息和相关的MS Docs 文章所暗示的内容:
var query = db.ApplicantCenterDistance
.GroupBy(a => a.LifeplusCaseId)
.Where(x => x.Where(x => x.Min(m => m.Distance) != " ")
.Select(s => new {
Id = s.Key,
MinDistance = s.Min(m => m.Distance),
Duration = s.Min(m => m.Duration),
items=s.ToList(),
}).ToList();
更新:EF 核心
如果您在 EF Core 3.1+ 中执行此操作,则一种选择是将整个记录集拉到客户端的内存中,然后将其分组。如果无论如何结果的数量总是非常大,那么这不会产生太大影响,因为您已经将所有项目保留在每个组中:
var dataList = db.ApplicantCenterDistance.ToList();
var data = dataList
.GroupBy(a => a.LifeplusCaseId)
.Select(s => new {
Id = s.Key,
MinDistance = s.Min(m => m.Distance),
Duration = s.Min(m => m.Duration),
items=s.ToList(),
}).Where(x=>x.MinDistance!=" ").ToList();
更新:字符串字段的最小值
作为Distance
一个字符串,MIN
如果您实际上想要最小值,则可能无法评估正确的数字比较,为此您需要将其转换为数字类型。
注意:您可以在上述任何查询中使用此语法,但是如果您希望在数据库中执行评估,则需要转换为 a
double
,在最后一个客户端示例中,您可以使用您希望转换的任何 C# 代码价值。
MinDistance = s.Where(m => m != " ").Min(m => (double)m.Distance),
在这里,我们首先过滤掉不能转换为数字的值,您可能需要根据您的数据集是否包含空值或零长度字符串来调整它。有关更多详细信息,请参阅此帖子。
推荐阅读
- rust - Serde 能否根据字段的值将 JSON 反序列化为一组类型中的一种?
- swift - CollectionView 单元格困惑
- asp.net-mvc - Azure + ASP.Net + System.UnauthorizedAccessException:对路径“/Content/img/CourseImages”的访问被拒绝
- c++ - 将父类对象转换为子对象的问题
- c# - 将模板 C++ 转换为 C#
- python - 类标签不如预期时的模型性能计算
- javascript - ion-item-slider 按钮未正确显示
- prestashop - 警告:在第 103 行的 */prestashop/src/PrestaShopBundle/Translation/Loader/SqlTranslationLoader.php 中为 foreach() 提供的参数无效
- python - 错误:'应用函数时解包的值太多(预期为 2)
- numpy - 多标签分类:解码一个热向量