使用Expression
using (MyDbContext ctx = new MyDbContext())
{
Expression<Func<Student, bool>> exp01 = s => s.Name.Contains("stu");
foreach (Student s in ctx.Students.IgnoreQueryFilters().Where(exp01))
{
Console.WriteLine(s.Name);
}
}
引入ExpressionTreeToString nuget包以后,通过ToString()显示对应的C#代码
- Object notation
Expression<Func<Student, bool>> exp01 = s => s.Name.Contains("stu");
Console.WriteLine(exp01.ToString("Object notation", "C#"));
*** 上面生成的代码不能直接移植,因为不能用new ParameterExpression(),要改成Expression.Parameter()静态调用。
建议使用Factory methods生成的代码。
- Factory methods
Expression<Func<Student, bool>> exp01 = s => s.Name.Contains("stu");
Console.WriteLine(exp01.ToString("Object notation", "C#"));
使用Factory methods生成的代码,可以得到同样的sql语句
using static System.Linq.Expressions.Expression;
using (MyDbContext ctx = new MyDbContext())
{
//Expression<Func<Student, bool>> exp01 = s => s.Name.Contains("stu");
var s = Parameter(
typeof(Student),
"s"
);
var exp01 = Lambda<Func<Student, bool>>(
Call(
MakeMemberAccess(s,
typeof(Student).GetProperty("Name")
),
typeof(string).GetMethod("Contains", new[] { typeof(string) }),
Constant("stu")
),
s
);
foreach (Student stu in ctx.Students.IgnoreQueryFilters().Where(exp01))
{
Console.WriteLine(stu.Name);
}
}
这样就可以动态的生成Expression,不知道怎么写的时候,就用Factory methods看一下。
虽然动态生成Expression看上去很酷,但是存在代码维护困难的问题,所以更推荐使用IQueryable延迟加载的特性。