简体   繁体   English

Simple.Odata.Client-通过仅将修改后的属性发送到服务器来实现Odata修补程序实体

[英]Simple.Odata.Client - Odata Patch Entity by only sending modified properties to server

I'm using Simple Odata Client to perform CRUD operations in a WPF application. 我正在使用简单Odata客户端在WPF应用程序中执行CRUD操作。

I have a parent & a child entity: 我有一个父母和一个孩子实体:

public class Order
{
    public int OrderId{get;set;}
    public int Description{get;set;}
    public ObservableCollection<OrderLine> OrderLines {get;set;}
}
public class OrderLine
{
    public int OrderId{get;set;}
    public int OrderLineId{get;set;}
    public int ItenId{get;set;}
    public int ItemDescription{get;set;}
    public virtual Order Order {get;set;}
}

And I have a class for perform crud operation: 我有一个执行粗操作的类:

public class ManageOrders
{
    //Implements INotifyPropertyChanged
    Public Order Order;

    public void Get()
    {
        this.Order = packages = await client
                    .For<Order>()
                    .ByKey(1001).
                    .Expand(x.OrderLines).
                    .FindEntriesAsync();
    }

    public void Save()
    {
        if("NEW")
        {
            // Add new item and save
        }
        if("MODIFIED")
        {
            // save modified item
        }
    }

    public void Delete()
    {
        //Delete
    }   
}

在此处输入图片说明

I'm binding Parent entity properties to the header controls. 我将父实体属性绑定到标题控件。

TextBox.Text = Order.Description;

and child entity to DataGrid. 和子实体到DataGrid。

DataGrid.ItemSource = Order.OrderLines;

When I click the GET Button, Order will be fetched from DB. 当我单击GET按钮时,将从数据库中获取订单。 Then I change the data in Order and OrderLines. 然后,我更改Order和OrderLines中的数据。 Then I Delete a OrderLine and add two new OrderLines. 然后,我删除一个OrderLine并添加两个新的OrderLines。

As I'm using ObservarbleCollection , the changes will be automatically added to Source from UI. 当我使用ObservarbleCollection ,更改将自动从UI添加到Source。

Requirement 需求

When I click SAVE button all the changes should be submitted to the server. 当我单击“保存”按钮时,所有更改都应提交到服务器。 (Batch request is preferred). (最好是批处理请求)。

Question

How can I send only changed entities to the server through a PATCH request, without sending unmodified properties both in header and lines? 如何通过PATCH请求仅将更改的实体发送到服务器,而不在标头和行中发送未修改的属性?

What you are asking for here is IMO the Holy Grail of web services and client-side frameworks. 您在这里要问的是IMO是Web服务和客户端框架的圣杯。

Patch in OData makes it possible and simple to receive and process only changed properties for an object. OData中的修补程序使得仅接收和处理对象的已更改属性成为可能并且变得简单。

However it is up to the client to build the data packet appropriately, that can be done in 1 of two ways: 但是,由客户端来适当地构建数据包,可以通过以下两种方法之一来完成:

  1. Before sending, the client should compare the data to send against the data that was last retrieved to determine the properties that have changed. 在发送之前,客户端应将要发送的数据与最后检索到的数据进行比较,以确定已更改的属性。

  2. If the data on the client is wrapped in some kind of view model the view model could track (or watch) changes made to the properties. 如果客户端上的数据包装在某种视图模型中,则视图模型可以跟踪(或监视)对属性所做的更改。

Then on send, the client side must use this information to build a Delta of the object graph. 然后在发送时,客户端必须使用此信息来构建对象图的增量。

You haven't included any information on how you are generating your URIs to the backend service, so I don't want to guess but what ever the mechanism, 1 of the 2 strategies above will need to be implemented. 您还没有提供有关如何为后端服务生成URI的任何信息,所以我不想猜测,但是无论哪种机制,都需要实现上述两种策略中的一种。

If your backend is an OData v4 service then you may find the OData Client package a helpful place to start. 如果您的后端是OData v4服务,那么您可能会发现OData Client软件包是一个有用的起点。 See OData Client library for .NET and the following to generate the client side object graphs: OData v4 Client Code Generator . 请参阅用于.NET的OData客户端库和以下内容以生成客户端对象图: OData v4客户端代码生成器 You can use this against any service that implements the OData v4 specification, not only when you control the code for the backend. 您可以将其用于实现OData v4规范的任何服务,不仅是在控制后端代码时。

Supports multiple modes for batching as batching is often implemented differently across OData v4 Implementations. 支持批处理的多种模式,因为批处理通常在OData v4实现中以不同的方式实现。 For that reason I have left batching out of this discussion, but know that it is supported natively by these libraries and does work quite well. 因此,在本次讨论中我不再进行批处理,但是知道这些库本身支持批处理,并且效果很好。

For an example of usage of the generated classes see this SO question: What is the correct way to call patch from an odata client in web api 2 Or follow one of my unit tests: 有关使用生成的类的示例,请参见以下SO问题: 从Web api 2中的odata客户端调用补丁的正确方法是什么?或者遵循我的单元测试之一:

    [TestMethod]
    public void TestPatch()
    {
        var client = ArcoCloud.Gateway.Client.Runtime.GetGatewayClient();
        var changeTracker = new Microsoft.OData.Client.DataServiceCollection<ArcoCloud.Gateway.Client.ArcoCloud_DataModel.Device>(client.Devices);

        // just change device 96
        var device = changeTracker.Single(d => d.Id == 96);
        device.Notes = "This is a test note to check if patch works natively";

        client.SaveChanges();
        /* Traced in Fiddler4
        PATCH: {
          "@odata.type": "#ArcoCloud_DataModel.Device",
          "Notes": "This is a test note to check if patch works natively"
        }*/
    }

Notice here to get the client to only send the modified properties are using a Microsoft.OData.Client.DataServiceCollection which inherits from ObservableCollection, but has the additional benefits of keeping an internal track of the changes to the objects in it's query. 请注意,要使客户端仅发送修改后的属性,请使用从ObservableCollection继承的Microsoft.OData.Client.DataServiceCollection,但它还具有在内部跟踪查询中对象更改的其他好处。 see DataServiceCollection Class . 请参见DataServiceCollection类

If you do use the OData Client Library and the Generated classes you can easily query the data service without the DataServiceCollection, but if you do that, updates will PUT the entire object graph. 如果确实使用OData客户端库和Generated类,则可以在没有DataServiceCollection的情况下轻松查询数据服务,但是如果这样做,则更新将放置整个对象图。 You will also find the syntax to save changes back quite wordy and hard to use. 您还会发现将更改保存回来的语法非常罗and并且难以使用。 This is by design, to write back you should use the DataServiceCollection. 这是设计使然,要回写您应该使用DataServiceCollection。 The framework offers the simply query mechanism so that you can simplify the processes in your apps, Querying/browsing/filtering data can be isolated from the code that a data edit window might use to load and save it's data. 该框架提供了简单的查询机制,因此您可以简化应用程序中的过程,可以将查询/浏览/过滤数据与数据编辑窗口可能用于加载和保存其数据的代码隔离开。

That's the official MS way to interact with OData v4 services from C# code. 这是通过C#代码与OData v4服务进行交互的官方MS方法。 The beauty of the T4 templates is that you can customize the template where needed or extend the generated partial classes so that your business logic does not get overridden when the classes are re-generated T4模板的优点在于,您可以在需要的地方自定义模板,或者扩展生成的部分类,以便在重新生成类时不会覆盖业务逻辑。

You can roll your own mechanism to support this if you want, just remember the two options, either track the changes as they happen, or use comparison before save to identify which fields have changed. 如果需要,您可以滚动自己的机制来支持此操作,只需记住两个选项,要么跟踪更改的发生,要么在保存之前使用比较来确定哪些字段已更改。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM