从客户端删除一个请求中的所有相关OData实体

本文关键字:实体 OData 请求 删除 客户端 一个 | 更新日期: 2023-09-27 18:08:38

以Northwind数据库为例,每个Customer都有一个Orders集合。我想在一个请求中删除特定客户与其所有订单之间的所有引用。

看起来我可以用DELETE http://services.odata.org/V4/Northwind/Northwind.svc/Customers('ANTON')/Orders做到这一点(基于规范),但我想知道客户端库是否支持这一点。

我使用Microsoft.OData.Client作为c#客户端库,Apache Olingo (v4)用于Java,而BreezeJS用于JavaScript。如能举个例子,我将不胜感激。

编辑:澄清我只是删除引用,而不是实际删除实体本身。

从客户端删除一个请求中的所有相关OData实体

正如swl10所说,您需要依次删除每个引用。但是OData支持$batch。您可以将所有删除方法放在一个请求中。代码如下:

DemoService dsc = new DemoService(new Uri("http://services.odata.org/V4/OData/(S(ut2byeiaglm424a0pbovpo33))/OData.svc/"));
var product = dsc.Products.Expand("Categories").Where(p => p.ID == 1).Single();
foreach (var c in product.Categories)
{
    dsc.DeleteLink(product, "Categories", c);
}
dsc.SaveChanges(SaveChangesOptions.BatchWithSingleChangeset);

您将发现这个SaveChanges将只发送一个请求$batch。在有效负载中,有两个内部DELETE请求。

考虑到前面对这个问题的澄清,即您希望删除引用而不是实体本身,答案似乎是否定的,您不能做您想做的事情。

在OData 4(您链接到的规范)中,使用$ref获得引用,而不是直接寻址实体。因此,您感兴趣的链接是这个:

http://services.odata.org/V4/Northwind/Northwind.svc/Customers('ANTON')/Orders/$ref

不幸的是,你不能做你想做的,因为协议说(语法改进):

处理单个实体引用的资源路径可以在DELETE请求中使用解除两个实体的关联。中可以使用寻址引用集合的资源路径如果它们后面跟着系统查询选项$id,则删除请求集合中的实体引用。

规范的编写者为了从协议中删除您想要执行的操作已经遇到了一些麻烦。你必须依次删除每个引用,你不能在一个协议请求中删除整个引用集合。

您只是想删除客户('ANTON')和订单之间的引用,还是删除客户('ANTON')下的订单实体?

如果以后需要,服务应该不按照协议提供这种Delete。

如果您只是想删除引用,您可以尝试从客户端"PATCH"Customers('ANTON')"。

如果我理解正确,您想要删除父实体及其所有子实体?你可以这样做:

1/删除实体及其导航属性,这是Jay Traband建议的"最简单的方法"。

2/另一种方法,你可以为每个实体设置:

var deletedEntities = Array();
Customers.entityAspect.setDeleted();
deletedEntities.push(Customers);
for( var i=0; i<Customers().Orders().length; i++){
    Customers().Orders()[i].entityAspect.setDeleted();
    deletedEntities.push(Customers().Orders()[i]);
}
manager.saveChanges(deletedEntities).then(saveSucceed).fail(saveFailed);
以上是我使用的两种方法。如果你找到更好的解决办法,请告诉我。