gpt4 book ai didi

c# - Linqkit 中使用 PredicateBuilder 进行通用查询

转载 作者:行者123 更新时间:2023-12-02 03:56:59 29 4
gpt4 key购买 nike

我一直在使用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();
}

为了结束这堆 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();
}

为此,我创建了一些扩展方法来处理此问题

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);
}

问题是没有应用过滤器,答案就在上面的 Invoke 中。 EF 无法将上述表达式翻译为 SQL。EF 错误为

Microsoft.EntityFrameworkCore.Query.Internal.SqlServerQueryCompilationContextFactory[8] The LINQ expression '(__property_0.Invoke([x]) == __filter_Value_1)' could not be translated and will be evaluated locally. To configure this warning use the DbContextOptionsBuilder.ConfigureWarnings API (event id 'RelationalEventId.QueryClientEvaluationWarning'). ConfigureWarnings can be used when overriding the DbContext.OnConfiguring method or using AddDbContext on the application service provider.

问题是:

我怎样才能让这个建筑工作?另外,关于如何最好地这样做有什么建议吗?

最佳答案

你似乎忘记了除了 PredicateBuilder ,LINQKit 提供的真正有用的功能 AsExpandable , ExpandInvoke自定义扩展方法是为了能够在表达式树中正确嵌入表达式

为了利用该功能,您应该使用 Expression<Func<...>>而不是Func<...> 。在发布的代码中,替换所有出现的 Func<TPredicate, string>Expression<Func<TPredicate, string>>并且问题应该得到解决。

关于c# - Linqkit 中使用 PredicateBuilder 进行通用查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43503236/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com