You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用LINQ筛选List中任意属性匹配指定字符串的对象?

实现DataTable结果集的全局文本搜索(LINQ方式)

我有一个用于DataTable的结果集,代码如下:

var data = ctx.Clinics.AsNoTracking().OrderBy(p => p.Name).Select(p => new
{
    ID = p.ID,
    Name = p.Name,
    Region = p.Regions.Description,
    City = p.City,
    Address = p.Address,
    Phone = p.Phone,
    InterestPassive = p.InterestPassive,
    InterestGlad = p.InterestGlad,
    Gross = p.Activities.Where(e => e.Converted.HasValue && e.Converted.Value && e.DateActivity.HasValue).Sum(s => (decimal?)s.FirstEstimate) ?? 0,
    DiscountApplied = p.Activities.Where(e => e.Converted.HasValue && e.Converted.Value && e.DateActivity.HasValue && e.Discount != null).Sum(e => (e.FirstEstimate / 100) * e.Discount) ?? 0,
}).ToList();

我希望对该列表的所有属性应用包含指定输入字符串的筛选(如表格全局搜索的自由文本框),获取搜索关键词的代码为:

string searchTerm = Request.Form.GetValues("search[value]").FirstOrDefault();

请问能否通过LINQ实现对List中对象的所有属性进行值搜索?


当然可以,分两种场景提供实现方案:

方案一:内存中过滤(已ToList之后)

如果数据已经加载到内存,可通过反射遍历匿名对象的所有属性,将属性值转为字符串后判断是否包含搜索关键词:

if (!string.IsNullOrEmpty(searchTerm))
{
    data = data.Where(item => 
        item.GetType().GetProperties()
            .Any(prop => 
            {
                var value = prop.GetValue(item)?.ToString();
                return !string.IsNullOrEmpty(value) && value.IndexOf(searchTerm, StringComparison.OrdinalIgnoreCase) >= 0;
            })
    ).ToList();
}

注意事项

  • 此方式是内存内过滤,数据量较大时性能会受影响,优先推荐数据库层面过滤。
  • StringComparison.OrdinalIgnoreCase实现不区分大小写搜索,可根据需求调整为区分大小写。
  • 数值类型(如ID、Gross)会自动转为字符串匹配,比如搜索"123"会匹配ID=123或Gross=123.5的记录。

方案二:数据库层面过滤(更高效)

如果数据量较大,建议直接在EF查询阶段加入筛选逻辑,让数据库执行过滤,性能更优。由于匿名类无法通过反射生成SQL,需手动对每个属性构建OR条件:

string searchTerm = Request.Form.GetValues("search[value]").FirstOrDefault();

var query = ctx.Clinics.AsNoTracking()
    .OrderBy(p => p.Name)
    .Select(p => new
    {
        ID = p.ID,
        Name = p.Name,
        Region = p.Regions.Description,
        City = p.City,
        Address = p.Address,
        Phone = p.Phone,
        InterestPassive = p.InterestPassive,
        InterestGlad = p.InterestGlad,
        Gross = p.Activities.Where(e => e.Converted.HasValue && e.Converted.Value && e.DateActivity.HasValue).Sum(s => (decimal?)s.FirstEstimate) ?? 0,
        DiscountApplied = p.Activities.Where(e => e.Converted.HasValue && e.Converted.Value && e.DateActivity.HasValue && e.Discount != null).Sum(e => (e.FirstEstimate / 100) * e.Discount) ?? 0,
    });

if (!string.IsNullOrEmpty(searchTerm))
{
    query = query.Where(p => 
        p.ID.ToString().Contains(searchTerm) ||
        p.Name.Contains(searchTerm) ||
        (p.Region != null && p.Region.Contains(searchTerm)) ||
        (p.City != null && p.City.Contains(searchTerm)) ||
        (p.Address != null && p.Address.Contains(searchTerm)) ||
        (p.Phone != null && p.Phone.Contains(searchTerm)) ||
        p.InterestPassive.ToString().Contains(searchTerm) ||
        p.InterestGlad.ToString().Contains(searchTerm) ||
        p.Gross.ToString().Contains(searchTerm) ||
        p.DiscountApplied.ToString().Contains(searchTerm)
    );
}

var data = query.ToList();

注意事项

  • 可为null的字符串属性(如Region、City)需先判断是否为null,避免空引用异常。
  • 若需要数据库层面的不区分大小写搜索,可替换Contains为EF.Functions.Like(p.Name, $"%{searchTerm}%"),兼容性更好。
  • 若需精准数值匹配(而非字符串包含),可单独调整对应属性的判断逻辑,比如p.ID == int.Parse(searchTerm)(需先处理格式验证)。

内容的提问来源于stack exchange,提问作者markzzz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 08:35:25