前一篇「ASP.NET MVC 使用 jQuery EasyUI DataGrid - 多欄排序 (Multiple Column Sorting) Part.1」已經完成了多欄排序的伺服器端的程式內容,不過還是有修改的空間,所以這篇文章就接續完成需要修改的部份。
在前一篇裡有提到,在處理多欄排序時我們不使用 Dynamic Expression API 去作多欄位排序的處理,而是改用 IOrderedQueryableHelper 動態產生 IOrderedEnumerable<T>,但如果在啟用多欄排序的情況下只有做單一欄位的排序時,例如進入 Customer/Index 頁面時,DataGrid 的排序是預設對 CustomerID 進行 asc 排序,這樣的情況似乎就不需要使用 IOrderedQueryableHelper 來取得 IOrderedEnumerable<T>,所以因應這樣的情況就將單一欄位排序與多欄排序的處理做個區分。
Step.1
將原本在 CustomerService.GetJsonForGrid 方法內的程式給抽出來,
建立一個私有方法 GetMultipleColumnSortingQuery 放置剛才所抽離出來的程式,
Step.2
在之前「ASP.NET MVC 使用 jQuery EasyUI DataGrid - 排序 (Sorting)」這篇文章裡有說過,為預防傳入的 order 與 sort 值有錯誤而造成程式執行的錯誤,所以在 CustomerService 裡針對傳入的 propertyName 會檢查是否為 Customer 的屬性名稱之一。
這個部份我希望不要在程式裡直接給欄位名稱的字串,而是自動從 Entity KeyMemers 裡取得第一個 KeyMember 名稱,讓程式增加彈性,在「Entity Framework 5 - 取得 Entity 的 Property Names 與 KeyMembers」這篇文章裡就有說明過,所以在 EntityHelper.cs 增加以下的程式內容:
/// <summary>
/// Keys the members.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static List<string> KeyMembers<T>() where T : class
{
List<string> result = new List<string>();
string entityName = typeof(T).Name;
string keyMembers = EntityHelper.GetAllEntityKeyMembers()
.FirstOrDefault(x => x.Key == entityName).Value;
if (!string.IsNullOrWhiteSpace(keyMembers))
{
result = keyMembers.Split(',').ToList();
}
return result;
}
/// <summary>
/// Gets all entity key members.
/// </summary>
/// <returns></returns>
private static Dictionary<string, string> GetAllEntityKeyMembers()
{
var result = new Dictionary<string, string>();
var mw = new MetadataWorkspace(
new[] {"res://*/"},
new[] {Assembly.GetExecutingAssembly()});
var tables = mw.GetItems(DataSpace.CSpace);
foreach (var e in tables.OfType<EntityType>())
{
result.Add(e.Name, string.Join(",", e.KeyMembers));
}
return result;
}
Step.3
接著建立一個 GetSingleColumnSortingQuery 方法,用來操作單一欄位排序的 IQueryalbe<Customer> 的處理,在 GetSingleColumnSortingQuery 方法裡就會使用到 Step.2 所新增加的方法。
在資料排序處理的部份就不使用 Dynamic Expression API,而是使用 IOrderedQueryableHelper 來處理。
private IQueryable<Customer> GetSingleColumnSortingQuery(
int page,
int pageSize,
string propertyName,
string sortOrder)
{
//取得 Entity 所有的 Property 名稱
var entityPropertyNames = EntityHelper.EntityPropertyNames<Customer>();
if (!entityPropertyNames.Contains(propertyName))
{
propertyName = EntityHelper.KeyMembers<Customer>().FirstOrDefault();
}
if (!(sortOrder.Equals("asc", StringComparison.OrdinalIgnoreCase)
|| sortOrder.Equals("desc", StringComparison.OrdinalIgnoreCase)))
{
sortOrder = "asc";
}
var query = db.Customers.AsQueryable();
query = sortOrder.Equals("asc", StringComparison.OrdinalIgnoreCase)
? query.OrderBy<Customer>(propertyName)
: query.OrderByDescending<Customer>(propertyName);
query = query.Skip((page - 1) * pageSize).Take(pageSize);
return query;
}
Step.4
完成了 GetSingleColumnSortingQuery, GetMultipleColumnSortingQuery 以及增加 EntityHelper 內的程式之後,現在重新修改 CustomerService.GetJsonForGrid 裡的程式。
程式裡並不是直接拿傳進方法的 propertyName 來判斷是否為單一欄位排序或是多欄位排序,而是以處理過 propertyName 與 order 的結果來判斷,以 propertySortTuples 的資料數量來做決定,
public JArray GetJsonForGrid(
int page = 1,
int pageSize = 10,
string propertyName = "CustomerID",
string order = "asc")
{
// 取得多個排序欄位與順序的 Tuple 結果
var propertySortTuples =
EntityHelper.GetPropertySortTuples<Customer>(propertyName, order);
var query = propertySortTuples.Count().Equals(1)
? this.GetSingleColumnSortingQuery(page, pageSize, propertyName, order)
: this.GetMultipleColumnSortingQuery(page, pageSize, propertySortTuples);
JArray ja = new JArray();
foreach (var item in query)
{
var itemObject = new JObject
{
{"CustomerID", item.CustomerID},
{"CompanyName", item.CompanyName},
{"ContactName", item.ContactName},
{"ContactTitle", item.ContactTitle},
{"Address", item.Address},
{"City", item.City},
{"Region", item.Region},
{"PostalCode", item.PostalCode},
{"Country", item.Country},
{"Phone", item.Phone},
{"Fax", item.Fax}
};
ja.Add(itemObject);
}
return ja;
}
Step.5
到上一個步驟就完成了我們這一次的修改,那麼這一個步驟還需要做什麼處理呢?
在這一個步驟裡我們可以依照「ASP.NET MVC + NLog + Clutch.Diagnostics.EntityFramework 追蹤 EF 執行的 SQL Command」這一篇文章裡的內容加入 NLog 與 Clutch.Diagnostics.EntityFramework,在進入偵錯模式的時候將 Entity Framework 所產生並執行的 SQL Command 內容顯示在 Visual Studio 的「輸出」視窗內,讓我們即時觀察在單一欄位或多欄位排序處理時在資料庫所執行的 SQL Command 內。
一開始進入 Customer 頁面時,DataGrid 第一次顯示資料的預設查詢
多增加了 CompanyName 的排序欄位
將 ConmpanyName 的排序順序變更為降冪
再增加排序欄位
最後這邊提醒一下,多欄位的排序先後順序是會依據你點選 DataGrid 欄位表頭時的順序,並不是依據 DataGrid 上所顯示的欄位排列順序,以免有人會錯意而造成誤會,如果要避免讓使用者誤會的話,可以去顯示使用者點選多欄位排序時的選擇先後順序,至於這個方法就留給各位自行去實做出來啦!
延伸閱讀:
Entity Framework 5 - 取得 Entity 的 Property Names 與 KeyMembers
ASP.NET MVC + NLog + Clutch.Diagnostics.EntityFramework 追蹤 EF 執行的 SQL Command
以上
沒有留言:
張貼留言