主頁 > 軟體設計 > 【實踐篇】手把手教你落地DDD

【實踐篇】手把手教你落地DDD

2023-05-29 13:07:30 軟體設計

1. 前言

常見的DDD實作架構有很多種,如經典四層架構、六邊形(配接器埠)架構、整潔架構(Clean Architecture)、CQRS架構等,架構無優劣高下之分,只要熟練掌握就都是合適的架構,本文不會逐個去講解這些架構,感興趣的讀者可以自行去了解,

本文將帶領大家從日常的三層架構出發,精煉推匯出我們自己的應用架構,并且將這個應用架構實作為Maven Archetype,最后使用我們Archetype創建一個簡單的CMS專案作為本文的落地案例,

需要明確的是,本文只是給讀者介紹了DDD應用架構,還有許多概念沒有涉及,例如物體、值物件、聚合、領域事件等,如果讀者對完整落地DDD感興趣,可以到本文最后了解更多,

2. 應用架構演化

我們很多專案是基于三層架構的,其結構如圖:

我們說三層架構,為什么還畫了一層 Model 呢?因為 Model 只是簡單的 Java Bean,里面只有資料庫表對應的屬性,有的應用會將其單獨拎出來作為一個
Maven Module,但實際上可以合并到 DAO 層,

接下來我們開始對這個三層架構進行抽象精煉,

2.1 第一步、資料模型與DAO層合并

為什么資料模型要與DAO層合并呢?

首先,資料模型是貧血模型,資料模型中不包含業務邏輯,只作為裝載模型屬性的容器;

其次,資料模型與資料庫表結構的欄位是一一對應的,資料模型最主要的應用場景就是DAO層用來進行 ORM,給 Service 層回傳封裝好的資料模型,供Service 獲取模型屬性以執行業務;

最后,資料模型的 Class 或者屬性欄位上,通常帶有 ORM 框架的一些注解,跟DAO層聯系非常緊密,可以認為資料模型就是DAO層拿來查詢或者持久化資料的,資料模型脫離了DAO層,意義不大,

2.2 第二步、Service層抽取業務邏輯

下面是一個常見的 Service 方法的偽代碼,既有快取、資料庫的呼叫,也有實際的業務邏輯,整體過于臃腫,要進行單元測驗更是無從下手,

public class Service {

    @Transactional
    public void bizLogic(Param param) {

        checkParam(param);//校驗不通過則拋出自定義的運行時例外

        Data data = https://www.cnblogs.com/jingdongkeji/archive/2023/05/29/new Data();//或者是mapper.queryOne(param);

        data.setId(param.getId());

        if (condition1 == true) {
            biz1 = biz1(param.getProperty1());
            data.setProperty1(biz1);
        } else {
            biz1 = biz11(param.getProperty1());
            data.setProperty1(biz1);
        }

        if (condition2 == true) {
            biz2 = biz2(param.getProperty2());
            data.setProperty2(biz2);
        } else {
            biz2 = biz22(param.getProperty2());
            data.setProperty2(biz2);
        }

        //省略一堆set方法
        mapper.updateXXXById(data);
    }
}

這是典型的事務腳本的代碼:先做引數校驗,然后通過 biz1、biz2 等子方法做業務,并將其結果通過一堆 Set 方法設定到資料模型中,再將資料模型更新到資料庫,

由于所有的業務邏輯都在 Service 方法中,造成 Service 方法非常臃腫,Service 需要了解所有的業務規則,并且要清楚如何將基礎設施串起來,同樣的一條規則,例如if(condition1=true),很有可能在每個方法里面都出現,

專業的事情就該讓專業的人干,既然業務邏輯是跟具體的業務場景相關的,我們想辦法把業務邏輯提取出來,形成一個模型,讓這個模型的物件去執行具體的業務邏輯,這樣Service方法就不用再關心里面的 if/else 業務規則,只需要通過業務模型執行業務邏輯,并提供基礎設施完成用例即可,

將業務邏輯抽象成模型,這樣的模型就是領域模型,

要操作領域模型,必須先獲得領域模型,但此時我們先不管領域模型怎么得到,假設是通過loadDomain方法獲得的,通過 Service方法的入參,我們呼叫loadDomain方法得到一個模型,我們讓這個模型去做業務邏輯,最后執行的結果也都在模型里,我們再將模型回寫資料庫,當然,怎么寫資料庫的我們也先不管,假設是通過saveDomain方法,

Service層的方法經過抽取之后,將得到如下的偽代碼:

public class Service {

    public void bizLogic(Param param) {

        //如果校驗不通過,則拋一個運行時例外
        checkParam(param);
        //加載模型
        Domain domain = loadDomain(param);
        //呼叫外部服務取值
	    SomeValue someValue=https://www.cnblogs.com/jingdongkeji/archive/2023/05/29/this.getSomeValueFromOtherService(param.getProperty2());
        //模型自己去做業務邏輯,Service不關心模型內部的業務規則
        domain.doBusinessLogic(param.getProperty1(), someValue);
        //保存模型
        saveDomain(domain);
    }
}

根據代碼,我們已經將業務邏輯抽取出來了,領域相關的業務規則封閉在領域模型內部,此時 Service方法非常直觀,就是獲取模型、執行業務邏輯、保存模型,再協調基礎設施完成其余的操作,

抽取完領域模型后,我們工程的結構如下圖:

2.3 第三步、維護領域物件生命周期

在上一步中,loadDomainsaveDomain 這兩個方法還沒有得到討論,這兩個方法跟領域物件的生命周期息息相關,

關于領域物件的生命周期的詳細知識,讀者可以自行學習了解,

不管是 loadDomain 還是 saveDomain,我們一般都要依賴于資料庫,所以這兩個方法對應的邏輯,肯定是要跟 DAO 產生聯系的,

保存或者加載領域模型,我們可以抽象成一種組件,通過這種組件進行封裝模型加載、保存的操作,這種組件就是Repository,

注意,Repository 是對加載或者保存領域模型(這里指的是聚合根,因為只有聚合根才會有Repository)的抽象,必須對上層屏蔽領域模型持久化的細節,因此其方法的入參或者出參,一定是基本資料型別或者領域模型,不能是資料庫表對應的資料模型,

以下是 Repository 的偽代碼:

public interface DomainRepository {

    void save(AggregateRoot root);

    AggregateRoot load(EntityId id);
}

接下來我們要考慮在哪里實作DomainRepository,既然 DomainRepository 與底層資料庫有關聯,但是我們現在 DAO 層并沒有引入 Domain 這個包,DAO 層自然無法提供 DomainRepository的實作,我們初步考慮是不是可以將 DomainRepository 實作在 Service 層,

但是,如果我們在 Service 中實作DomainRepository,勢必需要在 Service 層操作資料模型:查詢出來資料模型再封裝為領域模型、或者將領域模型轉為資料模型再通過ORM 保存,這個程序不該是 Service 層關心的,

因此,我們決定在 DAO 層直接引入 Domain 包,并在 DAO 層提供 DomainRepository 介面的實作,DAO 層查詢出資料模型之后,封裝成領域模型供DomainRepository 回傳,

這樣調整之后, DAO 層不再向 Service 回傳資料模型,而是回傳領域模型,這就隱藏了資料庫互動的細節,我們也把DAO層換個名字稱之為Repository,

現在,我們專案的架構圖是這樣的了:

由于資料模型屬于貧血模型,自身沒有業務邏輯,并且只有Repository這個包會用到,因此我們將之合并到Repository中,接下來不再單獨列舉,

2.4 第四步、泛化抽象

在第三步中,我們的架構圖已經跟經典四層架構非常相似了,我們再對某些層進行泛化抽象,

  • Infrastructure

Repository 倉儲層其實屬于基礎設施層,只不過其職責是持久化和加載聚合,所以,我們將 Repository層改名為 infrastructure-persistence,可以理解為基礎設施層持久化包,

之所以采取這種 infrastructure-XXX 的格式進行命名,是由于 Infrastructure 可能會有很多的包,分別提供不同的基礎設施支持,

例如:一般的專案,還有可能需要引入快取,我們就可以再加一個包,名字叫infrastructure-cache

對于外部的呼叫,DDD中有防腐層的概念,將外部模型通過防腐層進行隔離,避免污染本地背景關系的領域模型,我們使用入口(Gateway)來封裝對外部系統或資源的訪問(詳細見《企業應用架構模式》,18.1入口(Gateway)),因此將對外呼叫這一層稱之為infrastructure-gateway

注意:Infrastructure 層的門面介面都應先在Domain 層定義,其方法的入參、出參,都應該是領域模型(物體、值物件)或者基本型別,

  • User Interface

Controller 層其實就是用戶介面層,即 User Interface 層,我們在專案簡稱 ui,當然了可能很多開發者會覺得叫UI好像很別扭,認為 UI就是 UI 設計師設計的圖形界面,

Controller 層的名字有很多,有的叫 Rest,有的叫 Resource,考慮到我們這一層不只是有 Rest 介面,還可能還有一系列 Web相關的攔截器,所以我一般稱之為 Web,因此,我們將其改名為 ui-web,即用戶介面層的 Web 包,

同樣,我們可能會有很多的用戶介面,但是他們通過不同的協議對外提供服務,因而被劃分到不同的包中,

我們如果有對外提供的 RPC服務,那么其服務實作類所在的包就可以命名為 ui-provider

有時候引入某個中間件會同時增加 Infrastructure 和 User Interface,

例如,如果引入 Kafka 就需要考慮一下,如果是給 Service 層提供呼叫的,例如邏輯執行完發送訊息通知下游,那么我們再加一個包infrastructure-publisher;如果是消費 Kafka 的訊息,然后呼叫 Service 層執行業務邏輯的,那么就可以命名為 ui-subscriber

  • Application

至此,Service 層目前已經沒有業務邏輯了,業務邏輯都在 Domain 層去執行了,Service 只是協調領域模型、基礎設施層完成業務邏輯,

所以,我們把 Service 層改名為 Application Service 層,

經過第四步的抽象,其架構圖為:

2.5 第五步、完整的包結構

我們繼續對第四步中出現的包進行整理,此時還需要考慮一個問題,我們的啟動類應該放在哪里?

由于有很多的 User Interface,所以啟動類放在任意一個User Interface中都不合適,放置在Application Service中也不合適,因此,啟動類應該存放在單獨的模塊中,又因為 application這個名字被應用層占用了,所以將啟動類所在的模塊命名為 launcher,一個專案可以存在多個launcher,按需參考User Interface,

加入啟動包,我們就得到了完整的 maven 包結構,

包結構如圖所示:

至此,DDD 專案的整體結構基本講完了,

2.6 精煉后的思考

在經過前面五步精煉得到這個架構圖中,經典四層架構的四層都出現了,而且長得跟六邊形架構也很像,這是為什么呢?

其實,不管是經典四層架構、還是六邊形架構,亦或者整潔架構,都是對系統應用的描述,也許描述的側重點不一樣,但是描述的是同一個事物,既然描述的是同一個事物,長得像才是理所當然的,不可能只是換一個描述方式,系統就從根本上發生了改變,

對于任何一個應用,都可以看成“輸入-處理-輸出”的程序,

“輸入”環節:通過某種協議對外暴露領域的能力,這些協議可能是 REST、可能是 RPC、可能是 MQ 的訂閱者,也可能是WebSocket,也可能是一些任務調度的 Task;

”處理“環節:處理環節是整個應用的核心,代表了應用具備的核心能力,是應用的價值所在,應用在這個環節執行業務邏輯,貧血模型由Service執行業務處理,充血模型則是由模型進行業務處理,

“輸出”環節,業務邏輯執行完成之后將結果輸出到外部,

不管我們采用的什么架構,其描述的應用的核心都是這個程序,不必生搬硬套非得用什么應用架構,

正如《金剛經》所言:一切有為法,如夢幻泡影,如露亦如電,應作如是觀;凡所有相,皆是虛妄;若見諸相非相,即見如來,

3. ddd-archetype

3.1 Maven Archetype介紹

Maven Archetype是一個Maven插件,可以幫助開發人員快速創建專案的基礎結構,大大減少開發人員在創建專案時所需的時間和精力,并且可以確保專案結構的一致性和可重用性,從而提高代碼質量和可維護性,

我們在介紹DDD應用架構時,對專案的結構進行了介紹,我們將專案分為多個Maven Module,如果每個專案都手工創建一次,是比較繁瑣的作業,也不利專案結構的統一,

我們使用Maven Archetype創建DDD專案初始化的腳手架,使其在初始化時完整實作上文第五步的應用架構,

3.2 ddd-archetype的使用

3.2.1 專案介紹

ddd-archetype是一個Maven Archetype的原型工程,我們將其克隆到本地之后,可以安裝為Maven Archetype,幫助我們快速創建DDD專案腳手架,

專案鏈接:

https://github.com/feiniaojin/ddd-archetype

3.2.2 安裝程序

以下將以IDEA為例展示ddd-archetype的安裝使用程序,主要程序是:

克隆專案-->archetype:create-from-project-->install-->archetype:crawl

3.2.3 克隆專案

將專案克隆到本地:

git clone https://github.com/feiniaojin/ddd-archetype.git

直接使用主分支即可,然后使用IDEA打開該專案

3.2.4 archetype:create-from-project

配置打開IDEA的run/debug configurations視窗,如下:

選擇add new configurations,彈出以下視窗:

其中,上圖中1~4各個標識的值為:

標識1 - 選擇"+"號;

標識2 - 選擇"Maven";

標識3 - 命令為:

archetype:create-from-project -Darchetype.properties=archetype.properties

注意,在IDEA中添加的命令默認不需要加mvn

標識4 - 選擇ddd-archetype的根目錄

以上配置完成后,點擊執行該命令,

3.2.5 install

上一步執行完成且無報錯之后,配置install命令,

其中,上圖中1~2各個標識的值為:

標識1 - 值為install

標識2 - 值為上一步運行的結果,路徑為:

ddd-archetype/target/generated-sources/archetype

install配置完成之后,點擊執行,

3.2.6 archetype:crawl

install執行完成且無報錯,接著配置archetype:crawl命令,

其中,標識1中的值為:

archetype:crawl

配置完成,點擊執行即可,

3.3 使用ddd-archetype初始化專案

  • 創建專案時,點擊manage catalogs
  • 將本地的maven私服中的archetype-catalog.xml加入到catalogs中:

添加成功,如下:

  • 創建專案時,選擇本地archetype-catalog,并且選擇ddd-archetype,填入專案資訊并創建專案:
  • 專案創建完成后:

4. 代碼案例

本文提供了配套的代碼案例,該案例使用DDD和本文的應用架構實作了簡單的CMS系統,案例專案采用前后端分離的方式,因此有后端和前端兩個代碼庫,

4.1 后端

后端專案使用本文的ddd-archetype創建,實作了部分CMS的功能,并落地部分DDD的概念,

GitHub鏈接:https://github.com/feiniaojin/ddd-example-cms

實作的DDD概念有:物體、值物件、聚合根、Factory、Repository、CQRS,

技術堆疊:

  • Spring Boot
  • H2記憶體資料庫
  • Spring Data JDBC

無外部中間件依賴 ,clone到本地即可編譯運行,非常方便,

4.2 前端

前端專案基于vue-element-admin開發,詳細安裝方式見代碼庫的README,

GitHub鏈接:https://github.com/feiniaojin/ddd-example-cms-front

4.3 運行截圖

5. 總結以及進一步學習

本文通過對貧血三層架構進行精煉,推匯出適合我們落地的應用架構,并且將之實作為Maven Archetype以應用到實際開發,然而應用架構只是落地DDD的一個知識點,要完整落地DDD還必須體系化地掌握限界背景關系、背景關系映射、充血模型、物體、值物件、領域服務、Factory、Repository等知識點,

作者:京東物流 覃玉杰

內容來源:京東云開發者社區

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/553710.html

標籤:其他

上一篇:【實踐篇】手把手教你落地DDD

下一篇:返回列表

標籤雲
其他(159919) Python(38178) JavaScript(25462) Java(18146) C(15232) 區塊鏈(8268) C#(7972) AI(7469) 爪哇(7425) MySQL(7214) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5873) 数组(5741) R(5409) Linux(5344) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4578) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2434) ASP.NET(2403) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) .NET技术(1977) 功能(1967) Web開發(1951) HtmlCss(1949) C++(1925) python-3.x(1918) 弹簧靴(1913) xml(1889) PostgreSQL(1878) .NETCore(1862) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【實踐篇】手把手教你落地DDD

    本文通過對貧血三層架構進行精煉,推匯出適合我們落地的應用架構,并且將之實作為Maven Archetype以應用到實際開發,然而應用架構只是落地DDD的一個知識點,要完整落地DDD還必須體系化地掌握限界背景關系、背景關系映射、充血模型、物體、值物件、領域服務、Factory、Repository等知識點... ......

    uj5u.com 2023-05-29 13:07:30 more
  • 【實踐篇】手把手教你落地DDD

    本文通過對貧血三層架構進行精煉,推匯出適合我們落地的應用架構,并且將之實作為Maven Archetype以應用到實際開發,然而應用架構只是落地DDD的一個知識點,要完整落地DDD還必須體系化地掌握限界背景關系、背景關系映射、充血模型、物體、值物件、領域服務、Factory、Repository等知識點... ......

    uj5u.com 2023-05-29 13:06:36 more
  • 系統設計:從零用戶擴展到百萬用戶

    設計一個支持百萬用戶的系統是具有挑戰性的,這是一段需要不斷改進和不斷提升的旅程。在本章中,我們將構建一個支持單個用戶的系統,并逐漸擴展以服務于數百萬用戶。閱讀本章后,您將掌握一些技巧,幫助您解決系統設計面試問題。 > AI不會取代你,使用AI的人會。歡迎關注我的公眾號:更AI。以程式員的視角來看AI ......

    uj5u.com 2023-05-29 09:14:41 more
  • 命令模式(Command Pattern)

    ### 命令模式(Command Pattern) #### 一、定義 命令模式(Command Pattern)是一種資料驅動的設計模式,它屬于行為型模式。請求以命令的形式包裹在物件中,并傳給呼叫物件。呼叫物件尋找可以處理該命令的合適的物件,并把該命令傳給相應的物件,該物件執行命令。 將一個請求封 ......

    uj5u.com 2023-05-29 09:14:16 more
  • 命令模式(Command Pattern)

    ### 命令模式(Command Pattern) #### 一、定義 命令模式(Command Pattern)是一種資料驅動的設計模式,它屬于行為型模式。請求以命令的形式包裹在物件中,并傳給呼叫物件。呼叫物件尋找可以處理該命令的合適的物件,并把該命令傳給相應的物件,該物件執行命令。 將一個請求封 ......

    uj5u.com 2023-05-29 09:08:55 more
  • 系統設計:從零用戶擴展到百萬用戶

    設計一個支持百萬用戶的系統是具有挑戰性的,這是一段需要不斷改進和不斷提升的旅程。在本章中,我們將構建一個支持單個用戶的系統,并逐漸擴展以服務于數百萬用戶。閱讀本章后,您將掌握一些技巧,幫助您解決系統設計面試問題。 > AI不會取代你,使用AI的人會。歡迎關注我的公眾號:更AI。以程式員的視角來看AI ......

    uj5u.com 2023-05-29 09:02:21 more
  • 基于Expression Lambda運算式樹的通用復雜動態查詢構建器——《

    還在一行一行地手擼查詢代碼嗎?有沒有想過全自動的,通用的,免寫代碼的動態查詢?上一篇簡略講了如何根據前面設計的查詢描述器構造出可執行的運算式的原理,本篇來講講如何用C#代碼實作俄羅斯套娃般的多層嵌套查詢Expression Lambda運算式的動態自動構建。 ......

    uj5u.com 2023-05-28 08:29:44 more
  • 基于Expression Lambda運算式樹的通用復雜動態查詢構建器——《

    還在一行一行地手擼查詢代碼嗎?有沒有想過全自動的,通用的,免寫代碼的動態查詢?上一篇簡略講了如何根據前面設計的查詢描述器構造出可執行的運算式的原理,本篇來講講如何用C#代碼實作俄羅斯套娃般的多層嵌套查詢Expression Lambda運算式的動態自動構建。 ......

    uj5u.com 2023-05-28 08:29:16 more
  • 基于Expression Lambda運算式樹的通用復雜動態查詢構建器——《

    還在手擼查詢代碼嗎?有沒有想過全自動的,通用的,免寫代碼的動態查詢?上一篇簡略講了如何把查詢條件用代碼描述出來,本篇接繼來講講,如何根據前面設計好查詢描述器構造出可執行的運算式。 ......

    uj5u.com 2023-05-27 07:48:27 more
  • 基于Expression Lambda運算式樹的通用復雜動態查詢構建器——《

    還在手擼查詢代碼嗎?有沒有想過全自動的,通用的,免寫代碼的動態查詢?上一篇簡略講了如何把查詢條件用代碼描述出來,本篇接繼來講講,如何根據前面設計好查詢描述器構造出可執行的運算式。 ......

    uj5u.com 2023-05-27 07:47:57 more