简体   繁体   English

OData-Client:如何在新实体上重置链接

[英]OData-Client: How to Reset Link on new entity

I consume a OData-Service with the WCF OData client . 我使用WCF OData客户端使用OData-Service。 In my application when an entity is created, a linked property is set by default to an object: 在我的应用程序中,当创建实体时,默认情况下将链接属性设置为对象:

var defaultPackage = _service.GetDefaultPackage();
var newCar = new Car
{
    Key = "Unique identifier",
    Package = defaultPackage,
    Name = _name
};
_odata.AddToEntity(newCar);
_odata.SetLink(newCar, nameof(Car.Package), newCar.Package);

Then the user can change the values of the car via an user interface. 然后,用户可以通过用户界面更改汽车的值。 Changes of non primitive properties of instance are autransmitted to the service context. 实例的非原始属性的更改会自动传输到服务上下文。 This is done automatically via the INotifyPropertyChanged interface of the car (This interface is automatically implemented for all entities by the odata code generator). 这是通过carINotifyPropertyChanged接口自动完成的(此接口由odata代码生成器自动为所有实体实现)。

private void PropertyChanged(object sender, PropertyChangedEventArgs e)
{ 
    var car = (Car)sender;
    var newValue = GetPropertyValueByReflection(car, e.PropertyName);
    _odata.SetLink(car, e.PropertyName, newValue);
}

Among other things the user can delete the package of the car. 除其他事项外,用户可以删除汽车包裹。 So the property Package gets the value null . 因此,属性Package获得值null

The problem with the solution is now, that the service context does not reset the link for Package , but transfers it at _odata.SaveChanges(SaveChangesOptions.Batch) to the server. 解决方案的问题在于,服务上下文不会重置Package的链接,而是将其通过_odata.SaveChanges(SaveChangesOptions.Batch)传输到服务器。 This is the batch request: 这是批处理请求:

--batch_0abebbdc-969a-475a-b1da-a94a1733c6ae
Content-Type: multipart/mixed; boundary=changeset_3e2db159-7696-44af-bb51-00d2f48ed944

--changeset_3e2db159-7696-44af-bb51-00d2f48ed944
Content-Type: application/http
Content-Transfer-Encoding: binary

POST http://some-url.to/odata/Cars/Car HTTP/1.1
Content-ID: 5
Content-Type: application/atom+xml
DataServiceVersion: 1.0;NetFx
MaxDataServiceVersion: 3.0;NetFx
Accept: application/atom+xml,application/xml
Accept-Charset: UTF-8
User-Agent: Microsoft ADO.NET Data Services

<?xml version="1.0" encoding="utf-8"?>
<entry xmlns="http://www.w3.org/2005/Atom" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
    <id />
    <title />
    <updated>2017-06-21T10:58:55Z</updated>
    <author>
        <name />
    </author>
    <content type="application/xml">
        <m:properties>
            <d:Key>Unique identifier</d:Key>
            <d:Name>VW Caddy</d:Name>
        </m:properties>
    </content>
</entry>
--changeset_3e2db159-7696-44af-bb51-00d2f48ed944
Content-Type: application/http
Content-Transfer-Encoding: binary

DELETE $5/$links/Package HTTP/1.1
Content-ID: 10
DataServiceVersion: 1.0;NetFx
MaxDataServiceVersion: 3.0;NetFx
Accept: application/atom+xml,application/xml
Accept-Charset: UTF-8
User-Agent: Microsoft ADO.NET Data Services

--changeset_3e2db159-7696-44af-bb51-00d2f48ed944--
--batch_0abebbdc-969a-475a-b1da-a94a1733c6ae--

The server answers with an errer, because there is no link to be deleted. 服务器没有回答,因为没有链接要删除。 Does anybody know a solution for this problem as it is described here to use SetLink(source, propertyName, null) to remove the link. 是否有人知道这个问题的解决方案,因为它是描述在这里使用SetLink(source, propertyName, null)要删除链接。

Finally I found a solution that now works for me. 最终,我找到了一个对我现在有效的解决方案。 If the entity is new and there is a link set, SetLink(source, propertyName, null) cannot be used. 如果实体是新实体,并且有链接集,则不能使用SetLink(source, propertyName, null) Instead of that DetachLink(source, propertyName, oldTarget) must be used. 而不是那个DetachLink(source, propertyName, oldTarget)必须使用DetachLink(source, propertyName, oldTarget) I achieve this in the following way: 我可以通过以下方式实现:

private void PropertyChanged(object sender, PropertyChangedEventArgs e)
{ 
    var car = (Car)sender;
    var newValue = GetPropertyValueByReflection(car, e.PropertyName);
    object existingTarget;
    if ((newValue == null) && IsAdded(car) &&
         ThereExistsAnExistingLink(car, e.PropertyName, out existingTarget))
        _odata.DetachLink(car, e.PropertyName, existingTarget);
    else
        _odata.SetLink(car, e.PropertyName, newValue);
}

private bool IsAdded(object entity)
{
    return _odata.GetEntityDescriptor(entity).State.HasFlag(EntityStates.Added);
}

private bool ThereExistsAnExistingLink(object entity, 
                                       string propertyName, 
                                       out object existingTarget)
{
    var linkDescriptor = _context.Links.FirstOrDefault(
                           ld => ld.Source == _source && 
                                 ld.SourceProperty == _sourceProperty &&
                                !ld.HasStates(EntityStates.Detached)
                           );
    if (linkDescriptor != null)
    {
        existingTarget = linkDescriptor.Target;
        return true;
    }
    existingTarget = null;
    return false;
}

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

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