如何在一个请求中更新OData实体并修改其导航属性?

时间:2022-12-21 02:19:55

I am trying to implement what I thought was a simple scenario using an OData service provided by WCF Data services (using the OData V3 application/json;odata=verbose payload format, for now. I may use the JSON Light format in the future). The basic scenario goes like this:

我正在尝试使用WCF数据服务提供的OData服务来实现我认为的简单场景(使用OData V3应用程序/ json; odata = verbose有效载荷格式,现在。我将来可能会使用JSON Light格式) 。基本情况如下:

I have two entities:

我有两个实体:

class Person 
{ 
  public int ID { get; set; }
  public string Name { get; set; } 
  public virtual PersonCategory Category { get; set; }
}

class PersonCategory
{
  public int ID { get; set; }
  public string Description { get; set; }
  public virtual ICollection<Person> People { get; set; }
}

Now, I want to create a simple edit page for a Person. This edit page might have an input for the Name, and an input or drop-down for the Category of the Person.

现在,我想为Person创建一个简单的编辑页面。此编辑页面可能具有Name的输入,以及Person类别的输入或下拉列表。

So, the scenario goes:

所以,场景如下:

  1. Code downloads the Person using $expand for the Category: GET /api.svc/People(1)?$expand=Category
  2. 代码使用$ expand下载人员类别:GET /api.svc/People(1)?$expand=Category
  3. User edits both the person's Name property and their Category.
  4. 用户编辑人员的姓名属性及其类别。
  5. Code for the page makes a single request to update that Person's Name and Category properties.
  6. 页面代码只发出一个请求来更新Person的Name和Category属性。

The key here is in "a single request". This is the part that I'm having trouble finding documentation for. I've seen examples where they split number 3 above into two requests. Something like this (I don't remember the exact format - I'm also not sure if you'd have to DELETE the Category link before doing the PUT):

这里的关键是“单一请求”。这是我找不到文档的部分。我见过他们将上面的数字3分成两个请求的例子。这样的事情(我不记得确切的格式 - 我也不确定你在做PUT之前是否必须删除Category链接):

PATCH /api.svc/People(1) with content: {"Name": "new name" }
PUT /api.svc/People(1)/$links/Category with content: { "url": "/api.svc/Categories(2)" }

But, I've also heard it said, but not demonstrated, that it's possible to implement this update as a single request with the change to the Category navigation property specified inline with the other changes to the Person entity. Could someone give me an example of how this might be done? Also, can you show me how it would be done with a many-to-many navigation property, as opposed to the one-to-many I've described above.

但是,我也听说过,但没有证明,可以将此更新实现为单个请求,并更改为与Person实体的其他更改内联指定的Category导航属性。有人能给我一个如何做到这一点的例子吗?另外,你能告诉我如何使用多对多导航属性,而不是我上面描述的一对多导航属性。

And finally, I'm currently using the verbose JSON format, V3. Would your answers to the questions above be different if I instead used the new JSON light format? If so, how?

最后,我目前正在使用详细的JSON格式V3。如果我改为使用新的JSON光格式,您对上述问题的回答是否会有所不同?如果是这样,怎么样?

3 个解决方案

#1


4  

Pratik's comment was the answer (Pratik if you'd like to repost this as an answer, I'll mark it as such - thanks!):

Pratik的评论就是答案(Pratik,如果您想将此作为答案重新发布,我会将其标记为 - 谢谢!):

Question: Do you want to update the category instance or do you want to update some of the properties of the category instance. There is no way to do the later other than batch. For the former, you can do something like: { "Name" : "new name", "Category" : { "__metadata" : { "uri" : "/api.svc/Categories(2)" }}}. Hope this helps. – Pratik

问题:是否要更新类别实例,或者是否要更新类别实例的某些属性。除了批处理之外没有其他方法可以做。对于前者,您可以执行以下操作:{“名称”:“新名称”,“类别”:{“_ _ metaadata”:{“uri”:“/ api.svc / Category(2)”}}}。希望这可以帮助。 - Pratik

#2


4  

I found two ways to represent navigation properties inline:

我找到了两种表示内联导航属性的方法:

application/json;odata=verbose - { "Name": "new name", "Category": { "__metadata": { "uri": "Categories(2)" }}}

application / json; odata = verbose - {“Name”:“new name”,“Category”:{“_ _ metaadata”:{“uri”:“Categories(2)”}}}

application/json - { "Name": "new name", "Category@odata.bind": "Categories(2)" }

application / json - {“Name”:“new name”,“Category@odata.bind”:“Categories(2)”}

#3


0  

You don't need a batch, anymore. You can do it in one call. You simply need to also send up the changed properties and let the repository handle the changed properties.

你不再需要批量了。你可以在一个电话中完成。您只需发送更改的属性并让存储库处理更改的属性。

public class Person 
{
   public string FirstName {get;set;}
   public string LastName {get;set;}
   public int Age {get;set;}
}

Let's say you notice the first name has a typo, Jhon and it is supposed to be John. You can edit the first name and send it up. So you have the following object model. You can get this in 1 of two ways:

假设你注意到第一个名字有一个拼写错误,Jhon应该是John。您可以编辑名字并发送。所以你有以下对象模型。您可以通过以下两种方式之一获得此信息:

  • Have two parameters and set BodyStyle = WebMessageBodyStyle.Wrapped
  • 有两个参数并设置BodyStyle = WebMessageBodyStyle.Wrapped
  • Just create a generic model object with two properties: Property one is of Type T and property 2 is a List.
  • 只需创建一个具有两个属性的通用模型对象:属性1属于T类,属性2属于List。

So you would send up this json:

所以你要发送这个json:

[{ FirstName = 'John' }, ['FirstName']]

Now on the server side, you can do what you need to do.

现在在服务器端,您可以执行您需要执行的操作。

If you don't want to send the changed properties, you can guess the changed properties by choosing any property whose value isn't the default property.

如果您不想发送更改的属性,可以通过选择其值不是默认属性的任何属性来猜测更改的属性。

{ FirstName = 'John' }

{FirstName ='John'}

Then you can use a few methods to see what properties have changed:

然后,您可以使用几种方法来查看哪些属性已更改:

  • Custom code per entity to make sure that each property is not the default value and set it. Requires a piece of code per entity.
  • 每个实体的自定义代码,以确保每个属性不是默认值并进行设置。每个实体需要一段代码。
  • Reflection to make sure that each property is not the default value. Requires 1 class for all entities. I did this back in 2014 here in Entity Framework: http://www.rhyous.com/2014/12/01/entityupdater-generic-helper-for-entity-framework/
  • 确保每个属性都不是默认值的反射。所有实体都需要1个班级。我在2014年的实体框架中做到了这一点:http://www.rhyous.com/2014/12/01/entityupdater-generic-helper-for-entity-framework/

#1


4  

Pratik's comment was the answer (Pratik if you'd like to repost this as an answer, I'll mark it as such - thanks!):

Pratik的评论就是答案(Pratik,如果您想将此作为答案重新发布,我会将其标记为 - 谢谢!):

Question: Do you want to update the category instance or do you want to update some of the properties of the category instance. There is no way to do the later other than batch. For the former, you can do something like: { "Name" : "new name", "Category" : { "__metadata" : { "uri" : "/api.svc/Categories(2)" }}}. Hope this helps. – Pratik

问题:是否要更新类别实例,或者是否要更新类别实例的某些属性。除了批处理之外没有其他方法可以做。对于前者,您可以执行以下操作:{“名称”:“新名称”,“类别”:{“_ _ metaadata”:{“uri”:“/ api.svc / Category(2)”}}}。希望这可以帮助。 - Pratik

#2


4  

I found two ways to represent navigation properties inline:

我找到了两种表示内联导航属性的方法:

application/json;odata=verbose - { "Name": "new name", "Category": { "__metadata": { "uri": "Categories(2)" }}}

application / json; odata = verbose - {“Name”:“new name”,“Category”:{“_ _ metaadata”:{“uri”:“Categories(2)”}}}

application/json - { "Name": "new name", "Category@odata.bind": "Categories(2)" }

application / json - {“Name”:“new name”,“Category@odata.bind”:“Categories(2)”}

#3


0  

You don't need a batch, anymore. You can do it in one call. You simply need to also send up the changed properties and let the repository handle the changed properties.

你不再需要批量了。你可以在一个电话中完成。您只需发送更改的属性并让存储库处理更改的属性。

public class Person 
{
   public string FirstName {get;set;}
   public string LastName {get;set;}
   public int Age {get;set;}
}

Let's say you notice the first name has a typo, Jhon and it is supposed to be John. You can edit the first name and send it up. So you have the following object model. You can get this in 1 of two ways:

假设你注意到第一个名字有一个拼写错误,Jhon应该是John。您可以编辑名字并发送。所以你有以下对象模型。您可以通过以下两种方式之一获得此信息:

  • Have two parameters and set BodyStyle = WebMessageBodyStyle.Wrapped
  • 有两个参数并设置BodyStyle = WebMessageBodyStyle.Wrapped
  • Just create a generic model object with two properties: Property one is of Type T and property 2 is a List.
  • 只需创建一个具有两个属性的通用模型对象:属性1属于T类,属性2属于List。

So you would send up this json:

所以你要发送这个json:

[{ FirstName = 'John' }, ['FirstName']]

Now on the server side, you can do what you need to do.

现在在服务器端,您可以执行您需要执行的操作。

If you don't want to send the changed properties, you can guess the changed properties by choosing any property whose value isn't the default property.

如果您不想发送更改的属性,可以通过选择其值不是默认属性的任何属性来猜测更改的属性。

{ FirstName = 'John' }

{FirstName ='John'}

Then you can use a few methods to see what properties have changed:

然后,您可以使用几种方法来查看哪些属性已更改:

  • Custom code per entity to make sure that each property is not the default value and set it. Requires a piece of code per entity.
  • 每个实体的自定义代码,以确保每个属性不是默认值并进行设置。每个实体需要一段代码。
  • Reflection to make sure that each property is not the default value. Requires 1 class for all entities. I did this back in 2014 here in Entity Framework: http://www.rhyous.com/2014/12/01/entityupdater-generic-helper-for-entity-framework/
  • 确保每个属性都不是默认值的反射。所有实体都需要1个班级。我在2014年的实体框架中做到了这一点:http://www.rhyous.com/2014/12/01/entityupdater-generic-helper-for-entity-framework/