Linq-to-Entity查询的动态谓词

Dav*_*eer 11 c# linq linq-to-entities asp.net-mvc-3

以下Linq-to-Entities查询工作正常:

var query = repository.Where(r => r.YearProp1.HasValue &&
                                  r.YearProp1 >= minYear &&
                                  r.YearProp1 <= maxYear);
Run Code Online (Sandbox Code Playgroud)

我的数据库有十几个列,它们都报告与年份相关的信息(short?数据类型).我想为所有这些列重用相同的Linq-to-Entities逻辑.就像是:

Func<RepoEntity, short?> fx = GetYearPropertyFunction();
var query = repository.Where(r => fx(r).HasValue &&
                                  fx(r) >= minYear &&
                                  fx(r) <= maxYear);
Run Code Online (Sandbox Code Playgroud)

这会导致错误:

LINQ to Entities无法识别方法'System.Nullable`1 [System.Int16] fx(RepoEntity)'方法,并且此方法无法转换为商店表达式.

我理解为什么我收到错误,但我想知道是否有一个解决方法,不涉及重复代码十几次只是为了更改SQL查询运行的属性.

我会在多个查询中重用该函数,所以我想我的问题的一般版本是:有没有办法将简单的property-getter lambda函数转换为Linq-to-Entities可以使用的Expression?

Oce*_*t20 2

以 Rapha\xc3\xabl Althaus\' 答案为基础,但添加您最初寻找的通用选择器:

\n\n
public static class Examples\n{\n    public static Expression<Func<MyEntity, short?>> SelectPropertyOne()\n    {\n        return x => x.PropertyOne;\n    }\n\n    public static Expression<Func<MyEntity, short?>> SelectPropertyTwo()\n    {\n        return x => x.PropertyTwo;\n    }\n\n    public static Expression<Func<TEntity, bool>> BetweenNullable<TEntity, TNull>(Expression<Func<TEntity, Nullable<TNull>>> selector, Nullable<TNull> minRange, Nullable<TNull> maxRange) where TNull : struct\n    {\n        var param = Expression.Parameter(typeof(TEntity), "entity");\n        var member = Expression.Invoke(selector, param);\n\n        Expression hasValue = Expression.Property(member, "HasValue");\n        Expression greaterThanMinRange = Expression.GreaterThanOrEqual(member,\n                                             Expression.Convert(Expression.Constant(minRange), typeof(Nullable<TNull>)));\n        Expression lessThanMaxRange = Expression.LessThanOrEqual(member,\n                                          Expression.Convert(Expression.Constant(maxRange), typeof(Nullable<TNull>)));\n\n        Expression body = Expression.AndAlso(hasValue,\n                      Expression.AndAlso(greaterThanMinRange, lessThanMaxRange));\n\n        return Expression.Lambda<Func<TEntity, bool>>(body, param);\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

可以像您正在寻找的原始查询一样使用:

\n\n
Expression<Func<MyEntity, short?>> whatToSelect = Examples.SelectPropertyOne;\n\nvar query = Context\n            .MyEntities\n            .Where(Examples.BetweenNullable<MyEntity, short>(whatToSelect, 0, 30));\n
Run Code Online (Sandbox Code Playgroud)\n