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

OData-Client: How to Reset Link on new entity

我使用 WCF OData client 的 OData 服务。在创建实体时,在我的应用程序中,默认情况下将 linked 属性 设置为一个对象:

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);

然后用户可以通过用户界面更改汽车的值。实例的非原始属性的更改自动传输到服务上下文。这是通过 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);
}

除其他外,用户可以删除汽车包裹。所以 属性 Package 得到值 null

现在解决方案的问题是,服务上下文不会为 Package 重置 link,而是在 _odata.SaveChanges(SaveChangesOptions.Batch) 将其传输到服务器。这是批量请求:

--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 /$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--

服务器响应错误,因为没有要删除的 link。有没有人知道这个问题的解决方案,因为它被描述为 here 使用 SetLink(source, propertyName, null) 删除 link.

我终于找到了适合我的解决方案。如果实体是新的并且设置了link,则无法使用SetLink(source, propertyName, null)。而不是必须使用 DetachLink(source, propertyName, oldTarget)。我通过以下方式实现此目的:

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;
}