本文屬于 OData 系列
引言
在 OData 中,EDM(Entity Data Model) 代表“實體數(shù)據(jù)模型”,它是一種用于表示 Web API 中的結(jié)構(gòu)化數(shù)據(jù)的格式。EDM 定義了可以由 OData 服務(wù)公開的數(shù)據(jù)類型、實體和關(guān)系。 EDM 也提供了一些規(guī)則來描述數(shù)據(jù)模型中的實體之間的關(guān)系,例如繼承、關(guān)聯(lián)和復(fù)合類型。EDM 是 OData 協(xié)議的核心組成部分之一,它允許客戶端和服務(wù)器之間以一致的方式交換和操作數(shù)據(jù)。
EDM 與實體對象模型
我剛接觸 EDM 時恰好是與 EF Core 一起使用,就非常不理解這個現(xiàn)象:明明已經(jīng)在 EF Core 中已經(jīng)定義了模型,為啥還需要單獨配置一個 EDM?
其實,EDM 和實體框架(EF)Core 中的實體對象雖然都用于數(shù)據(jù)建模,但卻是不同的概念:在 EF Core 中,實體對象表示數(shù)據(jù)庫中的表或視圖,而 EDM 定義了 OData 服務(wù)中的數(shù)據(jù)結(jié)構(gòu),包括實體、屬性、導(dǎo)航屬性等。可以理解實體對象是為數(shù)據(jù)庫服務(wù),而 EDM 是用于數(shù)據(jù)開放服務(wù)的。
雖然 EDM 和 EF Core 中的實體對象都具有一些相似之處,例如它們都有屬性和關(guān)系,甚至你也可以直接返回實體模型用提供給 OData 讓其動態(tài)自動生成 EDM 模型(Non-ODM 模式),但是依然建議使用 EDM 模型,主要是有幾個方面:
- 實體框架中的實體類可能包含與 OData 服務(wù)定義不同的屬性。例如,實體框架中的實體類可能包含用于持久化和跟蹤狀態(tài)的屬性,而這些屬性可能并不需要在 OData 服務(wù)中公開。
- 實體框架中的實體類可能使用與 OData 服務(wù)定義不同的命名約定。例如,實體框架中的實體類可能使用 PascalCase(首字母大寫)命名約定,而在 OData 服務(wù)中的 EDM 可以使用 camelCase(首字母小寫)命名約定。
- 實體框架中的實體類可能包含與 OData 服務(wù)定義不同的數(shù)據(jù)結(jié)構(gòu)。例如,聯(lián)合主鍵的實現(xiàn)用于 OData 查詢較為麻煩,可以配置 EDM 使得 OData 對外服務(wù)不使用聯(lián)合主鍵。
EDM 配置
在配置 OData 時,我們需要在代碼中提供 EDM 對象。
.AddRouteComponents(AuthorizeHelper.PREFIX, EdmHelper.GetEdmModels());
GetEdmModels
函數(shù)返回一個 IEdmModel
對象。
public static IEdmModel GetEdmModels()
{
ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
var device = builder.EntitySet<DeviceInfo>("DeviceInfos").EntityType.HasKey(p => p.DeviceId);
device.Action("Upload");
builder.EnableLowerCamelCase();
return builder.GetEdmModel();
}
以上代碼中對 DeviceInfo 類型定義了一個實體對象,其具有 DeviceId
作為主鍵,擁有一個名為 Upload
的 Action。并且對所有的 EDM 對象啟用了 LowerCamelCase 支持。上面的感覺是挺簡單的是吧,注意我們使用到了 ODataConventionModelBuilder
對象,這個對象幫助我們自動實現(xiàn)了很多配置內(nèi)容。如果我們使用其他的方式就不那么簡單了。實際上配置 EDM 總共有三種方式。
我一般只使用 Convention 的配置方法,因此這里引用官方網(wǎng)站的例子,詳情請見 Introduction to the model builders - OData | Microsoft Learn
Explicit
如果模型通過 new EdmModel()
構(gòu)建,那么構(gòu)建的是無類型模型,相當(dāng)于你不依賴現(xiàn)有的 CLR 類型憑空構(gòu)建了一個模型。
public IEdmModel GetEdmModel()
{
EdmModel model = new EdmModel();
EdmEntityType customer = new EdmEntityType("WebApiDocNS", "Customer");
customer.AddKeys(customer.AddStructuralProperty("CustomerId", EdmPrimitiveTypeKind.Int32));
customer.AddStructuralProperty("Location", new EdmComplexTypeReference(address, isNullable: true));
model.AddElement(customer);
EdmEntityType order = new EdmEntityType("WebApiDocNS", "Order");
order.AddKeys(order.AddStructuralProperty("OrderId", EdmPrimitiveTypeKind.Int32));
order.AddStructuralProperty("Token", EdmPrimitiveTypeKind.Guid);
model.AddElement(order);
return model;
}
Non-convention
如果模型是依賴 new ODataModelBuilder()
構(gòu)建,那么構(gòu)建模型時可以依據(jù)現(xiàn)有的 CLR 對象進行構(gòu)建,不過依然需要配置每一個屬性、操作等。
public static IEdmModel GetEdmModel()
{
var builder = new ODataModelBuilder();
var customer = builder.EntityType<Customer>();
customer.HasKey(c => c.CustomerId);
customer.ComplexProperty(c => c.Location);
customer.HasMany(c => c.Orders);
var order = builder.EntityType<Order>();
order.HasKey(o => o.OrderId);
order.Property(o => o.Token);
return builder.GetEdmModel();
}
相當(dāng)于前一種方法已經(jīng)有了很大改進,我們可以依賴現(xiàn)有的結(jié)構(gòu),而不再需要手動去命名了。
Convention
更進一步,我們可以使用慣例 ( Convention )方式,模型依賴 new ODataConventionModelBuilder ()
構(gòu)建,這個是代碼最少的,整個模型的配置按照 OData RESTful 慣例實現(xiàn)。
public static IEdmModel GetEdmModels()
{
ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
var device = builder.EntitySet<DeviceInfo>("DeviceInfos").EntityType;
return builder.GetEdmModel();
}
Convention 涉及的內(nèi)容很多,有機會以后會詳細解釋慣例生成 EDM 這種模式。
常用 EDM 配置
EDM 配置項目繁多,我們常用的有:
- 配置實體(主鍵)
var device = builder.EntitySet<DeviceInfo>("DeviceInfos").EntityType;
- 配置(集合) Action
//對于實體上的Action
device.Action("Upload");
//對于集合上的Action
device.Collection.Action("Upload");
- 配置(集合) Function
//對于實體上的Function
device.Function("Data").Returns<string>();
//對于集合上的Function
device.Collection.Function("Data").Returns<string>();
對 Function 以及 Action 的詳細介紹,請期待后續(xù)文章。
訪問 EDM 模型
OData 服務(wù)提供了 $metadata
終結(jié)點,可以從服務(wù)的根 URL 后添加 $metadata
來訪問。例如以下是一個可以直接訪問的 EDM 模型,以 XML 形式提供:文章來源:http://www.zghlxwxcb.cn/news/detail-438768.html
http://services.odata.org/TripPinRESTierService/$metadata
此外,也可以使用某些工具(如 Microsoft 的 OData Connected Service)來自動生成客戶端代碼,并從服務(wù)中獲取元數(shù)據(jù)。這些工具通常會從服務(wù)的根 URL 下載 $metadata 文件,并將其解析為客戶端代碼。文章來源地址http://www.zghlxwxcb.cn/news/detail-438768.html
到了這里,關(guān)于OData WebAPI實踐-OData與EDM的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!