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



我在我的.NET Core 2.2应用程序上使用EF Core与DB连接,并在前端使用Angular 8。我还使用 OData 从我的 API 中检索一些数据。

我的 OData 查询如下所示:

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

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

但它应该返回类似(不区分大小写(的数据: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,但它用于其他用途。我找不到适合我的问题的解决方案。

尝试这样的事情...

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"这样的东西,我会把额外的愚蠢留给你.

在你做返回之前

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;

最新更新