【问题标题】:How to get dynamic column data linq如何获取动态列数据linq
【发布时间】:2021-06-01 21:12:32
【问题描述】:

我有以下代码,

public List<MemberDto> GetMembers(out int rowCount,int pageIndex,int pageSize,  string seachColumn = "", string searchTerm = "", string sortBy = "", string sortDiection = "")
{
    var members = (from m in context.Members
                   where (string.IsNullOrEmpty(searchTerm) || m.MemberNumber.Equals(searchTerm))
                         || (string.IsNullOrEmpty(searchTerm) || m.LastName.Equals(searchTerm))
                   select m).AsEnumerable();
                   
    if (!string.IsNullOrEmpty(sortBy))
    {
        PropertyDescriptor prop = TypeDescriptor.GetProperties(typeof(EFModel.ClientData.Member)).Find(sortBy, true);
        members = (sortDiection.ToLower() == "descnding") ? members.OrderByDescending(x => prop.GetValue(x)).ToList() : members.OrderBy(x => prop.GetValue(x)).ToList();
    }

    rowCount =  (!string.IsNullOrEmpty(searchTerm)) ? members.Count() : rowCount = context.Members.Count() ;
    
    members = members.Skip(pageIndex).Take(pageSize).ToList();

    List<MemberDto> memberDtos = new List<MemberDto>();
    mapper.Map(members, memberDtos);
    return memberDtos;
}

在上面的代码中,我的seachColumn值可以是("a","b",or "")。当seachColumn = "a" 时,我需要根据searchTerm 值按列MemberNumber 搜索表数据

seachColumn = "b" 时,我需要按LastName 列搜索表数据。基于searchTerm

为了实现这一点,我编写了以下代码。

if(seachBy == "a")
{
    var sa = (from m in context.Members
              where (string.IsNullOrEmpty(searchTerm) || m.MemberNumber.Equals(searchTerm))
              select m).AsEnumerable();
}
else if (seachBy == "b")
{
    var sa = (from m in context.Members
              where (string.IsNullOrEmpty(searchTerm) || m.LastName.Equals(searchTerm))
              select m).AsEnumerable();
}

我知道,我试过的代码有点傻。有什么合适的方法吗?

【问题讨论】:

  • 如果您要求进行一般性代码审查,这在 SO 中基本上是题外话(因为它可能非常主观并促进不同意见的讨论);您需要更加关注您的要求并具体化,并且应该促进基于事实的答案。请参阅don't-ask,因为它与改进主观问题有关。此外,codereview.stackexchange.com 的一般代码审查是主题

标签: c# entity-framework linq


【解决方案1】:

是的,有更好的方法来做到这一点。首先,您想以IQueryable 的身份完成这一切 - 为什么? - 因为只要您执行.AsEnumerable().ToList(),查询就会在数据库服务器上执行,并且数据会加载到内存中。

因此,在您的代码中 - 因为您调用了 .AsEnumerable(),它已将所有 context.Members.Where condition is true 加载到内存中:

var members = (from m in context.Members
                   where (string.IsNullOrEmpty(searchTerm) || m.MemberNumber.Equals(searchTerm))
                         || (string.IsNullOrEmpty(searchTerm) || m.LastName.Equals(searchTerm))
                   select m)
.AsEnumerable(); 

您的第二部分代码是分页。我们通常做的是写一个IQueryable 扩展方法。

因此,将以下具有 2 个扩展方法的类添加到一个公共位置。

public static class IQueryableExtensions
{
    public static IQueryable<T> ApplyPagination<T>(this IQueryable<T> source, string sortDirection, string sortBy, int pageNumber, int pageSize)
    {
        var sortDirectionInternal = sortDirection == "asc" ? "OrderBy" : "OrderByDescending";

        var orderBy = sortBy;

        if (pageSize != -1)  // -1 is for All - I don't apply pagination if pageSize == -1.
        {
            return source.OrderBy(orderBy, sortDirectionInternal)
                    .Skip((pageNumber - 1) * pageSize)
                    .Take(pageSize);
        }

        return source.OrderBy(orderBy, sortDirection);
    }

    public static IQueryable<T> OrderBy<T>(this IQueryable<T> source, string ordering, string sortDirection)
    {
        var type = typeof(T);

        // Get Property to Sort By
        var property = type.GetProperty(ordering);

        // If Property is NULL (not found) - Just use the first Property (Default) to ORDER BY - as this will prevent Exception
        if (property == null)
        {
            property = type.GetProperties().First();
        }

        var parameter = Expression.Parameter(type, "p");
        var propertyAccess = Expression.MakeMemberAccess(parameter, property);
        var orderByExp = Expression.Lambda(propertyAccess, parameter);
        var resultExp = Expression.Call(typeof(Queryable), sortDirection, new[] { type, property.PropertyType }, source.Expression, Expression.Quote(orderByExp));
        return source.Provider.CreateQuery<T>(resultExp);
    }
}

所以现在你上面的代码看起来像这样 - 我没有使用 VS 所以可能有一些 sytnax 错误:

// NOTE: you will need to include the namespace for the new IQueryableExtensions class

var members = (from m in context.Members
               where (string.IsNullOrEmpty(searchTerm) || m.MemberNumber.Equals(searchTerm))
                     || (string.IsNullOrEmpty(searchTerm) || m.LastName.Equals(searchTerm))
               select m);

// retrieve count only if you need to of total members that match the above criteria
rowCount = members.Count();

// This is all you need to do! - ApplyPagination(params) - 
members = members.ApplyPagination(sortDiection, sortBy, pageIndex, pageSize);

return mapper.Map<List<MemberDto>>(members);

【讨论】:

  • 你的pageNumber 是什么?如果计算结果小于 0,您可能会收到此错误。我的页码从 1 开始,所以对于 page1,它计算为 .Skip(0),对于 page2,它计算为 .Skip(1 * pageSize)
  • 是的,这就是原因。但该命令无法正常工作。一旦我没有通过 sortBy 。根据我的表结构,从这个代码部分property = type.GetProperties().First();属性取为MemberId,但检索数据显示不正确,它返回25条记录,但我不明白那个顺序是什么。
  • 是的,这就是原因。但该命令无法正常工作。一旦我没有通过 sortBy 。从此代码部分property = type.GetProperties().First(); 属性根据我的表结构取为MemberId,但检索数据显示不正确,它返回 25 条记录,但我不明白那个顺序是什么。
  • 对不起,先生,我认为这是因为在我的数据库中名字和姓氏总是加密的。这就是为什么我认为订单部分无法正常工作的原因。如何处理这个
  • 很明显,如果您不传递sortBy,它将从代码中获取第一个属性,OrderBy 将获取第一列/属性。这就是代码property = type.GetProperties().First(); 的作用。阅读代码// If Property is NULL (not found) - Just use the first Property (Default) to ORDER BY - as this will prevent Exception中的注释
猜你喜欢
  • 2018-09-01
  • 1970-01-01
  • 2011-09-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多