如何在C#的Where关键字中使用字符串变量作为查询条件
用字符串形式的条件过滤List或DbSet数据
直接将字符串形式的Lambda表达式传给Where方法是行不通的,因为List<T>.Where需要的是Func<T, bool>委托,而DbSet<T>.Where需要的是Expression<Func<T, bool>>表达式树,都不接受字符串参数。下面分两种场景给出可行方案:
一、过滤List
方案1:使用Roslyn动态编译字符串为委托
通过Roslyn编译字符串形式的Lambda,生成对应的Func<T, bool>委托后传给Where:
using System; using System.Collections.Generic; using System.Reflection; using System.IO; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; List<int> numbers = new List<int>() { 1, 2, 4, 8, 16, 32 }; string queryStr = "n => n < 10"; // 编译字符串Lambda为Func<int, bool> var syntaxTree = CSharpSyntaxTree.ParseText(@$" using System; public static class DynamicFilter {{ public static Func<int, bool> GetFilter() {{ return {queryStr}; }} }}"); var references = new[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location), MetadataReference.CreateFromFile(typeof(Func<int, bool>).Assembly.Location) }; var compilation = CSharpCompilation.Create( "DynamicFilterAssembly", syntaxTrees: new[] { syntaxTree }, references: references, options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)); using var ms = new MemoryStream(); var emitResult = compilation.Emit(ms); if (!emitResult.Success) { foreach (var diag in emitResult.Diagnostics) Console.WriteLine(diag.ToString()); throw new InvalidOperationException("无法编译字符串Lambda表达式"); } ms.Position = 0; var assembly = Assembly.Load(ms.ToArray()); var filterFunc = (Func<int, bool>)assembly.GetType("DynamicFilter").GetMethod("GetFilter").Invoke(null, null); var smallNumbers = numbers.Where(filterFunc).ToList(); // 结果:[1,2,4,8]
方案2:使用System.Linq.Dynamic.Core(更简便)
安装NuGet包 System.Linq.Dynamic.Core,它提供了支持字符串条件的Where扩展方法,无需手动编译:
using System.Collections.Generic; using System.Linq.Dynamic.Core; List<int> numbers = new List<int>() { 1, 2, 4, 8, 16, 32 }; string queryStr = "n < 10"; // 无需写"n => "前缀,直接写条件 var smallNumbers = numbers.Where(queryStr).ToList();
二、过滤DbSet(EF Core)
推荐使用System.Linq.Dynamic.Core,它能将字符串条件转换成EF Core可解析的表达式树,避免全表加载:
- 先安装NuGet包:
Install-Package System.Linq.Dynamic.Core - 编写代码:
// 假设你的DbContext有CampaignLog DbSet,实体包含Id属性 string queryStr = "Id == 1 || Id == 3"; var logdata = DbContext.CampaignLog.Where(queryStr).ToList();
该库支持常见的条件语法,比如比较、逻辑运算、甚至导航属性访问,例如"Category.Name == 'Books'"。
内容的提问来源于stack exchange,提问作者CS001
相关产品推荐
相关产品推荐

