I have two objects that reference each other.
[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; } }
On the client, I create these objects and create “associations”.
ProtoBufObject parent = new ProtoBufObject() { Oid = Guid.NewGuid() }; ChildProtoBufObject child = new ChildProtoBufObject() { Oid = Guid.NewGuid() }; parent.child = child; child.parent = parent;
Objects will be serialized as follows:
ProtoBufFormatter formatter = new ProtoBufFormatter(); HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Post, requestUri); requestMessage.Content = new ObjectContent<SearchParameters>(searchParameters, formatter);
And how they will be sent via http to Webapi, where it will be deserialized using WebApiContrib.Formatting.ProtoBuf.
In the Webapi controller, I get objects with the correct relationships, but the integrity of the relationship went wrong. I dump objects from Json to a file using this piece of code:
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);
And here is what this text file looks like
[{ "$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" } } } }]
the child has a "new" parent with id = 3 instead of ref = 1. The parent id = 3 has the correct link to the child.
Thus, this means that the top-level object will not be configured correctly. This is a huge problem with the Entity Framework (why I ran into this problem) because it uses a type reference, not just for properties (which are correct).
I also tried it with ProtoContract (DefaultRefencetype = true), but that made it even worse. Then I received from the parent with id = 3 a new child with id = 4.
My question is: how can I make the integrity of objects work?
I want:
[{ "$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" } } } }]
Edit: Entity Framework String
dbContext.Set<ProtoBufObject>.AddRange(myObjects);
throws an InvalidOperationException because the integrity of the models (parent, child.parent) is different.
Additional information: Conflicting changes to the role 'foo_bar_Target' of the relationship 'Entities.Context.foo_bar' have been detected.
If I use the client-side Newtonsoft.Json serializer and send it via WebApi (I use the same objects with the same relationships as with my Protobuf test), the Entity Framework can process the objects. Therefore, there should be some differences between the deserialized objects from Json and Protobuf. This is why I serialize objects again to see the differences.
I also added a link to my Put method:
if (protoBufObject != protoBufObject.child.parent) { throw new Exception("Instance integrity differs!"); }
as expected in the json file, this exception is thrown, so the links are really broken.
In running WebApi, I use the following code:
config.Formatters.Add(new ProtoBufFormatter());
Is there a problem there? Should I add more information in Formatters?