C# 如何发布OData实体并将其同时链接到多个现有实体?
如何将实体发布到OData端点,同时将其与正文中的其他现有实体关联C# 如何发布OData实体并将其同时链接到多个现有实体?,c#,odata,asp.net-core-webapi,odata-v4,C#,Odata,Asp.net Core Webapi,Odata V4,如何将实体发布到OData端点,同时将其与正文中的其他现有实体关联 考虑以下类结构(示例): Invoice和Person都是我域中的实体(因此Id属性)。假设两者都暴露在各自的EntitySet中,因此: GEThttp://host/odata/People(1) 返回Id=1的Person GEThttp://host/odata/Invoices(2) ?$expand='发卡机构,收件人' 返回Id=2的Invoice,并在有效负载中展开Issuer和Recipient 现在考
考虑以下类结构(示例):
Invoice
和Person
都是我域中的实体(因此Id
属性)。假设两者都暴露在各自的EntitySet中,因此:
返回GEThttp://host/odata/People(1)
Id=1的
Person
返回GEThttp://host/odata/Invoices(2) ?$expand='发卡机构,收件人'
Id=2的
,并在有效负载中展开Invoice
和Issuer
Recipient
现在考虑以下要求:
我想在系统中创建一个新发票,该发票将与现有的发卡机构和收件人关联 如何“告诉”OData框架我希望将给定的导航属性与现有实体关联?如何通知我的控制员行动,这是我的意图 理想情况下,我希望帖子主体的外观如下:
{ “发行人”:“/odata/People(1)”, “收件人”:“/odata/People(2)”, “Property1”:“someValue”, “财产2”:“100”, ... }POSThttp://host/odata/Invoices
颁发者
属性加载所需的“人员(1)”。如果不存在,则应返回错误的请求收件人
属性加载所需的“人员(2)”。如果不存在,则应返回错误的请求发票
实例,并从上面分配发卡机构
和收件人
,然后将其保存到数据库中entity/relation/$ref
语法使用特殊的PUT/POST URL配置事后关系。有了这样的语法,我可以做如下事情:
POSThttp://host/odata/Invoices
{“Property1”:“someValue”,“Property2”:“100”}
PUThttp://host/odata/Invoices(x) /Issuer/$ref
{“@odata.id”:http://host/odata/People(1) “}
PUThttp://host/odata/Invoices(x) /Recipient/$ref
{“@odata.id”:http://host/odata/People(2) “}
{
"Issuer": { "@odata.id": "/odata/People(1)" },
"Recipient": { "@odata.id": "/odata/People(2)" },
"Property1": "someValue",
"Property2": "100",
...
}
但我不知道如何从中读取/解析ID(比如如何在专用的Ref
方法中完成),甚至不知道OData标准是否支持这一点
现在,我将在模型和服务器中传递
ID
属性,假设这始终意味着一个现有关系,但这远远不够理想,因为它不够通用,会使我的API变得不灵活。最简单的解决方案是直接在模型中公开ForeignKey
属性。即使是MS文档中使用的模型也会暴露FKs
class Invoice
{
public int Id { get; set; }
public int Issuer_Person_Id { get; set; }
[ForeignKey(nameof(Issuer_Person_Id)]
public Person Issuer { get; set; }
public int Recipient_Person_Id { get; set; }
[ForeignKey(nameof(Recipient_Person_Id)]
public Person Recipient { get; set; }
// other properties
}
这并不会使您的API变得死板,而是使您的API更加灵活。
这也使您能够更好地控制模型的数据库实现,同时仍然不依赖于数据库引擎
在启用延迟加载的环境中,如果您需要检查相关实体的存在而不需要将其加载到内存中,那么包括FKs在内的环境还具有一些额外的性能优势
注意:通过在模型中包含FK,$ref
语法和批处理仍然可以使用,但是我们现在可以访问更实用的FK Id值,这些值可以在服务器端代码中轻松验证,就像发送值更容易一样
现在在补丁
或POST
中,我们可以直接使用id链接个人
记录
要实现这一点,客户端和服务器端都需要相同级别的信息/理解,因此它仍然是通用的,$metadata
文档充分描述了哪些FK字段链接了相关实体,但此处演示的良好命名约定会有所帮助
小心点:许多模型设计人员选择不公开
ForeignKey
属性的原因之一是,当您尝试发送或处理ForeignKey和相关实体时,存在歧义。对于
补丁
没有混淆,不能包含相关实体,对于POST
但是,如果请求中提供了相关实体以及FK,则相关实体通常被解释为创建/插入请求,FK被忽略
这在不同的实现框架中是不同的,但最终当同时提供FK和实体时,只能使用其中一个,这通常是因为实体更详细/具体,将优先于FK使用
因此,在启用FKs的情况下,我的建议是在客户端采取措施,确保您不会尝试将请求中的FK和相关实体发送回API
我同意您所建议的帖子中的@odata.id是一个合乎逻辑的结论,但是它提出了其他潜在的实施问题,这就是为什么协议提供了针对代表ForeignKey引用的$ref
端点的直接CRUD操作概念
ODataV4是专门声明性的,设计为针对单个资源的操作只影响该资源
class Invoice
{
public int Id { get; set; }
public int Issuer_Person_Id { get; set; }
[ForeignKey(nameof(Issuer_Person_Id)]
public Person Issuer { get; set; }
public int Recipient_Person_Id { get; set; }
[ForeignKey(nameof(Recipient_Person_Id)]
public Person Recipient { get; set; }
// other properties
}
{
"Issuer_Person_Id": 1,
"Recipient_Person_Id": 2,
"Property1": "someValue",
"Property2": "100",
...
}