背景
搞了近五年的系統開發,總是抱著一種思維模式,使用者的一個操作對應一個請求和一個事務,比如:使用者選擇了N條記錄,我就會向伺服器發生一個請求,伺服器在一個事務中進行處理。前幾天在群裡一個前輩反問:批量操作難道真的要在一個事務中?這個問題讓陷入了反思,謝謝前輩們(魏瓊東)。
DDD中有聚合的概念,一個聚合有且只有一個聚合根和一些其他實體,如:訂單聚合中,訂單是聚合根,訂單明細是聚合內的實體。因為DDD中只能操作聚合根,這篇文章就介紹聚合根的批量刪除問題。有人問聚合內的實體的刪除咋弄?聚合內實體的刪除必須伴隨著聚合根的修改(這裡不做詳細介紹)。
另外一點是需要注意的是,引入工作單元之後,批量操作和單個操作伺服器端的邏輯是不同的,如:索引驗證問題和工號生成問題(這裡不做詳細介紹)。
批量刪除思路
我目前有三種選擇,我記錄下來,然後一個一個分析:
- 傳送一個請求,伺服器一個事務。
- 傳送一個請求:伺服器N個事務。
- 傳送N個請求,伺服器N個事務。
傳送一個請求,伺服器一個事務。
這是我之前採用的思路,現在覺得非常不好,為什麼非要在一個事務中呢?如果您覺得非要在一個事務中,就告訴我一聲。
傳送一個請求:伺服器N個事務。
這種思路可以接受,不過要在伺服器端做額外的處理,如:收集哪些失敗或成功的資訊,發生給客戶端,如果我不用AJAX,我就會選擇這個方案。
傳送N個請求,伺服器N個事務。
考慮到我是AJAX程式設計,這種思路好,重分利用了客戶端。
傳送N個請求,伺服器N個事務的實現思路
思路有了,實現就不是問題了,搞個佇列排隊傳送請求就行了,當然你可以選擇並行傳送請求或分批次排隊傳送請求。
刪除的客戶端邏輯
1 /** 2 * 刪除功能。 3 * 4 * @class Delete 5 * @extends Happy.action.Action 6 * @namespace Happy.table.action 7 */ 8 Ext.define('Happy.table.action.Delete', { 9 extend: 'Happy.action.Action', 10 requires: [ 11 'Happy.server.PessimisticLockProxy', 12 'Happy.Msg', 13 'Happy.Ajax' 14 ], 15 16 DELETE_CONFIRM_TITLE: '刪除確認', 17 DELETE_CONFIRM_MSG: '確定執行刪除嗎?', 18 19 defaultConfig: { 20 itemId: 'delete', 21 iconCls: 'delete-button', 22 text: '刪除', 23 disabled: true, 24 autoEnableAndDisable: true 25 }, 26 27 /** 28 * 契約:<br/> 29 * <ul> 30 * <li>button.up('tablepanel')!==null。</li> 31 * </ul> 32 * @protect 33 * @method onClickHandler 34 * @param {Ext.button.Button} button 按鈕 35 */ 36 onClickHandler: function (button) { 37 var me = this; 38 39 var table = button.up('tablepanel'); 40 var records = table.getSelection(); 41 42 if (records.length == 0) { 43 return; 44 } 45 46 Ext.Msg.confirm(me.DELETE_CONFIRM_TITLE, me.DELETE_CONFIRM_MSG, function (btn) { 47 if (btn !== 'yes') { 48 return; 49 } 50 51 me.deleteRecords(records); 52 }); 53 }, 54 55 /** 56 * private 57 * @method deleteRecords 58 */ 59 deleteRecords: function (records) { 60 var me = this; 61 62 if (records.length == 0) { 63 Happy.Msg.showDeleteSuccess(); 64 return; 65 } 66 67 Happy.Ajax.destroy(records.shift(), { 68 success: function (record) { 69 me.deleteRecords(records); 70 }, 71 failure: function (record, operation) { 72 Happy.Msg.showDeleteFailure(operation.error); 73 } 74 }); 75 } 76 });
刪除的伺服器端邏輯
1 /// <summary> 2 /// 刪除。 3 /// </summary> 4 public ActionResult Delete(TAggregateRoot item) 5 { 6 this.CurrentCommandService.Execute(new TDeleteCommand 7 { 8 Aggregate = item 9 }); 10 11 return this.NewtonsoftJson(new 12 { 13 success = true 14 }); 15 }
效果圖
備註
這裡只是演示了批量刪除,有很多針對聚合根的批量操作都可以這麼處理。