服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C# - c# 动态构建LINQ查询表达式

c# 动态构建LINQ查询表达式

2022-10-18 11:55精致码农 • 王亮 C#

这篇文章主要介绍了c# 如何动态构建LINQ查询表达式,帮助大家更好的理解和学习c#,感兴趣的朋友可以了解下

作者:精致码农

出处:http://cnblogs.com/willick

联系:liam.wang@live.com

最近工作中遇到一个这样的需求:在某个列表查询功能中,可以选择某个数字列(如商品单价、当天销售额、当月销售额等),再选择 小于或等于大于或等于 ,再填写一个待比较的数值,对数据进行查询过滤。

如果只有一两个这样的数字列,那么使用 Entity Framework Core 可以这么写 LINQ 查询:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public Task<List<Product>> GetProductsAsync(string propertyToFilter, MathOperator mathOperator, decimal value)
{
  var query = _context.Products.AsNoTracking();
 
  query = propertyToFilter switch
  {
    "Amount1" when mathOperator == MathOperator.LessThanOrEqual => query.Where(x => x.Amount1 <= value),
    "Amount1" when mathOperator == MathOperator.GreaterThanOrEqual => query.Where(x => x.Amount1 >= value),
 
    "Amount2" when mathOperator == MathOperator.LessThanOrEqual => query.Where(x => x.Amount2 <= value),
    "Amount2" when mathOperator == MathOperator.GreaterThanOrEqual => query.Where(x => x.Amount2 >= value),
 
    _ => throw new ArgumentException($"不支持 {propertyToFilter} 列作为数字列查询", nameof(propertyToFilter))
  };
 
  return query.ToListAsync();
}

如果固定只有一两个数字列且将来也不会再扩展,这样写简单粗暴,也没什么问题。

但如果有几十个数字列,这样使用 swith 模式匹配的写法就太恐怖了,代码大量重复。很自然地,我们得想办法根据属性名动态创建 Where 方法的参数。它的参数类型是:Expression<Func<T, bool>>,是一个表达式参数。

要知道如何动态创建一个类似 Expression<Func<T, bool>> 类型的表达式实例,就要知道如何拆解表达式树。

对于本示例,以 x => x.Amount1 <= value 表达式实例为例,它的表达式树是这样的:

c# 动态构建LINQ查询表达式

然后我们可以按照此表达式树结构来构建我们的 LINQ 表达式:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public Task<List<Product>> GetProductsAsyncV2(string propertyToFilter, MathOperator mathOperator, decimal value)
{
  var query = _context.Products.AsNoTracking();
 
  var paramExp = Expression.Parameter(typeof(Product));
  var memberExp = Expression.PropertyOrField(paramExp, propertyToFilter);
  var valueExp = Expression.Constant(value);
  var compareExp = mathOperator == MathOperator.LessThanOrEqual ?
    Expression.LessThanOrEqual(memberExp, valueExp) :
    Expression.GreaterThanOrEqual(memberExp, valueExp);
  var lambda = Expression.Lambda<Func<Product, bool>>(compareExp, paramExp);
 
  return query.Where(lambda).ToListAsync();
}

每个 Expression.XXX 静态方法返回的都是一个以 Expression 为基类的实例,代表一个表达式。不同的表达式又可以组成一个新的表达式,直到得到我们需要的 Lambda 表达式。这样就形成了一种树形结构,我们称为表达式树。知道如何把一个最终的查询表达式拆解成表达式树,我们就容易动态构建此查询表达式。

得到一个表达式后,我们还可以动态编译并调用该表达式,比如上面示例得到的 lambda 变量,是一个Expression<Func<Product, bool>> 类型,调用其 Compile 方法,可以得到 Func<Product, bool> 类型的委托。

?
1
2
3
4
5
6
7
8
9
10
...
 
var toTestProduct = new Product { Amount1 = 100, Amount2 = 200 };
 
Func<Product, bool> func = lambda.Compile();
var result = func(toTestProduct);
 
Console.WriteLine($"The product's {propertyToFilter} is to {mathOperator} {value}.");
 
// Output: The product's Amount1 is LessThanOrEqual to 150.

你可以通过研究 Expression 类来了解更多动态构建表达式的方法。

动态构建 LINQ 表达式对于不能在编译时建立查询,只能在运行时建立查询的场景很有用。但它的缺点也很明显,不易维护、不易阅读、不易调试。如果最终的表达式执行出错,很难通过调试来发现具体是构建中的那一步写错了,只能凭自己的理解和经验查找错误。所以,如非必须,一般不推荐动态构建 LINQ 查询表达式。

以上就是c# 动态构建LINQ查询表达式的详细内容,更多关于c# LINQ查询表达式的资料请关注服务器之家其它相关文章!

原文链接:https://www.cnblogs.com/willick/p/14040435.html?utm_source=tuicool&utm_medium=referral

延伸 · 阅读

精彩推荐
  • C#C#访问及调用类中私有成员与方法示例代码

    C#访问及调用类中私有成员与方法示例代码

    访问一个类的私有成员不是什么好做法,大家也都知道私有成员在外部是不能被访问的,这篇文章主要给大家介绍了关于C#访问及调用类中私有成员与方法...

    cnc4732022-02-24
  • C#C#实现带搜索功能的ComboBox

    C#实现带搜索功能的ComboBox

    这篇文章主要为大家详细介绍了C#如何实现带搜索功能的ComboBox,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    眾尋4242021-12-09
  • C#Unity实现简单虚拟摇杆(附代码)

    Unity实现简单虚拟摇杆(附代码)

    这篇文章主要为大家详细介绍了Unity实现简单虚拟摇杆,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    臣定保幼主周全ぃ3492022-09-01
  • C#C#算法之大牛生小牛的问题高效解决方法

    C#算法之大牛生小牛的问题高效解决方法

    本文主要介绍两种方法处理大牛生小牛的问题,第二种效率更高,希望能给大家一个参考。...

    Robin5192021-11-26
  • C#C#中抽象类与接口的区别详解

    C#中抽象类与接口的区别详解

    本文主要介绍了C#中抽象类与接口的区别。具有很好的参考价值。下面跟着小编一起来看下吧...

    淡泊明志_宁静3742021-12-29
  • C#C#基于简单工厂模式实现的计算器功能示例

    C#基于简单工厂模式实现的计算器功能示例

    这篇文章主要介绍了C#基于简单工厂模式实现的计算器功能,结合简单实例形式分析了C#使用工厂模式的数值运算相关操作技巧,需要的朋友可以参考下...

    无盐海8212022-01-25
  • C#计算器实例代码讲解C#工厂模式

    计算器实例代码讲解C#工厂模式

    这篇文章主要介绍了c#工厂模式的的相关资料,以计算器实例代码讲解,帮助大家更好的理解和学习,感兴趣的朋友可以了解下...

    老胡写代码5242022-09-15
  • C#unity实现手机端摇杆控制人物移动

    unity实现手机端摇杆控制人物移动

    这篇文章主要为大家详细介绍了unity实现手机端摇杆控制人物移动,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    魏恩君--Caroline8032022-08-31