Linq-to-Entity查询的动态谓词
以下Linq-to-Entities查询工作正常:
var query = repository.Where(r => r.YearProp1.HasValue && r.YearProp1 >= minYear && r.YearProp1 <= maxYear);
我的数据库有十几个列,它们都报告与年份相关的信息( short?
数据类型)。 我想为所有这些列重用相同的Linq-to-Entities逻辑。 就像是:
Func fx = GetYearPropertyFunction(); var query = repository.Where(r => fx(r).HasValue && fx(r) >= minYear && fx(r) <= maxYear);
这会导致错误:
LINQ to Entities无法识别方法’System.Nullable`1 [System.Int16] fx(RepoEntity)’方法,并且此方法无法转换为商店表达式。
我理解为什么我收到错误,但我想知道是否有一个解决方法,不涉及重复代码十几次只是为了更改SQL查询运行的属性。
我会在多个查询中重用该函数,所以我想我的问题的一般版本是: 有没有办法将简单的property-getter lambda函数转换为Linq-to-Entities可以使用的Expression?
建立RaphaëlAlthaus的答案,但添加了您最初寻找的通用选择器:
public static class Examples { public static Expression> SelectPropertyOne() { return x => x.PropertyOne; } public static Expression> SelectPropertyTwo() { return x => x.PropertyTwo; } public static Expression> BetweenNullable(Expression>> selector, Nullable minRange, Nullable maxRange) where TNull : struct { var param = Expression.Parameter(typeof(TEntity), "entity"); var member = Expression.Invoke(selector, param); Expression hasValue = Expression.Property(member, "HasValue"); Expression greaterThanMinRange = Expression.GreaterThanOrEqual(member, Expression.Convert(Expression.Constant(minRange), typeof(Nullable ))); Expression lessThanMaxRange = Expression.LessThanOrEqual(member, Expression.Convert(Expression.Constant(maxRange), typeof(Nullable ))); Expression body = Expression.AndAlso(hasValue, Expression.AndAlso(greaterThanMinRange, lessThanMaxRange)); return Expression.Lambda>(body, param); } }
可以像你正在寻找的原始查询一样使用:
Expression> whatToSelect = Examples.SelectPropertyOne; var query = Context .MyEntities .Where(Examples.BetweenNullable(whatToSelect, 0, 30));
谓词本身就是一个filter,应该评估为bool(是否将其包含在结果中)。 你可以修改你的方法看起来像这样,它应该工作:
public static Expression> FitsWithinRange(int minYear, int maxYear) { return w => w.HasValue && w >= minYear && w <= maxYear; }
编辑:哦,并使用它:
var query = repository.Where(Repository.FitsWithinRange(minYear, maxYear));
你可以做那样的事情(不确定它是否会在linq2实体中“按原样”工作,但是如果你有问题…只需告诉)
用法
var query = entity>.NullableShortBetween(1, 3).ToList();
function
public static IQueryable NullableShortBetween (this IQueryable queryable, short? minValue, short? maxValue) where T: class { //item (= left part of the lambda) var parameterExpression = Expression.Parameter(typeof (T), "item"); //retrieve all nullable short properties of your entity, to change if you have other criterias to get these "year" properties var shortProperties = typeof (T).GetProperties().Where(m => m.CanRead && m.CanWrite && m.PropertyType == typeof(short?)); foreach (var shortProperty in shortProperties) { //item (right part of the lambda) Expression memberExpression = parameterExpression; //item. memberExpression = Expression.Property(memberExpression, shortProperty); //item. .HasValue Expression firstPart = Expression.Property(memberExpression, "HasValue"); //item. >= minValue Expression secondPart = Expression.GreaterThanOrEqual(memberExpression, Expression.Convert(Expression.Constant(minValue), typeof (short?))); //item. <= maxValue var thirdPart = Expression.LessThanOrEqual(memberExpression, Expression.Convert(Expression.Constant(maxValue), typeof (short?))); //item. .HasValue && item. >= minValue var result = Expression.And(firstPart, secondPart); //item. .HasValue && item. >= minValue && item. <= maxValue result = Expression.AndAlso(result, thirdPart); //pass the predicate to the queryable queryable = queryable.Where(Expression.Lambda>(result, new[] {parameterExpression})); } return queryable; }
编辑 :另一种解决方案,基于“简单”reflection,“看起来”就像你想要的那样
public static short? GetYearValue(this T instance) { var propertyInfo = typeof(T).GetProperties().FirstOrDefault(m => m.CanRead && m.CanWrite && m.PropertyType == typeof(short?)); return propertyInfo.GetValue(instance, null) as short?; }
用法
上述就是C#学习教程:Linq-to-Entity查询的动态谓词分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注---计算机技术网(www.ctvol.com)!
var result = list.Where(item => item.GetYearValue() != null && item.GetYearValue() >= 1 && item.GetYearValue() <= 3).ToList();
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/1003869.html