首页 > 解决方案 > 不区分大小写的排序不起作用(.NET Core、EF)

问题描述

我想以不区分大小写的方式对从 Postgresql 数据库中检索的项目列表进行排序。

假设我有以下未排序的值:A, B, a, c, b, C

我想:A, a, B, b, C, c

但现在我得到:A, B, C, a, b, c

我在这里用错了 StringComparison.OrdinalIgnoreCase 吗?

感谢您的任何帮助或提示!

public class SortingInfo
{
    public string SortColumn { get; set; }
    public SortOrder SortOrder { get; set; }
}

public Task<List<MyCustomType>> GetItemsAsync(SortingInfo sortingInfo)
{
    var items = _itemsRepo
        .Query
        .ApplySort(sortingInfo)
        .ToList();

    var mappedData = _mapper.Map<List<Entities.MyCustomType>, List<MyCustomType>>(items);

    return Task.FromResult(mappedData);
}
public static IQueryable<T> ApplySort<T>(this IQueryable<T> query, SortingInfo sortingInfo)
{
    var propertyInfos = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
    
    var objectProperty = propertyInfos.FirstOrDefault(p =>
        p.Name.Equals(sortingInfo.SortColumn.Trim(), StringComparison.OrdinalIgnoreCase));

    if (objectProperty == null)
    {
        return query;
    }

    var sortingOrder = sortingInfo.SortOrder == SortOrder.Asc
        ? "ascending"
        : "descending";

    return query.OrderBy($"{objectProperty.Name} {sortingOrder}");
}

标签: c#.netsortingentity-framework-core

解决方案


我怀疑以这种方式订购您的物品的原因是由于您当前的整理

您可以强制不区分大小写,也可以强制查询运行并在代码中排序:

    public static IEnumerable<T> ApplySort<T>(this IQueryable<T> query, SortingInfo sortingInfo)
    {
        var propertyInfos = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);

        var objectProperty = propertyInfos.FirstOrDefault(p =>
            p.Name.Equals(sortingInfo.SortColumn.Trim(), StringComparison.OrdinalIgnoreCase));

        if (objectProperty == null)
        {
            return query;
        }

        var param = Expression.Parameter(typeof(T));
        
        LambdaExpression lambda = Expression.Lambda(Expression.Property(param, sortingInfo.SortColumn), param);     

        var materialisedQuery = query.ToList(); // this will force query execution!

        var orderByMethod = sortingInfo.SortOrder == SortOrder.Asc
            ? typeof(Enumerable).GetMethods().First(m => m.Name == "OrderBy" && m.GetParameters().Count() == 2)
            : typeof(Enumerable).GetMethods().First(m => m.Name == "OrderByDescending" && m.GetParameters().Count() == 2);
        orderByMethod = orderByMethod.MakeGenericMethod(typeof(T), objectProperty.PropertyType);

        return Expression.Lambda<Func<IEnumerable<T>>>(Expression.Call(orderByMethod, Expression.Constant(materialisedQuery), lambda)).Compile()();
}

通过 EF 强制进行排序可能会很痛苦(如果可能的话 - 我不确定它是否允许您这样做)。

有一个参数用于在代码和数据库中对最终数据集进行排序:

  • 一方面,您可以更轻松地扩展代码(RDBMS 不能很好地扩展,并且扩展有限制)
  • 但是根据您的数据,您可能会发现提供订单有助于 SQL 提出更好的执行计划

推荐阅读