Entity Framework4.1实现动态多条件查询、分页和排序

本文介绍如何在EF中实现通用的分页与排序功能,包括动态排序扩展方法、多条件组合查询以及通过Expression获取字段名等技巧。此外,还提供了一个示例方法用于通过多个条件获取用户数据,并进行分页展示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

EF通用的分页实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/// <summary>
/// 根据条件分页获得记录
/// </summary>
/// <param name="where">条件</param>
/// <param name="orderBy">排序</param>
/// <param name="ascending">是否升序</param>
/// <param name="pageIndex">当前页码</param>
/// <param name="pageSize">每页大小</param>
/// <param name="totalRecord">总记录数</param>
/// <returns>记录列表</returns>
public virtual List<T> GetMany(Expression<Func<T, bool>> wherestring orderBy, bool ascendingint pageIndex, int pageSize, out int totalRecord)
{
    totalRecord = 0;
    where where.And(u => u.Flag != (int)Flags.Delete);
    var list = dbset.Where(where);
 
    totalRecord = list.Count();
    if (totalRecord <= 0) return new List<T>();
 
    list = list.OrderBy(orderBy, ascending).Skip((pageIndex - 1) * pageSize).Take(pageSize);
 
    return list.ToList();
}

 

动态排序扩展:

public static IQueryable<T> OrderBy<T>(this IQueryable<T> source, string propertyName, bool ascending) where T : class
{
    Type type = typeof(T);
 
    PropertyInfo property = type.GetProperty(propertyName);
    if (property == null)
        throw new ArgumentException("propertyName", "Not Exist");
 
    ParameterExpression param = Expression.Parameter(type, "p");
    Expression propertyAccessExpression = Expression.MakeMemberAccess(param, property);
    LambdaExpression orderByExpression = Expression.Lambda(propertyAccessExpression, param);
 
    string methodName = ascending ? "OrderBy" : "OrderByDescending";
 
    MethodCallExpression resultExp = Expression.Call(typeof(Queryable), methodName, new Type[] { type, property.PropertyType }, source.Expression, Expression.Quote(orderByExpression));
 
    return source.Provider.CreateQuery<T>(resultExp);
}

 

如果要通过Expression获取字段,可以使用以下代码:

/// <summary>
/// 获取对应的字段名
/// </summary>
/// <typeparam name="TSource"></typeparam>
/// <param name="keySelector"></param>
/// <returns></returns>
public static string GetMemberName<TSource, TKey>(Expression<Func<TSource, TKey>> keySelector)
{
    string fieldName = null;
    var exp = keySelector.Body as UnaryExpression;
    if (exp == null)
    {
        var body = keySelector.Body as MemberExpression;
        fieldName = body.Member.Name;
    }
    else
    {
        fieldName = (exp.Operand as MemberExpression).Member.Name;
    }
    return fieldName;
}

 

多条件组合(参见老赵相关文章):

/// <summary>
/// 统一ParameterExpression
/// </summary>
internal class ParameterReplacer : ExpressionVisitor
{
    public ParameterReplacer(ParameterExpression paramExpr)
    {
        this.ParameterExpression = paramExpr;
    }
 
    public ParameterExpression ParameterExpression { get; private set; }
 
    public Expression Replace(Expression expr)
    {
        return this.Visit(expr);
    }
 
    protected override Expression VisitParameter(ParameterExpression p)
    {
        return this.ParameterExpression;
    }
}
 
public static class PredicateExtensionses
{
    public static Expression<Func<T, bool>> True<T>() { return f => true; }
 
    public static Expression<Func<T, bool>> False<T>() { return f => false; }
 
    public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> exp_left, Expression<Func<T, bool>> exp_right)
    {
        var candidateExpr = Expression.Parameter(typeof(T), "candidate");
        var parameterReplacer = new ParameterReplacer(candidateExpr);
 
        var left = parameterReplacer.Replace(exp_left.Body);
        var right = parameterReplacer.Replace(exp_right.Body);
        var body = Expression.And(left, right);
 
        return Expression.Lambda<Func<T, bool>>(body, candidateExpr);
    }
 
    public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> exp_left, Expression<Func<T, bool>> exp_right)
    {
        var candidateExpr = Expression.Parameter(typeof(T), "candidate");
        var parameterReplacer = new ParameterReplacer(candidateExpr);
 
        var left = parameterReplacer.Replace(exp_left.Body);
        var right = parameterReplacer.Replace(exp_right.Body);
        var body = Expression.Or(left, right);
 
        return Expression.Lambda<Func<T, bool>>(body, candidateExpr);
    }
}

  

 

调用示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public static PagedList<UsersDTO> GetUsers(int pageIndex, int pageSize, string orderBy, bool ascending,
    Companys company, string email, string nickName, bool? isAdmin, UserStatus userStatus)
{
    PagedList<UsersDTO> result = new PagedList<UsersDTO>(pageIndex, pageSize);
    int totalRecord = 0;
 
    Expression<Func<Users, bool>> where = PredicateExtensionses.True<Users>();
    if (company != Companys.All) where where.And(u => u.Company == (int)company);
    if (!string.IsNullOrEmpty(email)) where where.And(u => u.Email.Contains(email));
    if (!string.IsNullOrEmpty(nickName)) where where.And(u => u.NickName.Contains(nickName));
    if (isAdmin.HasValue)
    {
        if (isAdmin.Value) where where.And(u => u.IsAdmin == 1);
        else where where.And(u => u.IsAdmin == 0);
    }
    if (userStatus != UserStatus.All) where where.And(u => u.UserStatus == (int)userStatus);
 
    if (string.IsNullOrEmpty(orderBy))
        orderBy = MapHelper.GetMappedName<UsersDTO, Users>(u => u.UserId);
    else
        orderBy = MapHelper.GetMappedName<UsersDTO, Users>(orderBy);
 
    List<Users> list = _usersDao.GetMany(where, orderBy, ascending, pageIndex, pageSize, out totalRecord);
    result.TotalRecordCount = totalRecord;
    foreach (var data in list)
    {
        result.Items.Add(Mapper.Map<Users, UsersDTO>(data));
    }
    return result;
}

  


上述方法的缺点是无法针对2个字段一起排序,不过只要修改排序参数还是可以实现的!

另外这种分页查询只能针对一个表或者视图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值