基于条件动态构建IQueryable GroupBy的问题求助
条件化构建IQueryable GroupBy的问题
我正尝试根据条件构建IQueryable的GroupBy,但一直未能成功。代码如下:
IQueryable<MyObject> query .. var returnedVal = query.GroupBy(y => new { Val1 = !first ? y.Val1 : null, Val2 = !second ? y.Val2 : null }) .Select(x => new MyObject { Val1 = !first ? y.Key.Val1 : null, Val2 = !second ? y.Key.Val2 : null });
测试数据:
| id | Val1 | Val2 |
|---|---|---|
| 1 | Sta | test1 |
| 2 | Danny | test2 |
| 3 | Elle | test2 |
| 4 | Elle | test3 |
预期场景:
- 场景1:
first=false、second=false,按Val1和Val2分组,返回全部4行; - 场景2:
first=true、second=false,仅按Val2分组,返回3行(test1、test2、test3); - 场景3:
first=false、second=true,仅按Val1分组,返回3行(Sta、Danny、Elle); - 场景4:
first=true、second=true,不分组,无返回结果。
当前问题:每当first或second为true时,对应的Val1或Val2仍会被包含在GroupBy中,请问将字段设为null是否是彻底排除其参与分组的正确方式?
解决方案
把字段设为null不是彻底排除其参与分组的正确方式。因为你使用的匿名类型依然保留了Val1/Val2属性,哪怕赋值为null,分组逻辑还是会把这个null值作为分组条件的一部分。另外你原代码的Select里还存在变量错误——应该用x.Key而不是y.Key,因为Select的参数是分组后的IGrouping实例x。
要彻底排除某个字段不参与分组,正确的做法是让分组键的匿名类型完全不包含该字段。针对你的四个场景,直接分情况处理GroupBy逻辑最清晰:
IQueryable<MyObject> query = ...; IQueryable<MyObject> returnedVal; if (first && second) { // 场景4:不分组,返回空结果 returnedVal = Enumerable.Empty<MyObject>().AsQueryable(); } else if (first) { // 场景2:仅按Val2分组 returnedVal = query.GroupBy(item => item.Val2) .Select(group => new MyObject { Val2 = group.Key }); } else if (second) { // 场景3:仅按Val1分组 returnedVal = query.GroupBy(item => item.Val1) .Select(group => new MyObject { Val1 = group.Key }); } else { // 场景1:按Val1和Val2组合分组 returnedVal = query.GroupBy(item => new { item.Val1, item.Val2 }) .Select(group => new MyObject { Val1 = group.Key.Val1, Val2 = group.Key.Val2 }); }
这种方式下,每个场景的分组键只包含需要参与分组的字段,完全符合你的预期,代码也更易读和维护。
如果你的场景更复杂,不想写过多if-else,也可以通过表达式树动态构建分组键,但对于当前的简单场景,分情况处理是最优选择。
内容的提问来源于stack exchange,提问作者TheProgrammer
相关产品推荐
相关产品推荐

