c# - Net Core:在洋葱架构中使用OData,将查询参数转换为Linq
问题描述
我们正在创建一个搜索函数来返回大型数据库中的匹配地址记录。
Address Table 包含 SQL 表中的 20+ 列,需要使用不同的 OData 参数(EqualTo、Contains、Starts With 等)进行查询。
尝试使用 OData,而不将 DBContext 注入 API 控制器。这在当前架构中是不允许的。如何编写代码来实现这一点?
*我们使用 ProjectTo 让它工作。但是,OData Http 特定功能正在传递到非 Api 级别。目前在 AppServices 中有 ODataQueryOptions。
我们如何将整个 ODataQueryOptions 转换为 Linq 表达式查询(无论传入什么),此资源仅用于过滤器,如何将 OData 过滤器转换为 LINQ 表达式?
DBContext-->DomainLayer-->Dto--> 然后是API Level,
中间的两层。映射器从 EF DBContext 映射到 Domain 到 Dto。
存储库方法带来数据。
AppService 方法转换为 Dto。
ProjectTo 的当前解决方案:
控制器 API:
[HttpGet]
public async Task<ActionResult<IList<AddressTypeDto>> GetAddressAPI(ODataQueryOptions<AddressTypeDto> queryOptions)
{
return Ok(await _service.GetAddressTypeDto(queryOptions));
}
申请服务:
(我们如何在 Startup 中应用 ODataModelBuilder 映射?)
public async Task<AddressTypeResponse> GetAddressTypeDto(ODataQueryOptions<AddressTypeDto> queryOptions)
{
var dto = (IQueryable<AddressTypeDto>)queryOptions.ApplyTo(_addressRepository.GetAddressTypes().ProjectTo<AddressTypeDto>(_mapper.ConfigurationProvider));
var dtoList = await dto.ToListAsync();
return dto;
}
存储库:
[EnableQuery]
public IQueryable<LkAddressType> GetAddressTypesData()
{
return _ctx.LkAddressType.AsNoTracking();
}
课程:
public class AddressTypeDto
{
public int AddressTypeId { get; set; }
public int? LastModifiedByUserId { get; set; }
public string AddressTypeCode { get; set; }
public string AddressTypeDescription { get; set; }
public bool? Status { get; set; }
public DateTime? CreateDate { get; set; }
}
public LkAddressType()
{
public int LkAddressTypeId { get; set; }
public int? LastModifiedByUserId { get; set; }
public string AddressTypeCode { get; set; }
public string AddressTypeDescription { get; set; }
public bool? Status { get; set; }
public DateTime? CreateDate { get; set; }
public DateTime? EffectiveStartDate { get; set; }
public DateTime? EffectiveEndDate { get; set; }
}
使用 C# Net Core 2.2、Entity Framework、Sql Server 数据库
资源: 也试图利用这个
解决方案
我写这个函数已经很久了,但链接可能会有所帮助。GetAll() 只返回一个 IEnumerable。
[Route(""), HttpGet]
public IHttpActionResult Get(ODataQueryOptions<Language> queryOptions)
{
Log.Info($"{nameof(Get)} (ODataQueryOptions)");
//OData directly with normal WebAPI
//https://blogs.msdn.microsoft.com/webdev/2013/02/25/translating-odata-queries-to-hql/
//https://stackoverflow.com/questions/10781309/asp-net-mvc-4-webapi-manually-handle-odata-queries
//https://blogs.msdn.microsoft.com/odatateam/2014/07/04/tutorial-sample-using-odatauriparser-for-odata-v4/
//OData without entity framework, but full-on odata controller
//http://www.odata.org/blog/how-to-use-web-api-odata-to-build-an-odata-v4-service-without-entity-framework/
//OData tips and tricks
//https://blogs.msdn.microsoft.com/davidhardin/2014/12/17/web-api-odata-v4-lessons-learned/
return Ok(queryOptions.ApplyTo(_repository.GetAll().AsQueryable()));
}