当前位置: 移动技术网 > IT编程>开发语言>.net > 动态构建Lambda表达式实现EF动态查询

动态构建Lambda表达式实现EF动态查询

2019年08月11日  | 移动技术网IT编程  | 我要评论

甘肃人事,dnf吉赛尔近卫兵的徽章有什么用,北部新区教育局

在使用entity framework做数据查询的时候,查询条件往往不是固定的,需要动态查询。可以通过动态构建lamda表达式来实现动态查询。

lamda表达式

使用lamda表达式可以很方便的按条件过滤数据。entity framework也是将lamda表达式转换成对应的sql语句执行。

比如下列代码,输出年龄大于1的人的名字:

namespace consoleapp
{
    public class person
    {
        public string name { get; set; }
        public int age { get; set; }
    }
    class mydbcontext : dbcontext
    {
        public dbset<person> people { get; set; }
        protected override void onconfiguring(dbcontextoptionsbuilder optionsbuilder)
        {
            optionsbuilder.usesqlserver("server=(local);database=testdb;user id=sa;password=sa;");
        }
    }

    class program
    {
        static void main(string[] args)
        {
            mydbcontext dbcontext = new mydbcontext();

            foreach (var item in dbcontext.people.where(m => m.age > 1))
            {
                console.writeline(item.name);
            }
        }
    }
}

peoples.where(m => m.age > 1)这个在代码里面写死了,如果要换条件就一定要改代码。

expression

先看一下where里面是什么,where里面是表达式的主体,分为参数m,左边参数m的属性和右边的值,通过中间的大于运算符进行比较运算。所以我们在构建表达式的时候,也需要构建这四个部分:

  • 参数
  • 参数的属性
  • 运算符

参数

参数有类型和名字:

type type= typeof(person);
var parameter = expression.parameter(type, "m");

属性

我们需要知道属性的名称和类型,可通过反射来得到对应的类型并和刚刚的参数关联起来:

propertyinfo property = type.getproperty("age");
expression expproperty = expression.property(parameter, property.name);

我们还需构建一个值的表达式:

expression<func<object>> valuelamda = () => 1;
expression expvalue = expression.convert(valuelamda.body, property.propertytype);

因为值委托的返回类型是object,所以需要使用expression.convert来转换成正确的类型。

如果值是简单类型,如int, string等,也可以直接使用expression.constant,简单一些:

expression expvalue = expression.constant(1);

运算符

现在已经有了属性表达式,值表达式,接下来就是要使用运算符表达式把它们连接起来:

expression expression = expression.greaterthan(expproperty, expvalue);

将表达式转换成对应的类型即可以使用了: 

expression<func<person, bool>> filter = ((expression<func<person, bool>>)expression.lambda(expression, parameter));
foreach (var item in dbcontext.people.where(filter))
{
    console.writeline(item.name);
}

下面是完整代码

namespace consoleapp
{
    public class person
    {
        public string name { get; set; }
        public int age { get; set; }
    }
    class mydbcontext : dbcontext
    {
        public dbset<person> people { get; set; }
        protected override void onconfiguring(dbcontextoptionsbuilder optionsbuilder)
        {
            optionsbuilder.usesqlserver("server=(local);database=testdb;user id=sa;password=sa;");
        }
    }

    class program
    {
        static void main(string[] args)
        {
            mydbcontext dbcontext = new mydbcontext();

            type type = typeof(person);
            var parameter = expression.parameter(type, "m");

            propertyinfo property = type.getproperty("age");
            expression expproperty = expression.property(parameter, property.name);

            expression<func<object>> valuelamda = () => 1;
            expression expvalue = expression.convert(valuelamda.body, property.propertytype);

            expression expression = expression.greaterthan(expproperty, expvalue);
            expression<func<person, bool>> filter = ((expression<func<person, bool>>)expression.lambda(expression, parameter));
            foreach (var item in dbcontext.people.where(filter))
            {
                console.writeline(item.name);
            }
        }
    }
}

这样就可以通过动态传入属性名和值来进行动态查询了。

封装和使用

我们做了一些简单的封装,更方便使用,代码:

https://github.com/seriawei/zkeacms/blob/master/src/easyframework/linq/query.cs

使用querycollection来添加条件,最后转成表达式:

static void main(string[] args)
{
    mydbcontext dbcontext = new mydbcontext();

    querycollection queries = new querycollection();
    queries.add(new query { name = "age", operator = query.operators.greaterthan, value = 1 });

    foreach (var item in dbcontext.people.where(queries.asexpression<person>()))
    {
        console.writeline(item.name);
    }
}

原文地址:

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网