c# - Entity Framework LINQ 复杂查询 - 组合多个谓词

标签 c# .net linq .net-core entity-framework-core

我正在尝试创建一个复杂的 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; }
}

最佳答案

最简单的解决方案之一是使用 LINQKit图书馆:

var predicate = PredicateBuilder.New<Person>();

if (!filter.Name.IsNullOrWhiteSpace())
{
    predicate = predicate.And(p => p.Name.ToLower().Contains(filter.Name.ToLower()));
}

if (!filter.Firstname.IsNullOrWhiteSpace())
{
    predicate = predicate.And(p => p.Firstname.ToLower().Contains(filter.Firstname.ToLower()));
}

if (!filter.ContactNumber.IsNullOrWhiteSpace())
{
    predicate = predicate.And(p => p.ContactNumber.contains(filter.ContactNumber));
}

Expression<Func<Person, bool>> exp = predicate;

query = query
    .AsExpandable()
    .Where(o => o.Persons.Any(exp.Compile()));

关于c# - Entity Framework LINQ 复杂查询 - 组合多个谓词,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67807843/

相关文章:

c# - 解析确切的自定义时间格式?

c# - 对图表(点数组)进行去噪

.net - 将多页 TIFF 转换为 PNG .Net

c# - 在字典的 linq 迭代过程中,什么可能导致堆栈溢出?

c# - 在 XDocument 中按名称在任意深度查询元素

c# - 如何将复杂的 linq 映射到对象

c# - 集合被修改;哈希表可能无法执行枚举操作

c# - 如何在 ASP.NET(Web 窗体)中添加标题后缀?

c# - 像 GlovePIE 一样伪造输入

c# - 为 C# .NET 编写 typeof(Xml) 的正确方法是什么?