如何用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
相关产品推荐
相关产品推荐

