前一篇「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
以上
沒有留言:
張貼留言