gpt4 book ai didi

c# - 动态构建包含 Where 过滤器

转载 作者:太空狗 更新时间:2023-10-29 23:37:10 24 4
gpt4 key购买 nike

背景

我需要能够构建一个 .Include,将结果过滤到在特定日期或之前创建的记录。我不知道原始 LINQ 语句中对象的类型,但我会找到它们(通过大量的循环,但这是可行的)。

我有一个这样的对象图:

          A -> Ac
/ \
Bc <- B \
/ \
Cc <- C D -> Dc

对象 AcBcCcDc 都是动态找到的(即开发人员在编写原始 linq 语句时不会键入这些关系)。然后需要将这些添加到 IQueryable 表达式中,并且只返回特定 DateTime 之前的值。

到目前为止的代码

我尝试构建一个构造 lambda 并比较日期的函数。到目前为止,如果原始查询是 A.Include(x => x.B).Include(x => x.B.Select(y => y.C),我可以构造字符串 "A.B.Bc ",所以我知道 A、B 和 Bc 的类型,以及它们之间的关联方式。

private static IQueryable<T> FilterChangeTrackerToDate<T>(this IQueryable<T> query, string includeString, DateTime targetDateTime)
{
var param = Expression.Parameter( typeof( T ), "x" );

var prop = Expression.Property(param, includeString + ".CreatedUtc");

var dateConst = Expression.Constant(targetDateTime);

var compare = Expression.LessThanOrEqual(prop, dateConst);

var lambda = Expression.Lambda<Func<T, bool>>(compare, param);

return query.Where(lambda);
}

问题是上面的代码崩溃了,因为 "A.B.Bc.CreatedUtc" 不是加载日期属性的正确方法 - 我需要遍历 .Select语句。

问题

为了同时加载记录和过滤它们,我需要动态构建一个.Select来提取我需要的值(值得庆幸的是,它是基于继承的静态值)并将这些值放入匿名类型中,然后可以使用 .Where() 对其进行过滤。所有这些都需要用最少的泛型来完成,因为我没有编译时类型来验证,我不得不滥用反射来让它们工作。

本质上,我需要创建这个:

.Select( x => new
{
Bc = x.B.Select(z => z.Bc.Select(y => y.CreatedUtc).Where( q => q > DateTime.UtcNow ) ),
A= x
} )

动态地,使用字符串“A.B.Bc”,用于任何级别的嵌套。

资源

这是我看到如何过滤 EF 包含方法的地方: LINQ To Entities Include + Where Method

这篇文章讨论了动态创建一个 Select,但它只是选择顶级值,而且似乎无法构建我的问题所需的其余部分:How to create LINQ Expression Tree to select an anonymous type

动态链接

使用 System.Linq.Dynamic 库,我尝试访问 Bc 的 CreatedUtc 值:

query = (IQueryable<T>) query.Select(includeString + ".CreatedUtc");

Where includeString = "B.Bc",但这给了我一个异常(exception):

Exception thrown: 'System.Linq.Dynamic.ParseException' in System.Linq.Dynamic.dll

Additional information: No property or field 'Bc' exists in type 'List`1'

最佳答案

我相信System.Linq.Dynamic是你需要的。它是一个最初由 Microsoft 的 ScottGu 编写的库,它允许您从这样的字符串构建 LINQ 查询:

IQueryable nestedQuery = query.Select("B.Bc.CreatedUtc");

查询是IQueryable<A> .

这个库有很多分支。你可以从here开始.关于查询语言的文档是 here .还有 here有一个版本具有一些附加功能和 here是 dotnet.core 版本。

UPD1: This库缺少 SelectMany 扩展方法,但 this一个有。因此,对于后一个库,您可以执行以下操作:

query.SelectMany("B").SelectMany("Bc").Select("CreatedUtc");

关于c# - 动态构建包含 Where 过滤器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38211631/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com