原文:通用查询实现方案(可用于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. POJ 3074 Sudoku DLX精确覆盖

    DLX精确覆盖.....模版题 Sudoku Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8336   Accepted: ...

  2. UTF8有很明显的特征:如果最高字节为0,则表示一个英文字符(与ASCII完全相同)。如果有2个以上1,表示是首个字节。如果最高位是10,则表示一个中间字节。

    摘自<Qt中的C++技术.pdf> page 33

  3. List of content management systems

    https://en.wikipedia.org/wiki/List_of_content_management_systems Microsoft ASP.NET Name Platform Sup ...

  4. 安卓开发,adb shell 调试sqlite3数据库

    安卓开发,adb shell 调试sqlite3数据库 在安卓中创建了sqlite3数据库,想要调试怎么办? 通过adb shell来进行查看. 第一步,将adb加入到系统变量中. 这样就可以在命令行 ...

  5. NET下Assembly的加载过程

    NET下Assembly的加载过程 最近在工作中牵涉到了.NET下的一个古老的问题:Assembly的加载过程.虽然网上有很多文章介绍这部分内容,很多文章也是很久以前就已经出现了,但阅读之后发现,并没 ...

  6. 6.CPU调度

    总论:所有的程序都是CPU和I/O等待交替执行 CPU调度器的操作时机 调用CPU调度器的时机,通常发生在 某一进程从执行状态转化为等待状态 某一进程从执行状态转化为就绪状态 某一进程从等待状态转为就 ...

  7. 验证备份集-使用DBVERIFY工具

    DBVERIFY确认备份集是否存在坏块 验证TEST03.DBF 文件的是否存在坏块 C:\Documents and Settings\Administrator>dbv file=D:\or ...

  8. Cordova Android项目如何做代码混淆

    我想修改build.gradle配置 可是这个文件明确写了// GENERATED FILE! DO NOT EDIT!可是还是试了试: if (cdvReleaseSigningProperties ...

  9. Orientdb基本操作

    https://blog.csdn.net/clj198606061111/article/details/82314459

  10. Python3基础笔记--生成器

    目录: 一.列表生成器 二.生成器 三.迭代器 一.列表生成器 a = [x for x in range(10)] b= [y*2 for y in range(10)] def f(n) retu ...