Jed*_*i31 0 c# entity-framework linqkit entity-framework-core
我一直在使用LinqKit来创建通用查询.
一直困扰我的一件事是你总是要测试过滤器中发送的值是否有效.
例如:假设我有一个字符串过滤器.条件可以是Equal,StartsWith,EndsWith和Contains.
我的方法看起来像这样:
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();
}
Run Code Online (Sandbox Code Playgroud)
为了结束这一堆If,我决定创建一个通用方法来将过滤器应用于属性.我的想法是传递将应用过滤器的属性和过滤器定义,并封装表达式创建逻辑
它将是这种类型的东西:
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();
}
Run Code Online (Sandbox Code Playgroud)
为此,我创建了一些扩展方法来处理这个问题
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);
}
Run Code Online (Sandbox Code Playgroud)
问题是没有应用过滤器,答案就在Invoke中.EF无法将上述表达式转换为SQL.EF错误是
Microsoft.EntityFrameworkCore.Query.Internal.SqlServerQueryCompilationContextFactory [8] LINQ表达式'(__ propertyperty_0.Invoke([x])== __filter_Value_1)'无法翻译,将在本地进行评估.要配置此警告,请使用DbContextOptionsBuilder.ConfigureWarnings API(事件ID"RelationalEventId.QueryClientEvaluationWarning").重写DbContext.OnConfiguring方法或在应用程序服务提供程序上使用AddDbContext时,可以使用ConfigureWarnings.
问题是:
我怎样才能使这个建筑工作?另外,关于如何最好的任何建议?
你似乎忘了除了PredicateBuilder由LINQKit提供了非常有用的功能AsExpandable,Expand以及Invoke自定义扩展方法是能够正确地嵌入表达式的表达式树内.
为了利用该功能,您应该使用Expression<Func<...>>而不是Func<...>.在已发布的代码中,替换所有出现的内容Func<TPredicate, string>,Expression<Func<TPredicate, string>>应该解决问题.
| 归档时间: |
|
| 查看次数: |
1298 次 |
| 最近记录: |