解决EasyUI-Datagrid和LinqToEntity结合应用时排序问题
我们在做WEB页面时,时常会选择JQuery框架的Datagrid,如Ext、EasyUI、Flexigrid,数据访问则采用LinqToSQL或LinqToEntity。UI用Jquery框架的目的是代码简洁,较好的用户体验,漂亮的CSS;数据访问采用LinqToSQL或LinqToEntity的优点是开发便捷,将大部分的时间投入到业务中,而不是Ado.net的数据操作上。
下图是UI和后台的交互简略图,UI将json发送到业务层,业务层将json数据包装成查询对象,然后进行数据访问,获取数据结果集后,再包装成json对象返回给UI,然后UI解析和展现。
这里我就以EasyUI的Datagrid和LinqToEntity为例。见效果图:
难点是当需要排序时,LinqToEntity是通过对象的属性指定排序字段,而UI传过来的是字段名,要将排序的字符串转换为Lambda的排序。
分析EasyUI的Datagrid在ajax操作时传递了4个参数,分别是:Page(第几页),Rows(每页记录数),Sort(排序的字段名),Order(排序方式),为此我构建了Datagrid的参数类:
- public class DatagridParameters {
- public int Page { get; set; }
- public int Rows { get; set; }
- public string Sort { get; set; }
- public string Order { get; set; }
- }
参数的包装我是通过一般处理程序来处理,也可以是WCF或其他,哪里处理不是本文的重要之处
- //获取参数
- DatagridParameters dgParameters = new DatagridParameters {
- Page = Convert.ToInt32(context.Request.Form["page"]),
- Rows = Convert.ToInt32(context.Request.Form["rows"]),
- Sort = context.Request.Form["sort"],
- Order = context.Request.Form["order"],
- };
然后,我们要访问数据:
- using (SchoolDatabase db = new SchoolDatabase()) {
- UserBO userBO = UserBO.CreateBO<UserBO>();
- IQueryable<UserBO> query = userBO.GetUserList(db);
- JArray jRows = new JArray();
- json.Add(new JProperty("total", query.Count()));
- //这里进行排序和分页操作
- query = datagridPara.ExecutePaging(query);
- foreach (UserBO bo in query) {
- JObject o = JObject.FromObject(bo);
- jRows.Add(JObject.FromObject(bo));
- }
- json.Add(new JProperty("rows", jRows));
- }
为了实现Queryable的排序和分页,我在DatagridParameters中增加了一个ExecutePaging方法,该方法用于将排序的字符串转换为Lambda排序,并添加分页功能。
- public class DatagridParameters {
- public int Page { get; set; }
- public int Rows { get; set; }
- public string Sort { get; set; }
- public string Order { get; set; }
- /// <summary>
- /// 执行分页操作
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="source"></param>
- /// <returns></returns>
- public IQueryable<T> ExecutePaging<T>(IQueryable<T> source) {
- if (string.IsNullOrWhiteSpace(Sort)) return source;
- if (string.IsNullOrWhiteSpace(Order)) Order = "asc";
- try {
- Type type = typeof(T);
- string methodName = "asc".Equals(Order, StringComparison.OrdinalIgnoreCase) ? "OrderBy" : "OrderByDescending";
- PropertyInfo property = type.GetProperty(Sort);
- ParameterExpression parameter = Expression.Parameter(type, "c");
- MemberExpression propertyAccess = Expression.MakeMemberAccess(parameter, property);
- LambdaExpression orderByExp = Expression.Lambda(propertyAccess, parameter);
- MethodCallExpression resultExp = Expression.Call(typeof(Queryable), methodName, new Type[] { type, property.PropertyType }, source.Expression, Expression.Quote(orderByExp));
- source = source.Provider.CreateQuery<T>(resultExp);
- } catch {}
- return source.Skip((Page - 1) * Rows).Take(Rows);
- }
- }