在很多時候计螺,我們在數(shù)據(jù)庫里面定義表字段和實(shí)際在頁面中展示的內(nèi)容登馒,往往是不太匹配的,頁面數(shù)據(jù)可能是多個表數(shù)據(jù)的綜合體圈纺,因此除了我們在表設(shè)計(jì)的時候考慮周到外蛾娶,還需要考慮數(shù)據(jù)展現(xiàn)的處理法褥。如果是常規(guī)的處理半等,那么需要對部分外鍵字段進(jìn)行特別的轉(zhuǎn)義處理,如果需要增加多一些字段莽囤,那么這種處理可能就相對比較麻煩一些朽缎。本文介紹如何在MVC控制器里面使用dynamic和ExpandoObject话肖,實(shí)現(xiàn)數(shù)據(jù)轉(zhuǎn)義后一體化的輸出葡幸,包括增加任意多的字段信息蔚叨。
1、數(shù)據(jù)信息的展示
一般情況下邢锯,我們在界面里面展示的信息是相對比較豐富的丹擎,盡管我們設(shè)計(jì)數(shù)據(jù)表的時候领曼,考慮的是如何精簡且避免重復(fù),但是在界面上展示的信息毁渗,往往是考慮如何讓用戶更加方便,因此可能盡可能的展示相關(guān)信息府适。
如對于這樣的場景檐春,設(shè)備信息作為主要的基礎(chǔ)信息疟暖,其相關(guān)的業(yè)務(wù)包括設(shè)備檢查田柔、設(shè)備維護(hù)硬爆、設(shè)備報(bào)修等信息,如下所示缘圈。
基于上面的數(shù)據(jù)設(shè)計(jì)糟把,我們?nèi)绻谡故驹O(shè)備檢查糊饱、設(shè)備維護(hù)颠黎、設(shè)備報(bào)修等信息的時候狭归,那么我們一般還需要展示部分的設(shè)備基礎(chǔ)信息过椎,這樣我們更容易了解整個記錄數(shù)據(jù)疚宇,但是我們在數(shù)據(jù)設(shè)計(jì)的時候,是把它們分開的间涵,因此需要在輸出到界面的時候榜揖,把它們綜合起來举哟。
我以前在《基于MVC4+EasyUI的Web開發(fā)框架經(jīng)驗(yàn)總結(jié)(9)--在Datagrid里面實(shí)現(xiàn)外鍵字段的轉(zhuǎn)義操作》介紹過一些數(shù)據(jù)轉(zhuǎn)義的處理,不過那種方式并不是比較理想的方式潜叛。本篇介紹的使用dynamic和ExpandoObject才是我理想的處理模式威兜。
我們來看看我最終通過這種方式實(shí)現(xiàn)的界面效果牡属,之后我們再來一步步介紹如何實(shí)現(xiàn)這個操作過程的扼睬。
2窗宇、數(shù)據(jù)轉(zhuǎn)義的實(shí)現(xiàn)
在上面的界面效果里面军俊,我們是基于MVC實(shí)現(xiàn)后臺的處理,在界面上利用Bootstrap進(jìn)行展示的(利用EaysUI組件也是類似的處理)担败。我們分為兩部分進(jìn)行介紹實(shí)現(xiàn)的提前,一部分是采用MVC的輸出數(shù)據(jù)泳唠,一部分是界面的展示。
1)MVC的控制器數(shù)據(jù)處理
在MVC里面勇垛,我們一般通過基類的FindWithPager進(jìn)行數(shù)據(jù)的分頁處理士鸥,基于如何在MVC控制器里面實(shí)現(xiàn)數(shù)據(jù)的分頁處理础淤,大家感興趣可以參考《基于Metronic的Bootstrap開發(fā)框架經(jīng)驗(yàn)總結(jié)(2)--列表分頁處理和插件JSTree的使用》隨筆進(jìn)行了解。
常規(guī)的做法币砂,如果是主表信息决摧,我們可以把它們簡單的輸出掌桩,如下所示姑食。
public override ActionResult FindWithPager()
{
//檢查用戶是否有權(quán)限音半,否則拋出MyDenyAccessException異常
base.CheckAuthorized(AuthorizeKey.ListKey);
string where = GetPagerCondition();
PagerInfo pagerInfo = GetPagerInfo();
List<DeviceInfo> list = baseBLL.FindWithPager(where, pagerInfo);
//Json格式的要求{total:22,rows:{}}
//構(gòu)造成Json的格式傳遞
var result = new { total = pagerInfo.RecordCount, rows = list };
return ToJsonContentDate(result);
}
也就是不需要經(jīng)過任何轉(zhuǎn)義就直接把查詢到的數(shù)據(jù)列表輸出給調(diào)用者曹鸠,由界面進(jìn)行數(shù)據(jù)的篩選處理。
如果對于上面提到的設(shè)備檢查坛善、設(shè)備維修等和設(shè)備信息相關(guān)的眠屎,我們就需要利用dynamic和ExpandoObject肆饶,把設(shè)備信息整合一起提供給界面了,具體代碼如下所示。
我們首先對查詢的記錄進(jìn)行遍歷阿宅,把每條記錄進(jìn)行轉(zhuǎn)換,如下所示蛉鹿。
List<ExpandoObject> objList = new List<ExpandoObject>();
foreach (DeviceCheckInfo info in list)
{
dynamic obj = new ExpandoObject();
注意上面我們定義了List<ExpandoObject>的列表和dynamic obj的對象妖异,這樣我們通過動態(tài)定義的對象他膳,把我們需要的字段屬性加到動態(tài)對象里面绒窑,然后放到集合里面即可些膨。
完整的分頁控制器代碼如下所示。
public override ActionResult FindWithPager()
{
//檢查用戶是否有權(quán)限肢预,否則拋出MyDenyAccessException異常
base.CheckAuthorized(AuthorizeKey.ListKey);
string where = GetPagerCondition();
PagerInfo pagerInfo = GetPagerInfo();
List<DeviceCheckInfo> list = baseBLL.FindWithPager(where, pagerInfo);
//設(shè)備編碼 所屬科室 品牌 品類 型號 設(shè)備序列號 檢查時間 處理人
List<ExpandoObject> objList = new List<ExpandoObject>();
foreach (DeviceCheckInfo info in list)
{
dynamic obj = new ExpandoObject();
DeviceInfo deviceInfo = BLLFactory<Device>.Instance.FindByCode(info.DeviceCode);
if (deviceInfo != null)
{
obj.Dept = deviceInfo.Dept;
obj.Brand = deviceInfo.Brand;
obj.Name = deviceInfo.Name;
obj.Model = deviceInfo.Model;
obj.SerialNo = deviceInfo.SerialNo;
}
obj.ID = info.ID;
obj.DeviceCode = info.DeviceCode;
obj.OperateTime = info.OperateTime;
obj.Operator = info.Operator;
objList.Add(obj);
}
//Json格式的要求{total:22,rows:{}}
//構(gòu)造成Json的格式傳遞
var result = new { total = pagerInfo.RecordCount, rows = objList };
return ToJsonContentDate(result);
}
2)界面的數(shù)據(jù)展示
上面定義了數(shù)據(jù)的獲取方式烫映,也就是我們需要任何數(shù)據(jù)都可以在MVC控制器里面窑邦,通過動態(tài)屬性的方式添加到集合對象里面冈钦,從而簡化了我們界面的處理瞧筛,我們只需要把獲得的信息展示在界面上即可导盅,非常簡便了。
界面視圖的HTML代碼如下所示
<table id="grid" class="table table-striped table-bordered table-hover" cellpadding="0" cellspacing="0" border="0" class="display" width="100%">
<thead id="grid_head">
<tr>
<!--設(shè)備編碼 所屬科室 品牌 品類 型號 設(shè)備序列號 檢查時間 處理人 -->
<th class="table-checkbox" style="width:40px"><input class="group-checkable" type="checkbox" onclick="selectAll(this)"></th>
<th>設(shè)備編碼</th>
<th>所屬科室</th>
<th>品牌</th>
<th>品類</th>
<th>型號</th>
<th>設(shè)備序列號</th>
<th>檢查時間</th>
<th>處理人</th>
<th style="width:90px">操作</th>
</tr>
</thead>
<tbody id="grid_body"></tbody>
</table>
我們綁定到界面上绢片,是通過Ajax的方式獲取數(shù)據(jù)岛琼,然后綁定顯示的槐瑞,JS代碼如下所示。
function SearchCondition(page, condition) {
//獲取Json對象集合祠挫,并生成數(shù)據(jù)顯示內(nèi)容
url = "/DeviceCheck/FindWithPager?page=" + page + "&rows=" + rows;
$.getJSON(url + "&" + condition, function (data) {
$("#totalCount").text(data.total);
$("#totalPageCount").text(Math.ceil(data.total / rows));
$("#grid_body").html("");
//<!--設(shè)備編碼 所屬科室 品牌 品類 型號 設(shè)備序列號 檢查時間 處理人 -->
$.each(data.rows, function (i, item) {
var tr = "<tr>";
tr += "<td><input class='checkboxes' type=\"checkbox\" name=\"checkbox\" value=" + item.ID + "></td>";
tr += "<td>" + item.DeviceCode + "</td>";
tr += "<td>" + item.Dept + "</td>";
tr += "<td>" + item.Brand + "</td>";
tr += "<td>" + item.Name + "</td>";
tr += "<td>" + item.Model + "</td>";
tr += "<td>" + item.SerialNo + "</td>";
tr += "<td>" + item.OperateTime + "</td>";
tr += "<td>" + item.Operator + "</td>";
tr += getActionHtml(item.ID); //獲取查看等舔、編輯软瞎、刪除操作代碼
tr += "</tr>";
$("#grid_body").append(tr);
});
//設(shè)置分頁屬性及處理
var element = $('#grid_paging');
if(data.total > 0) {
var options = {
bootstrapMajorVersion: 3,
currentPage: page,
numberOfPages: rows,
totalPages: Math.ceil(data.total / rows),
onPageChanged: function (event, oldPage, newPage) {
SearchCondition(newPage, condition); //頁面變化時觸發(fā)內(nèi)容更新
}
}
element.bootstrapPaginator(options);
} else {
element.html("");
}
});
}
這樣就最終優(yōu)雅的實(shí)現(xiàn)了我們前面介紹的界面效果了涤浇。