【聲明】
寫作不易,轉載請注明出處(
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”的產品訂購記錄 且 訂購明細中各項訂購數量小於訂單總訂購數量
【寫在最后】
博文除了圖片以外絕大部分文字內容都是我在上下班乘坐地鐵或公交時在手機上完成的,寫作不昜,如果對你還有點用處或啟發的話,望不吝點
贊,謝謝!