【声明】
写作不易,转载请注明出处(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)[附源码] -- 设计思路

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

  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. C#进阶系列——一步一步封装自己的HtmlHelper组件:BootstrapHelper(三:附源码)

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

  7. 轻量级通信引擎StriveEngine —— C/S通信demo(2) —— 使用二进制协议 (附源码)

    在网络上,交互的双方基于TCP或UDP进行通信,通信协议的格式通常分为两类:文本消息.二进制消息. 文本协议相对简单,通常使用一个特殊的标记符作为一个消息的结束. 二进制协议,通常是由消息头(Head ...

  8. C#轻量级通通讯组件StriveEngine —— C/S通信开源demo(2) —— 使用二进制协议 (附源码)

    前段时间,有几个研究ESFramework通信框架的朋友对我说,ESFramework有点庞大,对于他们目前的项目来说有点“杀鸡用牛刀”的意思,因为他们的项目不需要文件传送.不需要P2P.不存在好友关 ...

  9. 【转】.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 ...

随机推荐

  1. Android IOS WebRTC 音视频开发总结(七九)-- WebRTC选择H.264的四大理由

    本文主要介绍WebRTC选择H.264的理由(我们翻译和整理的,译者:weizhenwei,校验:blacker),最早发表在[编风网] 支持原创,转载必须注明出处,欢迎关注我的微信公众号blacke ...

  2. php学习笔记

    header("Content-Type:text/html;charset=utf-8");//设置中文请求中文 $host = "localhost";// ...

  3. Lua 5.2 编译 For Windows

    body { font-family: 微软雅黑; font-size: 11pt; line-height: 1.5; } html, body { color: #000000; backgrou ...

  4. css之页面两列布局

    两列布局:左边固定,后边自适应 第一种方法:左边的div左浮动或者是绝对定位,右边的div加margin-left:左边div的宽度 html部分 <div class="left&q ...

  5. TJI读书笔记15-持有对象

    TJI读书笔记15-持有对象 总览 类型安全和泛型 Collection接口 添加元素 List 迭代器 LinkedList 栈 Set Map Queue Collection和Iterator ...

  6. HTML5 的web储存: localStorage & sessionStorage

    早期的浏览器使用cookie储存,HTML5新增web储存,包括:localStorage 和 sessiongStorage; localStorage:可以永久储存: sessionStorage ...

  7. VC++ 6.0远程调试配置

    VC开发环境之所以提供远程调试的能力,是因为有些情况下单机调试会让你崩溃掉...比如,调试GUI程序的WM_PAINT消息,因为要单步调试,所以调试器会对界面的重绘产生副作用(Heisenberg不确 ...

  8. nagios二次开发(四)---nagios监控原理和nagios架构简介

    nagios监控原理 下面根据上面摘自网络的原理图对nagios的监控原理进行一下简单的说明: 1.nagios通过nsca进行被动监控.那么什么是被动监控呢?被动监测:就是指由被监测的服务器主动上传 ...

  9. Dictionary和Hashtable的一些异同

    Dictionary和Hashtable 区别: Dictionary和Hashtable 区别 Dictionary Hashtable  支持范型 不支持 需要自己做线程同步 通过调用 Synch ...

  10. 关于设置anroid系统时间

    我最近在做一个项目需要设置android系统时间,设置android 时间往往缺少权限,看到http://blog.csdn.net/kakaxi1o1/article/details/3687278 ...