考虑以下示例:
OData 服务层公开 Order 和 OrderLine 资源。消费者检索 Order 及其相关的 OrderLines。消费者编辑 Order,编辑 1 个 OrderLine,删除 1 个 OrderLine 并创建 1 个 OrderLine。消费者如何保存所有这些更改以确保更改全部或全无?
根据我对 OData 的了解,这将作为多个服务调用发送:
PUT /api/Order/9999
PUT /api/OrderLine/1001
DELETE /api/OrderLine/1002
POST /api/OrderLine/1002
每个调用都是无状态的和独立的,服务器将无法确定何时开始和结束事务。
我考虑了各种解决方案,但我不确定它们中的任何一个是否有效:
解决方案 1)让 Order 资源包含 OrderLine 信息。使用此解决方案,将使用“PUT /api/Order/9999”进行单个服务调用,其中包含所有 OrderLine 更改。这个策略看起来不错,因为它将消费者从服务器上的交易细节中抽象出来。但是,当同时使用 Breeze 和 WCF 数据服务客户端进行 PUT 时,我找不到将 OrderLine 集合包含到 Order 实体中的方法。另外,我不确定如何在订单中传达删除 OrderLine。OData 规范中是否有任何内容可以实现这一点?我发现可以在规范的第 10.3.2.2 节中发布相关实体。在放置实体时,我没有发现任何类似的创建/更新/删除相关实体的东西。
解决方案 2)使用 OData 的 $batch 操作会将 4 个服务调用作为一个发送。我不确定 $batch 功能的目的是为了提高性能还是为了将相关的服务调用分组到事务中。使用 $batch 进行交易,消费者有责任确定在同一批次中发送哪些服务调用。这是适当的关注点分离吗?在服务器端,批处理程序可能会变得复杂。如果需要在 Order 和 OrderLine 之间进行任何验证,则批处理处理程序将需要在尝试数据库事务之前重组这些对象并验证它们。
解决方案 3)公开 Begin 和 End 事务服务调用。同样,这将向消费者公开实现细节。我认为其含义与解决方案 2 非常相似。
该解决方案必须在 .NET 4.0 上运行,并且服务调用必须在 .NET 和 javascript 客户端上运行。可扩展性不是问题。我正在使用“Web API OData”,它永远不会支持 .NET 4.0 中的 $batch 功能,但可以切换到“WCF 数据服务”。我选择 OData 是因为它的检索功能,但如果 CUD 操作的事务在没有 OData 的情况下工作得更好,我愿意接受建议。一种可能性是继续将 OData 用于我的应用程序的高级搜索屏幕,但对 CUD 使用常规 REST 服务。