动态访问LINQ查询中匿名类型中嵌套的属性



我正在对我的EF映射的DB实体类执行一个冗长的LINQ查询,该查询由Linq2Sql处理,最终得到一个匿名类型:

...
.Where(e => ...)
.Join(..., (outer, inner) => new {
outer.Object1,
outer.TempId,
Object2 = inner
})

到目前为止,一切都很好,一切都将很好地转换为SQL并在DB上运行。我可以对匿名类型的对象进行迭代,此时只有其中包含的数据才会在C#端具体化。

但是:我现在需要执行最后一个过滤步骤,以减少数据集,这就是为什么它也应该在DB上运行。我需要比较Object1Object2上的属性。

此属性的名称作为字符串传递到我的方法中

在正常情况下,这不会是个问题。我可以简单地通过反射访问匿名对象——即使这意味着我必须通过枚举表上的.GetType().GetGenericArguments()[0]来获得匿名类型。

但是,我需要确保这里的所有内容都是类型安全的,因此接下来的foreach将允许我迭代并使用匿名类型的实例。因此,创建过滤器表达式并不简单,因为我不能为Lambda<TDelegate>指定类型——它必须是Func<..., Boolean>,其中...是我的匿名类型!

我曾考虑创建一个项目函数,该函数接受匿名类型中Object1Object2所属类型的实例,例如ObjectData,并返回属性值。这当然是可行的:

var prm = Expression.Parameter(typeof(ObjectData), "obj");
var projectionExpr = Expression.Lambda<Func<ObjectData, int>>(Expression.Property(prm, myPropertyName), prm);

但我不确定该在哪里使用它们——我需要某种";"单项选择";,它只是通过投影表达式将一个值投影到另一个值,这将与EF的LINQ to Entities/SQL生成很好地配合——类似于(伪代码,带有假想的PROJECT函数(这个:

.Select(info => new {
info.Object1,
info.TempId,
info.Object2,
Value1 = PROJECT(info.Object1, projectionExpr),
Value2 = PROJECT(info.Object2, projectionExpr)
})

我如何将我的最终过滤器放入故事中

这看起来更像是动态linq的情况。有了这个库,应该可以在查询中添加这样的内容:

.Where(e => ...)
.Join(..., (outer, inner) => new {
outer.Object1,
outer.TempId,
Object2 = inner
})
.Where($"Object1.{myPropertyName} == Object2.{myPropertyName}");

最新更新