|
本文属于 OData 系列
引言
在 OData 中,EDM(Entity Data Model) 代表“实体数据模型”,它是一种用于表示 Web API 中的结构化数据的格式。EDM 定义了可以由 OData 服务公开的数据类型、实体和关系。 EDM 也提供了一些规则来描述数据模型中的实体之间的关系,例如继承、关联和复合类型。EDM 是 OData 协议的核心组成部分之一,它允许客户端和服务器之间以一致的方式交换和操作数据。
EDM 与实体对象模型
我刚接触 EDM 时恰好是与 EF Core 一起使用,就非常不理解这个现象:明明已经在 EF Core 中已经定义了模型,为啥还需要单独配置一个 EDM?
其实,EDM 和实体框架(EF)Core 中的实体对象虽然都用于数据建模,但却是不同的概念:在 EF Core 中,实体对象表示数据库中的表或视图,而 EDM 定义了 OData 服务中的数据结构,包括实体、属性、导航属性等。可以理解实体对象是为数据库服务,而 EDM 是用于数据开放服务的。
虽然 EDM 和 EF Core 中的实体对象都具有一些相似之处,例如它们都有属性和关系,甚至你也可以直接返回实体模型用提供给 OData 让其动态自动生成 EDM 模型(Non-ODM 模式),但是依然建议使用 EDM 模型,主要是有几个方面:
- 实体框架中的实体类可能包含与 OData 服务定义不同的属性。例如,实体框架中的实体类可能包含用于持久化和跟踪状态的属性,而这些属性可能并不需要在 OData 服务中公开。
- 实体框架中的实体类可能使用与 OData 服务定义不同的命名约定。例如,实体框架中的实体类可能使用 PascalCase(首字母大写)命名约定,而在 OData 服务中的 EDM 可以使用 camelCase(首字母小写)命名约定。
- 实体框架中的实体类可能包含与 OData 服务定义不同的数据结构。例如,联合主键的实现用于 OData 查询较为麻烦,可以配置 EDM 使得 OData 对外服务不使用联合主键。
EDM 配置
在配置 OData 时,我们需要在代码中提供 EDM 对象。- .AddRouteComponents(AuthorizeHelper.PREFIX, EdmHelper.GetEdmModels());
复制代码 GetEdmModels 函数返回一个 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 对象,这个对象帮助我们自动实现了很多配置内容。如果我们使用其他的方式就不那么简单了。实际上配置 EDM 总共有三种方式。
我一般只使用 Convention 的配置方法,因此这里引用官方网站的例子,详情请见 Introduction to the model builders - OData | Microsoft Learn
Explicit
如果模型通过 new EdmModel() 构建,那么构建的是无类型模型,相当于你不依赖现有的 CLR 类型凭空构建了一个模型。- 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() 构建,那么构建模型时可以依据现有的 CLR 对象进行构建,不过依然需要配置每一个属性、操作等。- 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();
- }
复制代码 相当于前一种方法已经有了很大改进,我们可以依赖现有的结构,而不再需要手动去命名了。
Convention
更进一步,我们可以使用惯例 ( Convention )方式,模型依赖 new ODataConventionModelBuilder () 构建,这个是代码最少的,整个模型的配置按照 OData RESTful 惯例实现。- public static IEdmModel GetEdmModels()
- {
- ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
- var device = builder.EntitySet<DeviceInfo>("DeviceInfos").EntityType;
- return builder.GetEdmModel();
- }
复制代码Convention 涉及的内容很多,有机会以后会详细解释惯例生成 EDM 这种模式。
常用 EDM 配置
EDM 配置项目繁多,我们常用的有:
- var device = builder.EntitySet<DeviceInfo>("DeviceInfos").EntityType;
复制代码- //对于实体上的Action
- device.Action("Upload");
- //对于集合上的Action
- device.Collection.Action("Upload");
复制代码- //对于实体上的Function
- device.Function("Data").Returns<string>();
- //对于集合上的Function
- device.Collection.Function("Data").Returns<string>();
复制代码对 Function 以及 Action 的详细介绍,请期待后续文章。
访问 EDM 模型
OData 服务提供了 $metadata 终结点,可以从服务的根 URL 后添加 $metadata 来访问。例如以下是一个可以直接访问的 EDM 模型,以 XML 形式提供:- http://services.odata.org/TripPinRESTierService/$metadata
复制代码 此外,也可以使用某些工具(如 Microsoft 的 OData Connected Service)来自动生成客户端代码,并从服务中获取元数据。这些工具通常会从服务的根 URL 下载 $metadata 文件,并将其解析为客户端代码。
来源:https://www.cnblogs.com/podolski/archive/2023/05/11/17390887.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作! |
|