ODATA不区分重音的过滤 [英] OData accent-insensitive filter
问题描述
如何应用过滤口音不敏感?在OData中,&q;等式运算符区分大小写和重音。这个问题很容易解决,因为这个问题很容易解决,但是相对于口音,我找不到一个简单的解决方案。我知道contains
应该是不区分重音的,但是如果我使用包含筛选条件(";São José";),我只能得到这些响应&Quot;São José";和";São Josédos Campos";,它缺少";São Jose";。
以下示例按";florianopolis";筛选应该返回";florianópolis";,但它没有:
url:api/cidades/get?$filter=contains(nome, 'Florianopolis')
[HttpGet]
[EnableQuery]
public ActionResult<IQueryable<CidadeDTO>> Get()
{
try
{
return Ok(_mapper.Map<IEnumerable<CidadeDTO>>(_db.Cidades));
}
catch (System.Exception e)
{
return BadRequest(e.GetBaseException().Message);
}
}
它也应该带来类似实体框架的功能。
推荐答案
如果您的OData模型直接映射到EF模型,并且IQueryable<T>
表达式传递到OK()
,则查询将作为sql:
SELECT * FROM Cidades WHERE nome LIKE '%Florianopolis%'
发生这种情况时,数据库连接中的排序规则设置将确定比较匹配逻辑。
如果您的数据库排序规则不区分大小写和重音,但是您的数据仍然被筛选,就好像它不区分大小写一样,那么这表明IEnumerable<T>
已经传递到OK()
中,并且比较逻辑正在用C#进行计算,而C#默认情况下是不区分大小写和重音的。遗憾的是,这意味着很可能已首先将整个数据表加载到内存中,以便可以应用过滤。
在您的示例中,OData模型被映射到DTO表达式,而DTO表达式通过AutoMapper映射到EF模型,这就是生成的查询可以分解的地方。通过调用Map()
,您将从EF表加载所有记录,并将$filter
条件留给EnableQueryAttribute
要自动应用OData查询约定,必须从您的方法返回IQueryable<T>
,或者至少将IQueryable<T>
传递给OK()
响应处理程序。使用AutoMapper,您可以使用可查询扩展来满足IQueryable<T>
要求:
Queryable Extensions
将诸如NHibernate或Entity Framework之类的ORM与AutoMapper的标准mapper.Map函数一起使用时,您可能会注意到,当AutoMapper尝试将结果映射到目标类型时,ORM将查询图形中所有对象的所有字段。.
ProjectTo
必须是链中的最后一个调用。ORM使用实体,而不是DTO。因此,对实体应用任何筛选和排序,作为最后一步,将其投影到DTO。
在OData中,最后一个要求(关于ProjectTo
)仍然有问题,因为EnableQueryAttribute
将将查询选项追加到IQueryable<T>
响应中,最终仍然是首先将整个表物化到内存中(IEnumerable<T>
),然后再应用过滤,这仍然是非常低效的。当有人抱怨OData实现的性能不佳时,通常会观察到这种行为,它并不总是AutoMapper,而通常是数据源被完整加载到内存中然后然后过滤的模式。遵循AutoMapper的默认指导将引导您朝此方向前进。
相反,我们需要使用其他程序包:AutoMapper.Extensions.ExpressionMapping,它将使我们能够访问UseAsDataSource
扩展方法。
UseAsDataSource
将表达式相互映射是一项单调乏味的工作,并且会产生又长又丑的代码。
UseAsDataSource().For<DTO>()
不必显式映射表达式,从而使转换清晰。如果适用,它还会为您调用ProjectTo<TDO>()
。
这会将您的实现更改为以下内容:
[HttpGet]
[EnableQuery]
public ActionResult<IQueryable<CidadeDTO>> Get()
{
return Ok(_db.Cidades.UseAsDataSource().For<CidadeDTO>());
}
不要陷入假定AutoMapper对于OData API实现是必需的或最佳实践的陷阱。如果您没有使用AutoMapper提供的独特功能,则添加额外的抽象层可能会使您的解决方案过于复杂。
我不反对AutoMapper,我经常将它用于集成、ETL、GraphQL和非DDD样式的数据模式,其中DTO模型与底层的EF/数据存储模型有很大的不同。但是基于简单DDD数据模型和OData API的解决方案很容易没有维护和性能开销。
- 当一把简单的铲子就能完成工作时,不要雇佣挖掘机。
AutoMapper是一种基于约定的ORM,在您要更改代码中实现层之间的结构时非常有用。传统上,您可能会将可能表示聚合或具有扁平化结构的业务域模型映射到高度规范化的数据库模型。
OData也是基于约定的ORM。它旨在简化AutoAmpper提供的许多操作,但展平和取消展平模型除外。这些操作被推迟到EF引擎。通过OData映射公开的类型为DTO
如果您的DTO模型与您的EF模型是相同的关系结构,那么您通常根本不会使用AutoMapper,OData EDM映射是专门为管理这种类型的工作负载而优化的,并且设计为并且已经直接集成到序列化层中,从而使EDM真正成为只存在于网络和客户端中的数据传输对象。
这篇关于ODATA不区分重音的过滤的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!