資料傳輸物件(data transfer objects)用於應用層和展現層的資料傳輸。
展現層傳入資料傳輸物件(dto)呼叫乙個應用服務方法,接著應用服務通過領域物件執行一些特定的業務邏輯並且返回dto給展現層。這樣展現層和領域層被完全分離開了。在具有良好分層的應用程式中,展現層不會直接使用領域物件(倉庫,實體)。
為每個應用服務方法建立dto看起來是一項乏味耗時的工作。但如果你正確使用它們,這將會解救你的專案。為啥呢?
(1)抽象領域層 (abstraction of domain layer)
在展現層中資料傳輸物件對領域物件進行了有效的抽象。這樣你的層(layers)將被恰當的隔離開來。甚至當你想要完全替換展現層時,你還可以繼續使用已經存在的應用層和領域層。反之,你可以重寫領域層,修改資料庫結構,實體和orm框架,但並不需要對展現層做任何修改,只要你的應用層沒有發生改變。
(2)資料隱藏 (data hiding)
abp對資料傳輸物件提供了強大的支援。它提供了一些相關的(conventional)型別 & 介面並對dto命名和使用約定提供了建議。當你像這裡一樣使用dto,abp將會自動化一些任務使你更加輕鬆。
乙個例子 (example)
讓我們來看乙個完整的例子。我們相要編寫乙個應用服務方法根據name來搜尋people並返回people列表。person實體**如下:
public
class person : entity
public
virtual
string emailaddress
public
virtual
string password
}
首先,我們定義乙個應用服務介面:
public
abp建議命名input/ouput
物件類似於methodnameinput/methodnameoutput
,對於每個應用服務方法都需要將input和output進行分開定義。甚至你的方法只接收或者返回乙個值,也最好建立相應的dto型別。這樣,你的**才會更具有擴充套件性,你可以新增更多的屬性而不需要更改方法的簽名,這並不會破壞現有的客戶端應用。
當然,方法返回值有可能是void,之後你新增乙個返回值並不會破壞現有的應用。如果你的方法不需要任何引數,那麼你不需要定義乙個input dto。但是建立乙個input dto可能是個更好的方案,因為該方法在將來有可能會需要乙個引數。當然是否建立這取決於你。
input和output dto型別定義如下:
public
class searchpeopleinput
}public
class searchpeopleoutput
}public
class persondto : entitydto
public
string emailaddress
}
驗證:作為約定,input dto實現iinputdto 介面,output dto實現ioutputdto介面。當你宣告iinputdto引數時, 在方法執行前abp將會自動對其進行有效性驗證。這類似於asp.net mvc驗證機制,但是請注意應用服務並不是乙個控制器(controller)。abp對其進行攔截並檢查輸入。檢視dto 驗證(dto validation)文件獲取更多資訊。
entitydto是乙個簡單具有與實體相同的id屬性的簡單型別。如果你的實體id不為int型你可以使用它泛型版本。entitydto也實現了idto介面。你可以看到persondto
並不包含password
屬性,因為展現層並不需要它。
public
public searchpeopleoutput searchpeople(searchpeopleinput input)
).tolist();
return
new searchpeopleoutput ;
}}
我們從資料庫獲取實體,將實體轉換成dto並返回output。注意我們沒有手動檢測input的資料有效性。abp會自動驗證它。abp甚至會檢查input是否為null,如果為null則會丟擲異常。這避免了我們在每個方法中都手動檢查資料有效性。
但是你很可能不喜歡手動將person實體轉換成persondto。這真的是個乏味的工作。peson實體包含大量屬性時更是如此。
public searchpeopleoutput searchpeople(searchpeopleinput input)
persondto>();
[automap(typeof(myclass2))] //定義對映(這樣有兩種方式進行對映)
public
class myclass1
}public
class myclass2
}
接著你可以通過mapto擴充套件方法來進行對映:
var obj1 = new myclass1 ;
var obj2 = obj1.mapto(); //建立了新的myclass2物件,並將obj1.testprop的值賦值給新的myclass2物件的testprop屬性。
上面的**根據myclass1建立了新的myclass2物件。你也可以對映已存在的物件,如下所示:
var obj1 = new myclass1 ;
var obj2 = new myclass2();
obj1.mapto(obj2); //根據obj1設定obj2的屬性
abp還提供了一些輔助介面,定義了常用的標準化屬性。
ilimitedresultrequest定義了maxresultcount屬性。所以你可以在你的input dto上實現該介面來限制結果集數量。
ipagedresultrequest擴充套件了ilimitedresultrequest,它新增了skipcount屬性。所以我們在searchpeopleinput實現該介面用來分頁:
public
class searchpeopleinput : ipagedresultrequest
public
int maxresultcount
public
int skipcount
}
ERP渠道文件管理(二十四)
基本需求 用例圖 儲存過程 create procedure dbo bioerpcrmchanneldocument add documentid int,channelid int as insert into bioerpcrmchanneldocument documentid channe...
資料結構與演算法(二十四)
給定乙個陣列和滑動視窗的大小,請找出所有滑動視窗裡的最大值。例如,如果輸入陣列及滑動視窗的大小3,那麼一共存在6個滑動視窗,它們的最大值分別為 1 乙個滑動視窗可以看成乙個佇列。當視窗滑動時,處於視窗的第乙個數字被刪除,同時在視窗的末尾新增乙個新的數字。這符合佇列 先進先出 特性。2 題意 陣列中的...
二十四 mysql資料備份與還原
備份 將當前已有的資料或者記錄保留。還原 將已經保留的資料恢復到對應的表中。做備份和還原的原因 防止資料丟失 被盜 誤刪除等 保護資料記錄 資料備份還原的方式有 資料表備份 單錶資料備份 sql備份 增量備份。資料表備份 定義 不需要通過sql來備份,直接進入到資料庫資料夾複製對應的表結構及資料檔案...