使用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#代码

  1. 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生成的代码。

  1. 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延迟加载的特性。