1. 程式人生 > >如何向OrderBy傳遞字串引數(Entity Framework)

如何向OrderBy傳遞字串引數(Entity Framework)

AppBox 是基於 FineUI 的通用許可權管理框架,包括使用者管理、職稱管理、部門管理、角色管理、角色許可權管理等模組。

Entity Framework提供的排序功能

 再來回顧一下上篇文章,載入使用者列表並進行排序資料庫分頁的程式碼

var q = DB.Users.Include(u => u.Dept);
 
// 在使用者名稱稱中搜索
string searchText = ttbSearchMessage.Text.Trim();
if (!String.IsNullOrEmpty(searchText))
{
    q = q.Where(u => u.Name.Contains(searchText) || u.ChineseName.Contains(searchText) || u.EnglishName.Contains(searchText));
}
 
// 過濾啟用狀態
if (rblEnableStatus.SelectedValue != "all")
{
    q = q.Where(u => u.Enabled == (rblEnableStatus.SelectedValue == "enabled" ? true : false));
}
 
// 在查詢新增之後,排序和分頁之前獲取總記錄數
Grid1.RecordCount = q.Count();
 
// 排列
q = q.OrderBy(u => u.Name);
 
// 資料庫分頁
q = q.Skip(Grid1.PageIndex * Grid1.PageSize).Take(Grid1.PageSize);
 
Grid1.DataSource = q;
Grid1.DataBind();

讓我們把關注點集中到排序程式碼上:

q = q.OrderBy(u => u.Name);

在FineUI實際應用中,我們一般是從表格的 SortField 中讀取排序欄位,顯然EF提供的OrderBy無法接受字串表示的排序欄位。

手工建立Lamba表示式  

據此我們可以寫出如下的程式碼:

public Expression<Func<T, To>> GetSortExpression<T, To>(String sortBy)
{
    var param = Expression.Parameter(typeof(T), "x");
    Expression expr = Expression.Property(param, sortBy);
    return Expression.Lambda<Func<T, To>>(expr, param);
}
 
 
protected IQueryable<T> Sort<T>(IQueryable<T> q, FineUI.Grid grid)
{
    string sortField = grid.SortField;
 
    if (grid.SortDirection == "ASC")
    {
        q = q.OrderBy(GetSortExpression<T, object>(sortField));
    }
    else
    {
        q = q.OrderByDescending(GetSortExpression<T, object>(sortField));
    }
 
    return q;
}

經過測試,我們發現這個方法不支援bool, int, DateTime, DateTime?型別的列排序。

經過擴充套件後的程式碼如下所示:

protected IQueryable<T> Sort<T>(IQueryable<T> q, FineUI.Grid grid)
{
    string sortField = grid.SortField;
    var propertyType = typeof(T).GetProperty(sortField).PropertyType;
 
    if (grid.SortDirection == "ASC")
    {
        if (propertyType == typeof(bool))
        {
            q = q.OrderBy(GetSortExpression<T, bool>(sortField));
        }
        else if (propertyType == typeof(int))
        {
            q = q.OrderBy(GetSortExpression<T, int>(sortField));
        }
        else if (propertyType == typeof(DateTime))
        {
            q = q.OrderBy(GetSortExpression<T, DateTime>(sortField));
        }
        else if (propertyType == typeof(DateTime?))
        {
            q = q.OrderBy(GetSortExpression<T, DateTime?>(sortField));
        }
        else
        {
            q = q.OrderBy(GetSortExpression<T, object>(sortField));
        }
    }
    else
    {
        if (propertyType == typeof(bool))
        {
            q = q.OrderByDescending(GetSortExpression<T, bool>(sortField));
        }
        else if (propertyType == typeof(int))
        {
            q = q.OrderByDescending(GetSortExpression<T, int>(sortField));
        }
        else if (propertyType == typeof(DateTime))
        {
            q = q.OrderByDescending(GetSortExpression<T, DateTime>(sortField));
        }
        else if (propertyType == typeof(DateTime?))
        {
            q = q.OrderByDescending(GetSortExpression<T, DateTime?>(sortField));
        }
        else
        {
            q = q.OrderByDescending(GetSortExpression<T, object>(sortField));
        }
    }
 
    return q;
}

但這種做法過於臃腫,有沒有更好的辦法呢?

更好的SortBy擴充套件方法  

通過對 IQueryable<T> 進行擴充套件,提供了接受類似 "Name DESC", "CreateTime", "CreateTime DESC" 引數的 SortBy 方法,更具有通用性。

原始的SortBy擴充套件方法:

public static class QueryExtensions {
    public static IQueryable<T> SortBy<T>(this IQueryable<T> source, string propertyName) {
        if (source == null) {
            throw new ArgumentNullException("source");
        }
        // DataSource control passes the sort parameter with a direction
        // if the direction is descending          
        int descIndex = propertyName.IndexOf(" DESC");
        if (descIndex >= 0) {
            propertyName = propertyName.Substring(0, descIndex).Trim();
        }
 
        if (String.IsNullOrEmpty(propertyName)) {
            return source;
        }
 
        ParameterExpression parameter = Expression.Parameter(source.ElementType, String.Empty);
        MemberExpression property = Expression.Property(parameter, propertyName);
        LambdaExpression lambda = Expression.Lambda(property, parameter);
 
        string methodName = (descIndex < 0) ? "OrderBy" : "OrderByDescending";
 
        Expression methodCallExpression = Expression.Call(typeof(Queryable), methodName,
                                            new Type[] { source.ElementType, property.Type },
                                            source.Expression, Expression.Quote(lambda));
 
        return source.Provider.CreateQuery<T>(methodCallExpression);
    }
}

不過這個方法不支援"Name ASC"形式的引數,所以我們進行了簡單的修正,修正後的SortBy擴充套件方法:

public static class QueryExtensions
{
    public static IQueryable<T> SortBy<T>(this IQueryable<T> source, string sortExpression)
    {
        if (source == null)
        {
            throw new ArgumentNullException("source");
        }
 
        string sortDirection = String.Empty;
        string propertyName = String.Empty;
 
        sortExpression = sortExpression.Trim();
        int spaceIndex = sortExpression.Trim().IndexOf(" ");
        if (spaceIndex < 0)
        {
            propertyName = sortExpression;
            sortDirection = "ASC";
        }
        else
        {
            propertyName = sortExpression.Substring(0, spaceIndex);
            sortDirection = sortExpression.Substring(spaceIndex + 1).Trim();
        }
 
        if (String.IsNullOrEmpty(propertyName))
        {
            return source;
        }
 
        ParameterExpression parameter = Expression.Parameter(source.ElementType, String.Empty);
        MemberExpression property = Expression.Property(parameter, propertyName);
        LambdaExpression lambda = Expression.Lambda(property, parameter);
 
        string methodName = (sortDirection == "ASC") ? "OrderBy" : "OrderByDescending";
 
        Expression methodCallExpression = Expression.Call(typeof(Queryable), methodName,
                                            new Type[] { source.ElementType, property.Type },
                                            source.Expression, Expression.Quote(lambda));
 
        return source.Provider.CreateQuery<T>(methodCallExpression);
    }
 
}

優化後的排序分頁程式碼

首先在頁面基類PageBase中定義排序和分頁的程式碼(使用了前面定義的 SortBy 擴充套件函式):

protected IQueryable<T> Sort<T>(IQueryable<T> q, FineUI.Grid grid)
{
    return q.SortBy(grid.SortField + " " + grid.SortDirection);
}
 
protected IQueryable<T> SortAndPage<T>(IQueryable<T> q, FineUI.Grid grid)
{
    return Sort(q, grid).Skip(grid.PageIndex * grid.PageSize).Take(grid.PageSize);
}

最終查詢使用者列表的程式碼:

var q = DB.Users.Include(u => u.Dept);
 
// 在使用者名稱稱中搜索
string searchText = ttbSearchMessage.Text.Trim();
if (!String.IsNullOrEmpty(searchText))
{
    q = q.Where(u => u.Name.Contains(searchText) || u.ChineseName.Contains(searchText) || u.EnglishName.Contains(searchText));
}
 
// 過濾啟用狀態
if (rblEnableStatus.SelectedValue != "all")
{
    q = q.Where(u => u.Enabled == (rblEnableStatus.SelectedValue == "enabled" ? true : false));
}
 
// 在查詢新增之後,排序和分頁之前獲取總記錄數
Grid1.RecordCount = q.Count();
 
// 排列和資料庫分頁
q = SortAndPage<User>(q, Grid1);
 
 
Grid1.DataSource = q;
Grid1.DataBind();

下載或捐贈AppBox

2. AppBox v3.0 是捐贈軟體,你可以通過捐贈作者來獲取AppBox v3.0的全部原始碼(http://fineui.com/donate/)。

相關推薦

如何OrderBy傳遞字串引數Entity Framework

AppBox 是基於 FineUI 的通用許可權管理框架,包括使用者管理、職稱管理、部門管理、角色管理、角色許可權管理等模組。 Entity Framework提供的排序功能  再來回顧一下上篇文章,載入使用者列表並進行排序資料庫分頁的程式碼: var q = DB.Users.Incl

【轉】在使用實體框架Entity Framework的應用中加入審計信息Audit trail跟蹤數據的變動

要求 date ted hang ng- tar () eat code 在一些比較重要的業務系統中,通常會要求系統跟蹤數據記錄的變動情況。系統要記錄什麽時間,什麽人,對那些信息進行了變動。 比較簡單的實現方式是在每個表中加入兩個字段CreatedBy和CreatedA

C#:實體框架EFentity framework

本文來自:http://www.cnblogs.com/xuf22/articles/5513283.html 一、什麼是Entity Framework     微軟官方提供的ORM工具,ORM讓開發人員節省資料庫訪問的程式碼時間,將更多的時間放到業務邏輯層程式碼上。EF提供變更跟蹤

Any與All的用法Entity Framework

AppBox 是基於 FineUI 的通用許可權管理框架,包括使用者管理、職稱管理、部門管理、角色管理、角色許可權管理等模組。 屬於某個角色的使用者列表(Any的用法) 使用Subsonic,我們有兩種方法獲取屬於某個角色的使用者列表,分別是表關聯和子查詢。 Subsonic的表關聯實現:

關聯表查詢與更新Entity Framework

AppBox 是基於 FineUI 的通用許可權管理框架,包括使用者管理、職稱管理、部門管理、角色管理、角色許可權管理等模組。 關聯表的查詢操作 使用 Include 方法,我們可以在一次資料庫查詢中將關聯表的資料一併取出。 比如查詢線上使用者列表頁面,需要在前端顯示關聯的使用者資訊,如下所

Attach陷阱Entity Framework

AppBox 是基於 FineUI 的通用許可權管理框架,包括使用者管理、職稱管理、部門管理、角色管理、角色許可權管理等模組。 Attach方法 前面我們已經多次使用Attach方法,上一次使用Attach方法修改使用者所屬部門的程式碼如下所示: if (String.IsNullOrEmp

ASP.NET網站開發--實體框架EFEntity Framework

1、什麼是Entity Framework! 它就是微軟提供的ORM工具,ORM讓開發人員節省訪問資料庫的時間,將更多的時間放在業務邏輯程式碼層中,EF提供變更追蹤,唯一性約束,惰性載入,查詢事物等!開發人員使用Linq語言對資料庫操作如同操作Object一樣省事。 2、

NHibernate與EFEntity Framework的區別

概述長久以來,程式設計師和資料庫總是保持著一種微妙的關係,在商用應用程式中,資料庫一定是不可或缺的元件,這讓程式設計師一定要為了連線與訪問資料庫而去學習 SQL 指令,至少對於我而言,我覺得這是一個很不爽的事情。因此在資訊業中有很多人都在研究如何將程式設計模型和資料庫整合在一

ajax後臺傳遞list引數

學習記錄:複習 使用ajax向後臺傳遞list引數 前臺 jsp頁面 <button onclick="login222();">測試</button> js function login222() { var l

python flask 通過ajax後臺傳遞陣列引數

ajax 像後臺傳遞引數,一般是字典的形式傳遞,但是如果字典的value的值是一個數組的話,通過request.form  獲取得到的結果是 None。這是就需要把陣列物件轉化為json字串,後臺才可

利用out關鍵字函式傳遞List引數遇到的問題

引言 今天使用out關鍵字向函式傳遞List<T>引數遇到了一點問題,做個記錄。之前只是大概瞭解out關鍵字就是作為引用傳遞。 遇到的問題 今天先寫了如下程式碼: using System; using System.Collections.Generic;

C#綜合揭祕——利用泛型與反射更新實體ADO.NET Entity Framework

自從ADO.NET Entity Framework面世以來,受到大家的熱捧,它封裝了大量程式碼生成的工具,使用者只需要建立好實體之間的關係,系統就是會為使用者自動成功了Add、Delete、CreateObject、Attach、ToList......等等方法,這些方法

JSPServlet傳遞陣列引數

今天需要做一個多選刪除功能,需要從JSP中獲取已勾選的多選框的值,傳遞到Servlet中進行刪除操作。 <input type="checkbox" name="checkProduct" value="${product.pid}"> <input ty

網站分頁功能的實現Entity Framework和ADO.NET兩種綜述

專案中用到了分頁,上次是用的是Entity Framework,這次用ADO.NET,都是老師講的,有必要總結一下,加深下記憶。 一、Entity Framework中完成分頁 老師就講了一種,在從資料庫倒序查詢到想要的list後,在對應的使用者控制元件的.cs檔案中用了兩

ASP.NET MVC 控制器檢視傳遞模型資料可以是多個

利用ViewBag來傳遞資料檢視部分程式碼:           @model Login001.Models.YSY_Ware            商品            @foreach (var n in ViewBag.ware)            {   

【Tomcat】解決GET方式傳遞引數URL中的引數亂碼問題

在Tomcat中(其它的webserver中也一樣),引數可以通過GET和POST方式傳遞。通過GET和POST方式傳遞的引數,遇到亂碼時的解決辦法也不一樣。 在Tomcat中遇到GET方式傳遞的引數(URL中的引數)亂碼時,可以通過下面的方式解決(解決方式之

後臺如何前端傳遞JSON資料Servlet傳jsp頁面

JSON是目前最受歡迎的資料格式了,深受廣大程式設計師的喜愛,下面咱們看看如何傳遞JSON資料。 需要匯入fastjson包下載地址 具體程式碼實現 String jsonStr =

ajax後臺傳遞陣列引數

ajax從後臺獲取資料是非常常用的一種方式,從後臺獲取資料會先往後臺傳遞一些引數,以前傳遞的都是一些簡單的字串,今天在做頁面資料的批量刪除時需要向後臺傳遞一組資料刪除資料的編號,但是當把陣列用data