使用 OData 在 EF Core 中排序不区分大小写

Sorting in EF Core using OData to be case insensitive

我在我的 .NET Core 2.2 应用程序上使用 EF Core 连接数据库,在前端使用 Angular 8。我还使用 OData 从我的 API.

中检索一些数据

我的 OData 查询如下所示:

https://example.com/Odata/Farmers?$count=true&$orderby=firstName%20asc&$top=10

上面的查询 returns 数据排序如下: A, B, a, b

但它应该 returns 数据(不区分大小写): A, a, B, b.

我的 .NET Core API 端点如下所示:

[EnableQuery(HandleNullPropagation = HandleNullPropagationOption.False)]
[ODataRoute]
[AuthorizeScopes(AppScopes.FarmerListRead)]
[HttpGet]
public IQueryable<FarmerViewDto> GetAll()
{
    return _unitOfWork
        .FarmerViewRepository
        .GetAllQueryable()
        .UseAsDataSource()
        .For<FarmerViewDto>();
}

我在 OData 路由配置中找到了一个 属性 EnableCaseInsensitive,但它用于其他用途。我找不到适合我的问题的解决方案。

在你做 return

之前
var farmerViewDto = _unitOfWork
        .FarmerViewRepository
        .GetAllQueryable()
        .UseAsDataSource()
        .For<FarmerViewDto>();


var returnValue = farmerViewDto.ToList().OrderBy(x => x.PropertyYouWantToSort, StringComparer.OrdinalIgnoreCase).AsQueryable();

retur returnValue;

在我的评论中添加额外信息 更快但有很多代码

var searchFilter = //user input

var query = _unitOfWork
        .FarmerViewRepository
        .GetAllQueryable()
        .UseAsDataSource()
        .For<FarmerViewDto>().AsQueryable();

if (searchFilter == "property1")
{
    query = query.OrdberBy(x => x.Property1, StringComparer.OrdinalIgnoreCase).AsQueryable();
}
if (searchFilter == "property2")
{
    query = query.OrdberBy(x => x.Property2, StringComparer.OrdinalIgnoreCase).AsQueryable();
}
.....

return query;

通过反射

var searchFilter = //user input

var query = _unitOfWork
        .FarmerViewRepository
        .GetAllQueryable()
        .UseAsDataSource()
        .For<FarmerViewDto>();

query.Where(x => x.GetType()
                  .GetProperty(searchFilter)
                  .GetValue(x).ToString(), StringComparer.OrdinalIgnoreCase).AsQueryable();

return query;

尝试这样的事情...

public class CaseInsensitiveComparer : IComparer<string> 
{ 
    public int Compare(string a, string b) 
    { 
        return string.Compare(a, b, StringComparison.OrdinalIgnoreCase); 
    } 
}

[EnableQuery(HandleNullPropagation = HandleNullPropagationOption.False)]
[ODataRoute]
[AuthorizeScopes(AppScopes.FarmerListRead)]
[HttpGet]
public IQueryable<FarmerViewDto> GetAll()
{
    return _unitOfWork
        .FarmerViewRepository
        .GetAllQueryable()
        .UseAsDataSource()
        .For<FarmerViewDto>();
        .OrderBy(x => x.firstName, new CaseInsensitiveComparer());
}

== 编辑 ==

以下可查询扩展支持按单个列名按升序或降序(默认为升序)排序...

namespace System.Linq
{
    public static class QueryableExtensions
    {
        public static IOrderedQueryable<TSource> Sort<TSource>(this IQueryable<TSource> source, IComparer<string> comparer, string sortExpression)
        {
            bool sortDescending = false;
            if (sortExpression.EndsWith(" DESC", StringComparison.OrdinalIgnoreCase))
            {
                sortDescending = true;
                sortExpression = sortExpression.Substring(0, sortExpression.Length - 5);
            }
            if (sortExpression.EndsWith(" ASC", StringComparison.OrdinalIgnoreCase))
            {
                sortDescending = false;
                sortExpression = sortExpression.Substring(0, sortExpression.Length - 4);
            }

            var param = Expression.Parameter(typeof(TSource), "source");
            var expression = Expression.Lambda<Func<TSource, string>>(Expression.Convert(Expression.Property(param, sortExpression), typeof(string)), param);

            if (!sortDescending)
                return source.OrderBy<TSource, string>(expression, comparer);
            else
                return source.OrderByDescending<TSource, string>(expression, comparer);
        }
    }
}

然后您可以按以下方式使用...

    return _unitOfWork
        .FarmerViewRepository
        .GetAllQueryable()
        .UseAsDataSource()
        .For<FarmerViewDto>();
        .Sort(new CaseInsensitiveComparer(), "firstName asc");

它假定所有对象属性都可以合理地转换为字符串。如果您的属性上有自定义 类,您需要确保正确覆盖 ToString()

它也只适用于单个字段,即:"field""field1 asc""field1 desc"。如果你想要像 "field1 asc, field2 desc".

这样的东西,我会把额外的愚蠢留给你