У меня есть два объекта, которые ссылаются друг на друга.
[JsonObject(IsReference = true)]
[DataContract(IsReference = true, Namespace = "http://schemas.datacontract.org/2004/07/TrackableEntities.Models")]
[ProtoContract]
public class ProtoBufObject : ITrackable
{
[DataMember(Order = 3)]
public Guid Oid { get; set; }
[DataMember(Order = 4)]
[ProtoMember(4, AsReference = true)]
public ChildProtoBufObject child { get; set; }
[DataMember(Order = 1)]
public TrackingState TrackingState { get; set; }
[DataMember(Order = 2)]
public ICollection<string> ModifiedProperties { get; set; }
}
[JsonObject(IsReference = true)]
[DataContract(IsReference = true, Namespace = "http://schemas.datacontract.org/2004/07/TrackableEntities.Models")]
[ProtoContract]
public class ChildProtoBufObject : ITrackable
{
[DataMember(Order = 3)]
public Guid Oid { get; set; }
[DataMember(Order = 4)]
[ProtoMember(4, AsReference = true)]
public ProtoBufObject parent { get; set; }
[DataMember(Order = 1)]
public TrackingState TrackingState { get; set; }
[DataMember(Order = 2)]
public ICollection<string> ModifiedProperties { get; set; }
}
На клиенте я создаю экземпляры этих объектов и создаю «ассоциации».
ProtoBufObject parent = new ProtoBufObject()
{
Oid = Guid.NewGuid()
};
ChildProtoBufObject child = new ChildProtoBufObject()
{
Oid = Guid.NewGuid()
};
parent.child = child;
child.parent = parent;
Объекты будут сериализованы следующим образом:
ProtoBufFormatter formatter = new ProtoBufFormatter();
HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Post, requestUri);
requestMessage.Content = new ObjectContent<SearchParameters>(searchParameters, formatter);
А затем они будут отправлены по http на вебапи, где будут десериализованы с помощью WebApiContrib.Formatting.ProtoBuf.
В контроллере Webapi я получаю объекты с правильными отношениями, НО целостность отношений пошла не так. Я выгружаю объекты с Json в файл с этим фрагментом кода:
string json = JsonConvert.SerializeObject(samples);
//write string to file
string oid = samples.First().Oid.ToString();
System.IO.File.WriteAllText(@"D:\JsonTest\dummypath" + oid + ".txt", json);
А вот как выглядит этот текстовый файл
[{
"$id": "1",
"TrackingState": 0,
"ModifiedProperties": null,
"Oid": "8c00ea73-ac84-4130-b1a8-61e1df89f9bf",
"child": {
"$id": "2",
"TrackingState": 0,
"ModifiedProperties": null,
"Oid": "81026a01-7de2-4045-ac0a-314b3fd7360c",
"parent": {
"$id": "3",
"TrackingState": 0,
"ModifiedProperties": null,
"Oid": "8c00ea73-ac84-4130-b1a8-61e1df89f9bf",
"child": {
"$ref": "2"
}
}
}
}]
у ребенка есть "новый" родитель с id=3 вместо ref=1. Родительский элемент с идентификатором 3 имеет правильную ссылку на дочерний элемент.
Таким образом, кажется, что объект верхнего уровня не будет настроен правильно. Это огромная проблема с Entity Framework (вот почему я придумал эту проблему), потому что она использует ссылку на тип, а не только на свойства (что правильно).
Я также пробовал это с ProtoContract(DefaultRefencetype=true), но это сделало его еще хуже. Затем я получил от родителя с id=3 новый дочерний элемент с id=4.
Мой вопрос: как я могу заставить целостность объектов работать?
Я хочу:
[{
"$id": "1",
"TrackingState": 0,
"ModifiedProperties": null,
"Oid": "8c00ea73-ac84-4130-b1a8-61e1df89f9bf",
"child": {
"$id": "2",
"TrackingState": 0,
"ModifiedProperties": null,
"Oid": "81026a01-7de2-4045-ac0a-314b3fd7360c",
"parent": {
"$ref": "1"
}
}
}
}]
Изменить: строка Entity Framework
dbContext.Set<ProtoBufObject>.AddRange(myObjects);
выдает InvalidOperationException, потому что целостность моделей (родительская, дочерняя.родительская) различается.
Additional information: Conflicting changes to the role 'foo_bar_Target' of the relationship 'Entities.Context.foo_bar' have been detected.
Если я использую сериализатор Newtonsoft.Json на стороне клиента и отправляю его через WebApi (я использую те же объекты с теми же отношениями, что и в моем тесте Protobuf), Entity Framework может обрабатывать объекты. Поэтому должны быть какие-то различия между десериализованными объектами из Json и Protobuf. Вот почему я снова сериализовал объекты, чтобы увидеть различия.
Я также добавил в свой метод Put проверку ссылок:
if (protoBufObject != protoBufObject.child.parent)
{
throw new Exception("Instance integrity differs!");
}
как и ожидалось от файла json, это исключение выдается, поэтому ссылки действительно повреждены.
При запуске WebApi я использую следующий код:
config.Formatters.Add(new ProtoBufFormatter());
Там проблема? Нужно ли мне добавить дополнительную информацию в форматтеры?