原文:通用查询实现方案(可用于DDD)[附源码] -- 设计思路

【声明】
写作不易,转载请注明出处(http://www.cnblogs.com/wiseant/p/3988592.html)。
 
【系列文章】
通用查询实现方案(可用于DDD)[附源码] -- 代码解读
 
【前言】
在上一篇博文中,我向大家简单介绍了Xant.Querier通用查询,并分享了项目源码。这一篇继续给大家分享我的设计思路,也为了日后自己翻看。
 
【如何表示最基本的条件】

最基本的查询条件可以描述为{字段}={值},运算结果为布尔值。比较运算符不一定是等于,可以是包含、大于、小于等于,那么可以将一个条件描述为这样的表达式,该表达式计算结果为布尔值:

{字段}.比较运算({值})
OK,我们已经完成了第一步,可以表达出像单号等于"PO123"或是名字包含"中国"这样的条件了。
但这只是一个良好的开始而已,实际业务中我们很可能用像 {数量}*{单价}>{值} 或是 {单价}*(1-{折扣}/100)>{值} 这样的条件,那么如何实现呢?
 
【因子、算式抽象过程】
是时候对我们的设计进行抽象了,我们将参与表达式计算或条件比较的元素都定义为因子,字段、常量都是具体的因子类型,两个因子的数学运算称为一个算式。
那么我们该怎么实现复杂算式的表达呢?
我们可以将算式定义为一种特定类型的因子,地位与字段、常量平级,这样算式中就可以包含子算式、字段或常量。如下图:
 
算式就可以被抽象为两个因子之间以算术运算符连接的关系:{因子}.算术运算({因子})。
 
算式以左子树优先二叉树表式为:
 
这样一来,我们就可以很方便的表示如前面提到的{单价}*(1-{折扣}/100)这样的算式了:
 
OK,有了算式的设计,我们可以表达因子间复杂的计算了,下面我们开始对条件进行设计。
有了前面的经验,我们的设计会顺利很多,我们将条件抽象为两个因子的关系运算,这是水到渠成的事。那么该怎样设计多个条件的组合呢?
 
如果大家对前面因子的抽象过程融会贯通了的话,要做出这个设计并不难,不妨停下来先想想你会怎么设计实现。
【组合条件的实现】
简单的条件以左子树优先的二叉树表示为:
 
两个条件的组合定义为一个新类"条件对",以左子树优先的二叉树表示为:
"条件对"将对左条件和右条件执行指定的逻辑运算(AND/OR/NOT),因为左(右)条件本身又可以为条件对,所以可以满足复杂的条件组合。
 
下面我们来定义一个简单的查询

查询对象:订单

查询条件:订单编号以”PO”打头 且 总订购金额/总订购数量(即平均单价)>=5500的订单

 
【对于关联实体(表)的查询】
我们经常会用到诸如找出某个供应商的订单或是订购了某类产品的订单,我们要获取的是订单对象,但条件针对的是订单对象的关联对象,我们该怎样满足这样的条件查询呢?
我能想到是首先对字段因子进行重构,字段因子应不仅能表达其字段名称还要能够表达完整路径(如订单.订购项.产品.编码),如此我们就便能这样表示"包含有编码以A开头的产品订购项的订单":

{订单.订购项.产品.编码}.StartsWith("A")
这样在编译器编译查询对象时,将字段的完整路径逐级展开进行解析,生成相应的SQL脚本或是Linq语句即可实现关联查询。

 

下面我们来定义两个稍微复杂的查询

查询对象:订单

查询条件:供应商编号以”S”打头 且 存在订购明细中单价*订单折扣(即折后单价)>=5000的订单

查询对象:订单

查询条件:({订单编号}以”PO”开头 或 {订单日期}不大于等于2014-1-1) 且 存在产品编码为”A1”的产品订购记录 且 订购明细中各项订购数量小于订单总订购数量

 

【写在最后】

博文除了图片以外绝大部分文字内容都是我在上下班乘坐地铁或公交时在手机上完成的,写作不昜,如果对你还有点用处或启发的话,望不吝点,谢谢!

 

通用查询实现方案(可用于DDD)[附源码] -- 设计思路的更多相关文章

  1. (原创)通用查询实现方案(可用于DDD)[附源码] -- 设计思路

    [声明] 写作不易,转载请注明出处(http://www.cnblogs.com/wiseant/p/3988592.html).   [系列文章] 通用查询实现方案(可用于DDD)[附源码] -- ...

  2. (原创)通用查询实现方案(可用于DDD)[附源码] -- 简介

    [声明] 写作不易,转载请注明出处(http://www.cnblogs.com/wiseant/p/3985353.html).   [系列文章] 通用查询实现方案(可用于DDD)[附源码] -- ...

  3. 通用查询实现方案(可用于DDD)[附源码] -- 简介

    原文:通用查询实现方案(可用于DDD)[附源码] -- 简介 [声明] 写作不易,转载请注明出处(http://www.cnblogs.com/wiseant/p/3985353.html).   [ ...

  4. python多线程爬取-今日头条的街拍数据(附源码加思路注释)

    这里用的是json+re+requests+beautifulsoup+多线程 1 import json import re from multiprocessing.pool import Poo ...

  5. 开源方案搭建可离线的精美矢量切片地图服务-8.mapbox 之sprite大图图标文件生成(附源码)

    项目成果展示(所有项目文件都在阿里云的共享云虚拟主机上,访问地图可以会有点慢,请多多包涵). 01:中国地图:http://test.sharegis.cn/mapbox/html/3china.ht ...

  6. 【转】.NET(C#):浅谈程序集清单资源和RESX资源 关于单元测试的思考--Asp.Net Core单元测试最佳实践 封装自己的dapper lambda扩展-设计篇 编写自己的dapper lambda扩展-使用篇 正确理解CAP定理 Quartz.NET的使用(附源码) 整理自己的.net工具库 GC的前世与今生 Visual Studio Package 插件开发之自动生

    [转].NET(C#):浅谈程序集清单资源和RESX资源   目录 程序集清单资源 RESX资源文件 使用ResourceReader和ResourceSet解析二进制资源文件 使用ResourceM ...

  7. 日志组件Log2Net的介绍和使用(附源码开源地址)

    Log2Net是一个用于收集日志到数据库或文件的组件,支持.NET和.NetCore平台. 此组件自动收集系统的运行日志(服务器运行情况.在线人数等).异常日志.程序员还可以添加自定义日志. 该组件支 ...

  8. Cesium专栏-填挖方分析(附源码下载)

    Cesium 是一款面向三维地球和地图的,世界级的JavaScript开源产品.它提供了基于JavaScript语言的开发包,方便用户快速搭建一款零插件的虚拟地球Web应用,并在性能,精度,渲染质量以 ...

  9. C#进阶系列——一步一步封装自己的HtmlHelper组件:BootstrapHelper(三:附源码)

    前言:之前的两篇封装了一些基础的表单组件,这篇继续来封装几个基于bootstrap的其他组件.和上篇不同的是,这篇的有几个组件需要某些js文件的支持. 本文原创地址:http://www.cnblog ...

随机推荐

  1. 在AutoLyout中动态获得cell的高度 和 autoLyout中的小随笔

    autoLyout中动态获得cell的高度和autoLyout小总结 一.在autoLyout中通过动态的方式来获取cell 的方式呢? 1.       在布局时候要有对于cell中contentV ...

  2. 捕捉到来自宇宙深空的神奇X-射线信号

    请看下图: 这是专门用于捕捉X-射线信号的航天望远镜,约有5吨重,执行轨道距离地面大约有5万多公里.6月24日,美国宇航局NASA宣布,这台航天望远镜从银河系深处捕捉到一种波长非常特殊的神奇X-射线信 ...

  3. 封装一个ViewPager真正的实现图片无限循环滚动带导航点

    效果图: 大家在写项目的过程中常常会碰到须要实现Viewpager里面载入几张图片来循环自己主动轮播的效果,假设不封装一下的话代码分散在activity里面会显得非常乱.并且也不利于我们下次复用,所以 ...

  4. BZOJ 2424 DP OR 费用流

    思路: 1.DP f[i][j]表示第i个月的月底 还剩j的容量 转移还是相对比较好想的-- f[i][j+1]=min(f[i][j+1],f[i][j]+d[i]); if(j>=u[i+1 ...

  5. Access-Control-Allow-Origin 如何设置多个值呢

    需求就是多个网站请求同一个api服务器和这里一样https://segmentfault.com/q/10... 我不是做后端的,但是我们后端不知道怎么设置,在web.config里设置了一下 < ...

  6. Bayes++ Library入门学习之熟悉UKF相关类

    UKF-SLAM是一种比较流行SLAM方案.相比EKF-SLAM,UKF利用unscented transform代替了EKF的线性化趋近,因而具有更高的精度.Bayes++库中的unsFlt.hpp ...

  7. SQL_触发器学习

    --触发器学习-------------------------------------------------------------------------------after 触发器----- ...

  8. Java调用Python遇到的一系列问题与解决方案

    首先,百度了几个方法 1.用jython里的一个jar包,jython.jar,里面封装了一个专门调用Python的类, 但是不知道为什么我用Java一调用就报错,因此放弃.   2.用runtime ...

  9. phpstorm10安装并汉化

    一.下载phpstorm 下载地址:https://pan.baidu.com/s/1R64ZROVP1ljGbYfCwWjwxA 二.一直点击下一步安装即可 注意:第3步的时候选择一下支持的后缀 三 ...

  10. PHP 数组转字符串,字符串转数组

    explode将字符串分割为数组: $str = explode( ',',$str); 第一个参数为字符串的分界符,例如1,2,3,4. 第二个是需要分割的数组 分割后就是 array( 1 , 2 ...