c# - 在运行时动态选择 LINQ SELECT 字段
问题描述
我对具有多个链接表的数据库进行了 LINQ 查询,并且需要根据输入返回(SELECT)不同的字段。
ClassA has ParamA, ParamB, and ICollection<ClassB>ClassBs
ClassB has ParamD, ParamE
Linq 查询的一部分:
.Select(c => new ClassA()
{
ParamA = c.ParamA,
ParamB = c.ParamB,
ClassBs = c.ClassBs.Select(p => new ClassB()
{
ParamD = p.ParamD,
ParamE = p.ParamE
}).ToList()
}).ToList();
在某些电话中,我只需要 ParamA 和 ParamE。在其他调用中,可能是 ParamB 和 ParamE。我已经能够使用表达式完成这项工作,但不能用于 ICollection。我尝试使用 Dynamic.Linq.Core,但在 SELECT 中找不到任何新的示例。我宁愿用 MemberExpressions 来做这件事......
[更新] 更多上下文:ClassA 和 ClassB 本质上是指向 SQL 表的 EF 模型。ClassA 与 ClassB 具有一对多的关系,因此,我以这种方式查询它们。ClassA 将是学生记录(姓名、地址、家庭等),ClassB 将是测试记录,其中学生可能有多个测试,每个测试都有参加日期、等级、highest_score_of_class、lowest_score_of_class 等等。
我并不总是想要两个表的所有字段,因为可能有 100 万条记录,因此,为什么我更喜欢 SELECT 只需要特定查询和操作请求的内容。
解决方案
这可能有点冗长,但表达式可以做到这一点,例如:
var typeClassA = typeof(ClassA);
var typeClassB = typeof(ClassB);
var parameterExpressionP = Expression.Parameter(typeClassB, "p");
var newExpression = Expression.New(typeClassB);
var paramDPropertyExpression = Expression.Property(parameterExpressionP, "ParamD");
var paramDMemberBinding = Expression.Bind(typeClassB.GetProperty("ParamD"), paramDPropertyExpression);
var paramEPropertyExpression = Expression.Property(parameterExpressionP, "ParamE");
var paramEMemberBinding = Expression.Bind(typeClassB.GetProperty("ParamE"), paramEPropertyExpression);
var memberInitExpression = Expression.MemberInit(
newExpression,
paramDMemberBinding, paramEMemberBinding);
var projectionExpression = Expression.Lambda<Func<ClassB, ClassB>>(memberInitExpression, parameterExpressionP);
var parameterExpressionC = Expression.Parameter(typeClassA, "c");
var selectParamExpression = Expression.Property(parameterExpressionC, "ClassBs");
var selectExpression = Expression.Call(
typeof(Enumerable),
nameof(Enumerable.Select),
new[] { typeClassB, typeClassB },
selectParamExpression, projectionExpression);
var toListExpression = Expression.Call(
typeof(Enumerable),
nameof(Enumerable.ToList),
new[] { typeClassB },
selectExpression);
这将创建一个类似的表达式:
c.ClassBs.Select(p => new ClassB() {ParamD = p.ParamD, ParamE = p.ParamE}).ToList()
推荐阅读
- python - 集成导致 TypeError:“numpy.float64”对象不能解释为整数
- java - 使用 Windows 命令提示符创建 XLDeploy dar 文件
- javascript - Google Apps 脚本通过电子表格发送电子邮件不起作用
- php - 如何每个 ip/session 只更新一次列?
- javascript - 将多个 && 条件合并为 1
- java - 处理 - 椭圆/矩形碰撞的方法
- reactjs - 在 Netlify 上托管时,React-media 查询不适用于页面加载的大屏幕
- chart.js - chartjs中yaxis中的刻度对齐
- mysql - COUNT 未返回预期值
- cucumber - 黄瓜进口