OData WebAPI實踐-Non-EDM模式

波多爾斯基發表於2023-05-12

本文屬於OData系列文章

前文說到了 EDMOData 之間的關係,具有 EDMOData 提供了強大的查詢能力,但是 OData 並不必須要配置 EDM,我們也可以使用 Non-EDM 方案。

Non-EDM

所謂 Non-EDM ,並不是說在 OData 執行時不需要 EDM 配置了,而是由 OData 動態生成的 EDM,進而實現 OData 功能。

配置

配置 OData 就可以不需要在內配置 GetEdmModel()。當然,如果你需要配置路由,因為函式引數需要,我們可以返回一個預設的空 EDM。

            services.AddControllers()
                .AddOData(opt => opt.Count().Filter().Expand().Select().OrderBy().SetMaxTop(5)
                );

控制器

為了實現 OData 的功能,我們依然需要給控制器與函式上增加一些配置:

	[ApiController]
    [Route("api/[controller]")]
    public class AccountsController : ControllerBase
    {
        [HttpGet]
        public IActionResult Get(ODataQueryOptions<Account> queryOptions)
        {
            var querable = accounts.AsQueryable<Account>();
            var finalQuery = queryOptions.ApplyTo(querable);
            return Ok(finalQuery);
        }

        [HttpGet("{id}")]
        public IActionResult Get(Guid id, ODataQueryOptions<Account> queryOptions)
        {
            var accountQuery = accounts.Where(c => c.AccountId == id);
            if (!accountQuery.Any())
            {
                return NotFound();
            }

            var finalQuery = queryOptions.ApplyTo(accountQuery.AsQueryable<Account>()) as IQueryable<dynamic>;
            var result = finalQuery.FirstOrDefault();

            if (result == null)
            {
                return NotFound();
            }

            return Ok(result);
        }
    }

這裡程式碼使用了 ODataQueryOptions,因此沒有使用 [EnableQuery]

我們檢視 OData 路由,Account 不在路徑中了。
image

但是我們還是可以使用 OData 語法來進行查詢:

image

細心的同學發現:

  • 我使用了 $count,但是返回的內容並沒有計數結果。
  • 返回物件中沒有 @odata.context 指示對應實體的 EDM 配置資訊。
  • 在定義了 OData EDM 的物件中,返回陣列型別是 "Value":[] 的形式,而沒有定義 EDM 的物件會直接返回陣列物件,這個在與前端進行互動的過程中需要特別注意。

限制

不使用 EDM 模式,在使用 OData 查詢時還是有很多限制:

  • 類似$count 之類的語句暫時還不支援。
  • 不支援複雜物件(ComplexType)的 $select。
  • 無法配置 EntityType 的 Ignore ,不支援一些 OData 的高階特性。
  • 不能實現 OData Routing 對映,可能會造成 Versioning 之類的操作困難。

因此,還是建議在使用 OData 時使用並正確配置 EDM,這樣可以獲得最全面的 OData 特性支援。

相關文章