
[英]EF Core global query filter based on nullable property resulting in NullReferenceException
[英]Filtering EF query based on filter object automatically
假设我们有以下课程:
class A
{
public int Id {get; set;}
public string Name {get; set;}
}
class FilterA
{
public List<int> Ids {get; set;}
public List<string> Names {get; set;}
}
我有一个 IQueryable,我需要以某种通用方式根据 FilterA 中提供的值进行过滤,因为在实际项目中我必须处理数百个这样的对象,每个对象都有数十个属性,我厌倦了写意大利面条代码如下:
if(filter.Ids.Any())
{
query = query.Where(q=>filter.Ids.Contains(q.Id));
}
if(filter.Names.Any())
{
query = query.Where(q=>filter.Names.Contains(q.Name));
}
...
我试图自己实现几次,但都失败了。 从我的角度来看,主要问题是我无法指定返回不同类型的表达式列表,因此每次都以一些可怕的、巨大的和不可读的反射结束。 因此,也许我遗漏了一些明显的方法,或者已经有了解决方案——除非它不是一大堆不可读的代码,否则一切都会起作用,只是不希望治疗比疾病更糟。
提前致谢
你可以做的一件事是引入扩展方法,这样检查就可以变成一个衬里/链接(实际的方法名称由你决定):
public static class QueryableExts
{
private static MethodInfo? _methodInfo = typeof(Enumerable).GetMethod(nameof(Enumerable.Contains));
public static IQueryable<T> WhereInNotNullOrEmpty<T, TKey>(
this IQueryable<T> q,
Expression<Func<T, TKey>> selector,
ICollection<TKey>? values)
{
if (values == null || values.Any())
{
return q;
}
var collection = Expression.Constant(values);
var contains = Expression.Call(_methodInfo, collection, selector.Body);
var expression = Expression.Lambda<Func<T, bool>>(contains, selector.Parameters);
return q.Where(expression);
}
}
和用法:
query = query
.WhereInNotNullOrEmpty(q => q.Id, filter.Ids)
.WhereInNotNullOrEmpty(q => q.Name, filter.Names);
除此之外,如果您想以更动态的方式应用此过滤,则只能使用一些代码生成/反射。 我认为使用源生成器可能是比在现代 .NET 中对此进行反射更可取的方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.