重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
这篇文章将为大家详细讲解有关LINQ查询表达式如何利用c# 进行构建,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。
目前成都创新互联已为成百上千家的企业提供了网站建设、域名、网络空间、网站托管维护、企业网站设计、穆棱网站维护等服务,公司将坚持客户导向、应用为本的策略,正道将秉承"和谐、参与、激情"的文化,与客户和合作伙伴齐心协力一起成长,共同发展。最近工作中遇到一个这样的需求:在某个列表查询功能中,可以选择某个数字列(如商品单价、当天销售额、当月销售额等),再选择小于或等于
和大于或等于
,再填写一个待比较的数值,对数据进行查询过滤。
如果只有一两个这样的数字列,那么使用 Entity Framework Core 可以这么写 LINQ 查询:
public Task> 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
要知道如何动态创建一个类似 Expression
对于本示例,以 x => x.Amount1 <= value 表达式实例为例,它的表达式树是这样的:
然后我们可以按照此表达式树结构来构建我们的 LINQ 表达式:
public Task> 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
>(compareExp, paramExp); return query.Where(lambda).ToListAsync(); }
每个 Expression.XXX 静态方法返回的都是一个以 Expression 为基类的实例,代表一个表达式。不同的表达式又可以组成一个新的表达式,直到得到我们需要的 Lambda 表达式。这样就形成了一种树形结构,我们称为表达式树。知道如何把一个最终的查询表达式拆解成表达式树,我们就容易动态构建此查询表达式。
得到一个表达式后,我们还可以动态编译并调用该表达式,比如上面示例得到的 lambda 变量,是一个Expression
... var toTestProduct = new Product { Amount1 = 100, Amount2 = 200 }; Funcfunc = 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.
关于LINQ查询表达式如何利用c# 进行构建就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。