Net Core:在洋葱架构中使用OData,将查询参数转换为Linq

Posted

技术标签:

【中文标题】Net Core:在洋葱架构中使用OData,将查询参数转换为Linq【英文标题】:Net Core: Using OData in Onion Architecture, Convert Query Parameters Into Linq 【发布时间】:2020-10-20 08:10:07 【问题描述】:

我们正在创建一个搜索函数来返回大型数据库中的匹配地址记录。

地址表包含 SQL 表中的 20+ 列,需要使用不同的 OData 参数(EqualTo、Contains、Starts With 等)进行查询。

尝试使用 OData,而不将 DBContext 注入 API 控制器。这在当前架构中是不允许的。如何编写代码来实现这一点?

*我们使用 ProjectTo 让它工作。但是,OData Http 特定功能正在传递到非 Api 级别。 目前在 AppServices 中有 ODataQueryOptions。

我们如何将 Whole ODataQueryOptions 转换为 Linq 表达式查询(不管传入什么),这个资源只用于过滤器,How to transform OData filter to a LINQ expression?

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 数据库

资源: 也尝试使用它

How do I map an OData query against a DTO to another entity?

【问题讨论】:

我认为[Queryable] 属性仅适用于IQueryable 的结果函数。当您调用ToListAsync 时,查询实际上是对数据库执行的。更改您的代码以返回 db.AddressData 嗨@Max 好的,我如何将参数传递到可查询的存储库中?随意写完整的答案,我可以发送积分,谢谢 【参考方案1】:

我写这个函数已经很久了,但链接可能会有所帮助。 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://***.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()));
    

【讨论】:

嗨 @Remy,我正在寻找 linq 中的表达式树,更多 iqueryable 部分,我已经在代码中有 Applyto

以上是关于Net Core:在洋葱架构中使用OData,将查询参数转换为Linq的主要内容,如果未能解决你的问题,请参考以下文章

在 .NET Core Web API for MongoDB 中使用 OData

如何正确地将 OData 与 ASP.net Core 集成

使用 ASP.NET Core OData 8.0 映射动态 OData 路由

.Net Core 上的 OData 不会在 $select 上返回正确的结果

如何在 .Net Core 6.0 中结合 CosmosDB、Entity Framework 和 OData?

将 ASP.NET 身份与核心域模型解耦 - 洋葱架构