【发布时间】:2021-08-20 18:33:27
【问题描述】:
我正在尝试创建一个复杂的 Linq 查询,如下所示: 获取所有员工符合给定过滤参数的组织。
过滤器示例:
- 名字:约翰
- 姓名:史密斯
我的第一次尝试:
if (!filter.Name.IsNullOrWhiteSpace())
{
query = query.Where(o => o.Persons.Any(p => p.Name.ToLower().Contains(filter.Name.ToLower())));
}
if (!filter.Firstname.IsNullOrWhiteSpace())
{
query = query.Where(o => o.Persons.Any(p => p.Firstname.ToLower().Contains(filter.Firstname.ToLower())));
}
if (!filter.ContactNumber.IsNullOrWhiteSpace())
{
query = query.Where(o => o.Persons.Any(p => p.ContactNumber.contains(filter.ContactNumber)));
}
这种方法的问题在于,当组织 A 中有人姓 John(例如 John Johnson),而组织 A 中有人姓 Smith (Jenny Smith) 时,组织 (A) 包含那两个人被退回。这是不应该的。我只希望组织中的人员名字为“john”且姓氏为“Smith”
我找到了一种可行但肮脏且不可扩展的方法:
if (!filter.ContactNumber.IsNullOrWhiteSpace())
{
if (!filter.Name.IsNullOrWhiteSpace() && !filter.Firstname.IsNullOrWhiteSpace())
{
query = query.Where(o => o.Persons.Any(p => p.ContactNumber.contains(filter.ContactNumber)
&& p.Name.ToLower().Contains(filter.Name.ToLower())
&& p.Firstname.ToLower().Contains(filter.Firstname.ToLower())));
}
else if (!filter.Name.IsNullOrWhiteSpace())
{
query = query.Where(o => o.Persons.Any(p => p.ContactNumber.contains(filter.ContactNumber)
&& p.Name.ToLower().Contains(filter.Name.ToLower())));
} else if (!filter.Firstname.IsNullOrWhiteSpace())
{
query = query.Where(o => o.Persons.Any(p => p.ContactNumber.contains(filter.ContactNumber)
&& p.Firstname.ToLower().Contains(filter.Firstname.ToLower())));
} else
{
query = query.Where(o => o.Persons.Any(p => p.ContactNumber.contains(filter.ContactNumber));
}
} else if(!filter.Name.IsNullOrWhiteSpace())
{
if (!filter.Firstname.IsNullOrWhiteSpace())
{
query = query.Where(o => o.Persons.Any(p => p.Firstname.ToLower().Contains(filter.Firstname.ToLower()) && p.Name.ToLower().Contains(filter.Name.ToLower())));
} else
{
query = query.Where(o => o.Persons.Any(p => p.Name.ToLower().Contains(filter.Name.ToLower())));
}
} else if (!filter.Firstname.IsNullOrWhiteSpace())
{
query = query.Where(o => o.Persons.Any(p => p.Firstname.ToLower().Contains(filter.Firstname.ToLower())));
}
如您所见,这不是一个非常干净的解决方案。
我也尝试在表达式中使用方法调用,但 Linq 无法翻译。有什么办法可以制作一个谓词表达式列表并将它们合并为一个?还是有其他更好的解决方案?
顺便说一句,由于我需要一个分页列表,所以所有内容都必须在一个查询中。
供您参考,这就是我的过滤器类的样子。它只是从我的前端发送的一个类,包含所有需要过滤的字段。
public class ContactFilter
{
public string Name{ get; set; }
public string Firstname{ get; set; }
public string ContactNummer { get; set; }
}
【问题讨论】:
-
filter到底是什么类型?看起来不像Predicate<T>。它的属性来自哪里? -
Filter 只是一个简单的类,其中包含需要过滤的字段。有些字段可能为空,有些不是,取决于填写的字段。我编辑了描述
-
为什么您的第一个代码不起作用?它似乎是过滤器中每个值的 AND 条件。
-
顺便说一句,包含可能需要替换为相等。
-
由于下面的解释,第一个代码不起作用。我需要包含,因为我想允许部分匹配
标签: c# .net linq .net-core entity-framework-core