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

Lamda表达式

使用Lamda表达式可以很方便的按条件过滤数据。Entity Framework也是将Lamda表达式转换成对应的SQL语句执行。

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

  1. namespace ConsoleApp
  2. {
  3. public class Person
  4. {
  5. public string Name { get; set; }
  6. public int Age { get; set; }
  7. }
  8. class MyDbContext : DbContext
  9. {
  10. public DbSet<Person> People { get; set; }
  11. protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
  12. {
  13. optionsBuilder.UseSqlServer("Server=(local);Database=TestDB;User Id=sa;Password=sa;");
  14. }
  15. }
  16.  
  17. class Program
  18. {
  19. static void Main(string[] args)
  20. {
  21. MyDbContext dbContext = new MyDbContext();
  22.  
  23. foreach (var item in dbContext.People.Where(m => m.Age > ))
  24. {
  25. Console.WriteLine(item.Name);
  26. }
  27. }
  28. }
  29. }

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

Expression

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

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

参数

参数有类型和名字:

  1. Type type= typeof(Person);
  2. var parameter = Expression.Parameter(type, "m");

属性

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

  1. PropertyInfo property = type.GetProperty("Age");
  2. Expression expProperty = Expression.Property(parameter, property.Name);

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

  1. Expression<Func<object>> valueLamda = () => ;
  2. Expression expValue = Expression.Convert(valueLamda.Body, property.PropertyType);

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

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

  1. Expression expValue = Expression.Constant();

运算符

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

  1. Expression expression = Expression.GreaterThan(expProperty, expValue);

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

  1. Expression<Func<Person, bool>> filter = ((Expression<Func<Person, bool>>)Expression.Lambda(expression, parameter));
  2. foreach (var item in dbContext.People.Where(filter))
  3. {
  4. Console.WriteLine(item.Name);
  5. }

下面是完整代码

  1. namespace ConsoleApp
  2. {
  3. public class Person
  4. {
  5. public string Name { get; set; }
  6. public int Age { get; set; }
  7. }
  8. class MyDbContext : DbContext
  9. {
  10. public DbSet<Person> People { get; set; }
  11. protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
  12. {
  13. optionsBuilder.UseSqlServer("Server=(local);Database=TestDB;User Id=sa;Password=sa;");
  14. }
  15. }
  16.  
  17. class Program
  18. {
  19. static void Main(string[] args)
  20. {
  21. MyDbContext dbContext = new MyDbContext();
  22.  
  23. Type type = typeof(Person);
  24. var parameter = Expression.Parameter(type, "m");
  25.  
  26. PropertyInfo property = type.GetProperty("Age");
  27. Expression expProperty = Expression.Property(parameter, property.Name);
  28.  
  29. Expression<Func<object>> valueLamda = () => ;
  30. Expression expValue = Expression.Convert(valueLamda.Body, property.PropertyType);
  31.  
  32. Expression expression = Expression.GreaterThan(expProperty, expValue);
  33. Expression<Func<Person, bool>> filter = ((Expression<Func<Person, bool>>)Expression.Lambda(expression, parameter));
  34. foreach (var item in dbContext.People.Where(filter))
  35. {
  36. Console.WriteLine(item.Name);
  37. }
  38. }
  39. }
  40. }

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

封装和使用

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

https://github.com/SeriaWei/ZKEACMS/blob/master/src/EasyFrameWork/LINQ/Query.cs

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

  1. static void Main(string[] args)
  2. {
  3. MyDbContext dbContext = new MyDbContext();
  4.  
  5. QueryCollection queries = new QueryCollection();
  6. queries.Add(new Query { Name = "Age", Operator = Query.Operators.GreaterThan, Value = });
  7.  
  8. foreach (var item in dbContext.People.Where(queries.AsExpression<Person>()))
  9. {
  10. Console.WriteLine(item.Name);
  11. }
  12. }

原文地址:http://www.zkea.net/codesnippet/detail/entity-framework-dynamic-search.html

动态构建Lambda表达式实现EF动态查询的更多相关文章

  1. 动态创建Lambda表达式实现高级查询

    需求简介 最近这几天做的东西总算是回归咱的老本行了,给投资管理项目做一个台账的东西,就是类似我们的报表.其 中有一个功能是一个高级查询的需求,在查询条件方面大概有7.8个查询条件.需求就是如果一个条件 ...

  2. 动态创建 Lambda 表达式

    首先我们看一个简单 Lambda 表达式的构成. i => i > 5 在这个表达式中,"i" 被称为 Parameter,"i > 5" 是 ...

  3. easyui datagrid remoteSort的实现 Controllers编写动态的Lambda表达式 IQueryable OrderBy扩展

    EF 结合easy-ui datagrid 实现页面端排序 EF动态编写排序Lambda表达式 1.前端页面 var mainListHeight = $(window).height() - 20; ...

  4. 动态组合lambda 表达式

    //记录实体集合—动态组合lambda 表达式 Expression<Func<AdEntity, bool>> thirdWhere = p => p.Observer ...

  5. 【转】EntityFramework动态组合Lambda表达式作为数据筛选条件,代替拼接SQL语句

    传统的操作数据库方式,筛选数据需要用StringBuilder拼接一大堆的WHERE子句. 在Entity Framework中,代码稍有不慎就会造成巨大性能消耗,如: using(var db=ne ...

  6. [2014-12-30]如何动态构造Lambda表达式(动态构造Lambda查询条件表达式)

    声明 本文对Lambda表达式的扩展,示例代码来源于网络. 场景描述 web开发查询功能的时候,如果查询条件比较多,就会遇到动态组合查询条件的情况.在手写sql的情况下,我们一般会根据传入的参数,针对 ...

  7. 动态拼接lambda表达式树

    前言 最近在优化同事写的代码(我们的框架用的是dapperLambda),其中有一个这样很普通的场景——界面上提供了一些查询条件框供用户来进行过滤数据.由于dapperLambda按条件查询时是传入表 ...

  8. C#动态创建lambda表达式

    /// <summary> /// 创建lambda表达式:p=>true /// </summary> /// <typeparam name="T&q ...

  9. 使用Expression动态创建lambda表达式

    using System;using System.Linq.Expressions;using System.Reflection; namespace Helper{ public class L ...

随机推荐

  1. java之动态代理设计模式

    代理:专门完成代理请求的操作类,是所有动态代理类的父类,通过此类为一个或多个接口动态地生成实现类. 弄清动态代理的关键是清楚java的反射机制,在https://www.cnblogs.com/xix ...

  2. PCA主成分分析(最大投影方差)

    PCA简介: 从n维数据中提取最能代表这组数据的m个向量,也就是对数据进行降维(n->m),提取特征. 目标: 找到一个向量\(\mu\),使n个点在其上的投影的方差最大(投影后的数据越不集中, ...

  3. 事隔五年之后,开启第2版DSP数字信号处理和CMSIS-NN神经网络教程,同步开启三代示波器,前15章发布(2019-11-04)

    说明:1.第1版DSP教程发布于2014年末,纪念下:https://www.cnblogs.com/armfly/p/11274826.html2.这几年在信号处理的应用上积累了一些经验,也发现了很 ...

  4. Docker安全扫描工具之docker-bench-security

    简介 Docker Bench for Security检查关于在生产环境中部署Docker容器的几十个常见最佳实践.这些测试都是自动化的,其灵感来自CIS Docker基准1.2.0版. 这种安全扫 ...

  5. 东芝半导体最新ARM开发板——TT_M3HQ开箱评测

    前言 最近从面包板社区申请到一块东芝最新ARM Cortex-M3内核的开发板--TT_M3HQ,其实开发板收到好几天了,这几天一直在构思怎么来写这第一篇评测文章,看大家在社区也都发了第一篇评测,我也 ...

  6. ETCD:客户端v3

    原文地址:etcd/clientv3 etcd/clientv3是v3版本的Go etcd官方客户端 安装 go get go.etcd.io/etcd/clientv3 开始 创建客户端使用clie ...

  7. python 装饰器使用总结

    python 装饰器使用总结 by:授客 QQ:1033553122 测试环境 win10 python 3.5 例1:一个简单的例子 #!/usr/bin/env python # -*- codi ...

  8. C lang: The caracter reverse

    Ax_Code #include<stdio.h> int main(void) { int i; char string[7] = {"mrsoft"}; char ...

  9. dbms_profiler

    @?/rdbms/admin/profload.sql @?/rdbms/admin/proftab.sql CREATE or replace PUBLIC SYNONYM plsql_profil ...

  10. windows系统搭建zookeeper

    安装&配置 在apache的官方网站提供了好多镜像下载地址,然后找到对应的版本 下载地址: http://mirrors.cnnic.cn/apache/zookeeper/zookeeper ...