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