解答网友提问:如何构建动态表达式实现高级查询服务
Posted dotNET跨平台
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了解答网友提问:如何构建动态表达式实现高级查询服务相关的知识,希望对你有一定的参考价值。
上次我们介绍了"一秒创建高级查询服务"。前天,有网友在公众号后台问我,怎么使用动态表达式:
我想应该是客户提出了更高的要求,查询的条件不仅限于大于、小于,更加多样化,需要动态组合成条件,类似下图:
那么,有不有什么方式能快速实现这一业务要求呢?!
思考
我们使用IQueryable去查询数据,那么只需要传入的参数能够转成Lambda表达式就可以了。
当然,可以使用Expression.Lambda
方法去动态创建表达式树,但是那样对传入的数据模型格式有一定要求。
能不能就用字符串生成动态表达式呢?
实现方式
Roslyn是微软开源的.NET编译器,但是鲜为人知的,它还提供了CSharp scripting
API。
创建Asp.Net Core Web API项目,引用Nuget包Microsoft.CodeAnalysis.CSharp.Scripting
。
然后,修改WeatherForecastController.cs的Get方法,假定查询条件是从前端拼接后传递过来的:
[HttpGet]
public async Task<IEnumerable<WeatherForecast>> Get()
{
//温度大于20, Summary必须以C开头
var filter = @"p => p.TemperatureC > 20 && p.Summary.StartsWith(""C"")";
//由于使用了String.StartsWith,所以要引用String所在的Assembly
var options = ScriptOptions.Default.AddReferences(typeof(WeatherForecast).Assembly,
typeof(String).Assembly);
Func<WeatherForecast, bool> expression = await CSharpScript.EvaluateAsync<Func<WeatherForecast, bool>>(filter, options);
var rng = new Random();
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
TemperatureC = rng.Next(-20, 55),
Summary = Summaries[rng.Next(Summaries.Length)]
}).AsQueryable().Where(expression)
.ToArray();
}
运行程序,可以看到只返回满足条件的数据(默认应该是5条),如下图:
结论
需要注意的是,动态编译肯定是有一定的性能损失的,这就要看业务上如何取舍了。
欢迎大家到公众号后台留言与我交流。如果你有更好的实现方式,也可以告诉我!
如果你觉得这篇文章对你有所启发,请关注我的个人公众号”My IO“,记住我!
以上是关于解答网友提问:如何构建动态表达式实现高级查询服务的主要内容,如果未能解决你的问题,请参考以下文章
基于Expression Lambda表达式树的通用复杂动态查询构建器——《构思篇二》已开源