如何构建访问DateTime.Date属性的Linq Expression动态表达式
如何创建用于访问DateTime.Date的Linq Expression?
你写的构建代码有两个核心错误:一是没有在访问CreatedAtUtc后继续链式访问Date属性,二是错误地直接对属性表达式调用Quote——Quote节点是查询提供器处理Lambda表达式时自动生成的,不需要手动包裹单层属性访问节点。
原问题复现代码
目标要实现的等价查询写法如下:
var query = CollectionQuery.OrderBy(c => c.CreatedAtUtc.Date); // CollectionQuery为User类型的可查询集合 var expressions = query.Expression;
调试上述原生写法的表达式树时,可以看到Quote类型的节点:
你之前的手动构建代码缺少.Date属性访问环节:
ParameterExpression arg = Expression.Parameter(typeof(User), "c"); var memberExpression = Expression.Property(arg, "CreatedAtUtc"); var quoteExpression = Expression.Quote(memberExpression); // 此处逻辑错误
正确构建代码
按属性访问的链式顺序逐层构造即可,最后组装成Lambda传入OrderBy,Quote节点会在查询解析时自动生成,无需手动构造:
ParameterExpression arg = Expression.Parameter(typeof(User), "c"); // 先访问c.CreatedAtUtc属性 MemberExpression createdAtAccess = Expression.Property(arg, nameof(User.CreatedAtUtc)); // 再访问CreatedAtUtc的Date属性 MemberExpression dateAccess = Expression.Property(createdAtAccess, nameof(DateTime.Date)); // 组装成Lambda表达式:c => c.CreatedAtUtc.Date Expression<Func<User, DateTime>> orderKeySelector = Expression.Lambda<Func<User, DateTime>>(dateAccess, arg); // 直接传入OrderBy即可正常使用 var query = CollectionQuery.OrderBy(orderKeySelector);
补充说明:EF Core 2.2 原生支持
DateTime.Date的SQL翻译,只要表达式结构正确,不会触发客户端求值,会自动生成对应数据库的日期截取SQL(比如SQL Server的CONVERT(date, xxx)、PostgreSQL的DATE_TRUNC('day', xxx))。如果是自定义查询提供器场景确实需要手动生成
Quote节点,直接对组装完成的Lambda表达式调用Expression.Quote(orderKeySelector)即可,不要对中间的属性访问节点单独调用Quote。
内容的提问来源于stack exchange,提问作者Weanich Sanchol
相关产品推荐
相关产品推荐

