EF架構~真(zhen)正被封裝(zhuang)的排序方法(fa),支持多列排序
對于linq to sql 和linq to entity來說,當你(ni)把獲取數據(ju)的(de)(de)(de)(de)方法封(feng)裝了(le)之(zhi)(zhi)后(hou)(hou),總覺得還(huan)(huan)缺(que)點什(shen)么,想了(le)之(zhi)(zhi)后(hou)(hou),應(ying)該是排(pai)(pai)序(xu)(xu),但看了(le)微軟的(de)(de)(de)(de)orchard項目(mu)之(zhi)(zhi)后(hou)(hou),覺得它的(de)(de)(de)(de)排(pai)(pai)序(xu)(xu)封(feng)裝的(de)(de)(de)(de)并不好,而且還(huan)(huan)有多列排(pai)(pai)序(xu)(xu)的(de)(de)(de)(de)問題(ti),所以(yi),我自己又改進了(le)一下,首先提出一個與分層(ceng)無關(guan)的(de)(de)(de)(de)IOrderable接口(kou)的(de)(de)(de)(de)概念,它是為了(le)讓(rang)WEB,BLL,DATA層(ceng)之(zhi)(zhi)間解(jie)耦的(de)(de)(de)(de),其(qi)次增加了(le)ThenAsc和ThenDesc讓(rang)它們支持多列排(pai)(pai)序(xu)(xu),orchard項目(mu)里,之(zhi)(zhi)前是使用參數來實現的(de)(de)(de)(de),最(zui)多支持3列排(pai)(pai)序(xu)(xu),而且不支持升(sheng)降混(hun)排(pai)(pai)的(de)(de)(de)(de)情況,呵呵。
看一個IOrderable接口
/// <summary> /// 排序規范 /// </summary> /// <typeparam name="T"></typeparam> public interface IOrderable<T> { /// <summary> /// 遞增 /// </summary> /// <typeparam name="TKey"></typeparam> /// <param name="keySelector"></param> /// <returns></returns> IOrderable<T> Asc<TKey>(global::System.Linq.Expressions.Expression<Func<T, TKey>> keySelector); /// <summary> /// 然后遞增 /// </summary> /// <typeparam name="TKey1"></typeparam> /// <typeparam name="TKey2"></typeparam> /// <param name="keySelector1"></param> /// <returns></returns> IOrderable<T> ThenAsc<TKey>(Expression<Func<T, TKey>> keySelector); /// <summary> /// 遞(di)減(jian) /// </summary> /// <typeparam name="TKey"></typeparam> /// <param name="keySelector"></param> /// <returns></returns> IOrderable<T> Desc<TKey>(global::System.Linq.Expressions.Expression<Func<T, TKey>> keySelector); /// <summary> /// 然(ran)后遞(di)減(jian) /// </summary> /// <typeparam name="TKey"></typeparam> /// <param name="keySelector"></param> /// <returns></returns> IOrderable<T> ThenDesc<TKey>(Expression<Func<T, TKey>> keySelector); /// <summary> /// 排序后的結果集 /// </summary> global::System.Linq.IQueryable<T> Queryable { get; } }
OK,下面是(shi)(shi)(shi)為接(jie)口的(de)(de)(de)一(yi)個實(shi)現,這(zhe)個實(shi)現我是(shi)(shi)(shi)放(fang)在Data層的(de)(de)(de),因為它是(shi)(shi)(shi)與(yu)ORM架構(gou)有關(guan)的(de)(de)(de),可能你的(de)(de)(de)linq與(yu)ado.net的(de)(de)(de)排序(xu)實(shi)現是(shi)(shi)(shi)不同的(de)(de)(de),所(suo)以,不能放(fang)在entity層,我的(de)(de)(de)習慣是(shi)(shi)(shi),所(suo)有linq特有的(de)(de)(de)都放(fang)在linq架構(gou)的(de)(de)(de)Data層(如,IQueryable,這(zhe)就是(shi)(shi)(shi)linq特有的(de)(de)(de),而list,IEnumerable等擴展應該放(fang)在entity層)
namespace EntityFrameworks.Data.Core { /// <summary> /// Linq架構(gou)里對(dui)集合排序(xu)實現 /// </summary> /// <typeparam name="T"></typeparam> public class Orderable<T> : IOrderable<T> { private IQueryable<T> _queryable; /// <summary> /// 排序后的結果集 /// </summary> /// <param name="enumerable"></param> public Orderable(IQueryable<T> enumerable) { _queryable = enumerable; } /// <summary> /// 排(pai)序(xu)之(zhi)后(hou)的結果集 /// </summary> public IQueryable<T> Queryable { get { return _queryable; } } /// <summary> /// 遞(di)增 /// </summary> /// <typeparam name="TKey"></typeparam> /// <param name="keySelector"></param> /// <returns></returns> public IOrderable<T> Asc<TKey>(Expression<Func<T, TKey>> keySelector) { _queryable = (_queryable as IOrderedQueryable<T>) .OrderBy(keySelector); return this; } /// <summary> /// 然后遞(di)增 /// </summary> /// <typeparam name="TKey"></typeparam> /// <param name="keySelector"></param> /// <returns></returns> public IOrderable<T> ThenAsc<TKey>(Expression<Func<T, TKey>> keySelector) { _queryable = (_queryable as IOrderedQueryable<T>) .ThenBy(keySelector); return this; } /// <summary> /// 遞減 /// </summary> /// <typeparam name="TKey"></typeparam> /// <param name="keySelector"></param> /// <returns></returns> public IOrderable<T> Desc<TKey>(Expression<Func<T, TKey>> keySelector) { _queryable = _queryable .OrderByDescending(keySelector); return this; } /// <summary> /// 然后遞(di)減 /// </summary> /// <typeparam name="TKey"></typeparam> /// <param name="keySelector"></param> /// <returns></returns> public IOrderable<T> ThenDesc<TKey>(Expression<Func<T, TKey>> keySelector) { _queryable = (_queryable as IOrderedQueryable<T>) .ThenByDescending(keySelector); return this; } } }
而這個排(pai)序的(de)方(fang)法(fa),可(ke)以單(dan)獨(du)被(bei)BLL層使用(yong),自己(ji)去組裝它,也可(ke)以在Data層提(ti)供(gong)的(de)GetModel()方(fang)法(fa)里(li)直(zhi)接使用(yong),因為我的(de)架構里(li)已經有(you)排(pai)序功能擬合到GetModel方(fang)法(fa)里(li)了,看代碼(ma):
public IQueryable<TEntity> GetModel(Action<IOrderable<TEntity>> orderBy) { var linq = new Orderable<TEntity>(GetModel()); orderBy(linq); return linq.Queryable; }
如(ru)果在其它層(ceng)調用,可以自己(ji)去實例化(hua)Action<IOrderable<TEntity>>這個對象,如(ru)代碼:
backgroundEntities1 db = new backgroundEntities1(); DbContextRepository<WebManageUsers> user = new DbContextRepository<WebManageUsers>(db); Action<IOrderable<WebManageUsers>> orderBy = query => query.Asc(j => j.DepartmentID) .ThenDesc(j => j.ManageUserID); user.GetModel(orderBy).ToList().ForEach(k => { Console.WriteLine("部門:" + k.DepartmentID + ",用戶 :" + k.ManageUserID); });
上面的代碼是先對DepartmentID進行升序,再對ManageUserID進行降(jiang)序,看(kan)一下結果如圖: