默认情况下,ODataController执行区分大小写的搜索。我们如何扩展此行为以执行不区分大小写的搜索。
public class NammaODataController : ODataController
{
[EnableQuery]
public IQueryable<FD> GetFD(ODataQueryOptions qo)
{
return _ctx.FDs.AsQueryAble();
//EF takes care to apply odata query operators internally
//after control passes from action
}
}
我提到this SO似乎我们可以利用表达式树,但是在 哪个可扩展点?
有什么办法可以拦截查询并自定义EF / Web Api piplelie来实现这个目标吗?
以下是一个例子:/ FD?$ filter = tolower(Pr_Name)eq tolower('TAMARA') - 这应该归还所有名为'Tamara'的人(案例 麻木不仁,可能是'TAMARA','tamara','Tamara'等。希望这会 帮助,提出我的观点。
修改
ODATA Web API queries
中的区分大小写与SQL排序无关。这是Microsoft OData框架的一个问题。
使用substringof运算符
void Main()
{
var lower = _ctx.FD
.Where(sv => sv.Pr_Name.Contains("tamara"))
.Take(1)
.ToList();
Console.WriteLine("LOWER CASE AZURE SQL OUTPUT");
Console.WriteLine(lower);
Console.WriteLine("UPPER CASE AZURE SQL OUTPUT");
var upper = _ctx.FD
.Where(sv => sv.Pr_Name.Contains("TAMARA"))
.Take(1)
.ToList();
Console.WriteLine(upper);
}
使用
eq
运算符
void Main()
{
var lower = FD
.Where(sv => sv.Pr_Name == tamara A TOPOLESKI")
.Take(1)
.ToList();
Console.WriteLine("LOWER CASE AZURE SQL OUTPUT");
Console.WriteLine(lower);
Console.WriteLine("UPPER CASE AZURE SQL OUTPUT");
var upper = FD
.Where(sv => sv.Pr_Name == "TAMARA TOPOLESKI")
.Take(1)
.ToList();
Console.WriteLine(upper);
}
答案 0 :(得分:1)
你是对的,问题与你的整理无关。它与您正在使用的odata表达式有关。在您更新的测试查询中,您使用的Contains
会在搜索值的任意一端被翻译成带有通配符(任意字符串为零或多个字符)的LIKE
。但是,在odata表达式中,您使用的是eq
,它将被转换为EF表达式中的=
,然后再次转换为SQL查询。由于您在输出中显示的Pr_Name
值不完全等于"Tamara"
但包含"Tamara"
,因此odata查询不会带回任何数据。
你需要的是odata过滤器表达式substringof
,它将由EF转换为Contains
,在sql中将其翻译为LIKE
,并在搜索值的任一侧使用通配符。
/FD?$filter=substringof(Pr_Name,'tamara')
有关更多过滤器表达式,请参阅Using Filter Expressions
如评论中所述@ThomasKoelle
,这与列的整理有关。 OData管道(您已在上面定义)使用Entity Framework将传入的表达式转换为数据库的查询。所以OData表达式与它无关,也没有构建的EF查询。
如果您使用区分大小写的排序规则,那么您必须将所有搜索字词和搜索列放在相同的情况下,这对性能非常不利,因为这些搜索条款不会是SARGable。
对于大多数DBMS,列的排序规则继承自数据库的默认排序规则,该排序规则从实例默认排序规则继承。您可以在每个级别覆盖,但必须在定义实例(模式/数据库)时明确完成。