我一直在使用LinqKit来创建通用查询很长一段时间。在Linqkit中使用PredicateBuilder进行通用查询
总是困扰着我的一件事是,你总是必须测试过滤器中发送的值是否有效。
例如:假设我有一个字符串过滤器。条件可以是平等的,开始的,结束的,包含的。
我的方法会是这个样子:
public List<MyModel> Get(MyModelFilter filter)
{
if (string.IsNullOrEmpty(filter.prop))
{
predicate = predicate.And(_myModel => myModel.Prop.Contains(filter.prop));
}
// Plus a giant amount of if's with multiple filters
return DbSet.AsExpandable()
.Where(predicate)
.ToList();
}
要结束这一堆如果的,我决定创建的过滤器适用于性能的通用方法。 我的想法是通过在过滤器将被应用的属性和过滤器定义,并封装表达创建逻辑
这将是类型的东西:
public List<MyModel> Get(MyModelFilter filter)
{
predicate = predicate.And(_myModel => myModel.Prop, filter.PropFilterDefinition);
// Goodnye If's, Only others filter impl
return DbSet.AsExpandable()
.Where(predicate)
.ToList();
}
对于这一点,我我创建了一些扩展方法来处理这个问题
public static Expression<Func<TPredicate, bool>> And<TPredicate>(
this ExpressionStarter<TPredicate> predicate,
Func<TPredicate, string> property, StringFilterDefinition filter,
bool ignoreNull = true)
{
if (InvalidStringFilter(filter, ignoreNull))
{
return predicate;
}
// This is LinqKit's And Extension Method
return predicate.And(BuildPredicate(property, filter));
}
private static Expression<Func<TPredicate, bool>> BuildPredicate<TPredicate>(
Func<TPredicate, string> property,
StringFilterDefinition filter)
{
if (filter.Filter == StringFilterComparators.Equal)
{
return x => property.Invoke(x) == filter.Value;
}
if (filter.Filter == StringFilterComparators.BeginsWith)
{
return x => property.Invoke(x).StartsWith(filter.Value);
}
if (filter.Filter == StringFilterComparators.EndsWith)
{
return x => property.Invoke(x).EndsWith(filter.Value);
}
return x => property.Invoke(x).Contains(filter.Value);
}
private static bool InvalidStringFilter(
StringFilterDefinition filter,
bool ignoreNullValue = true)
{
if (filter?.Filter == null)
{
return true;
}
return ignoreNullValue && string.IsNullOrEmpty(filter.Value);
}
问题是过滤器没有被应用,并且答案是在那里调用。 EF无法将上述表达式转换为SQL。 的EF误差是
Microsoft.EntityFrameworkCore.Query.Internal.SqlServerQueryCompilationContextFactory [8]所述的 LINQ表达式 '(__property_0.Invoke([X])== __filter_Value_1)' 无法翻译和将本地评估。要配置 ,此警告使用DbContextOptionsBuilder.ConfigureWarnings API (事件ID'RelationalEventId.QueryClientEvaluationWarning')。 重写 DbContext.OnConfiguring方法或使用 应用程序服务提供者上的AddDbContext时,可以使用ConfigureWarnings。
的问题是:
我怎样才能使这项工程的? 另外,关于如何最好的这个建议?