I have two objects which 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 instantiate this objects and make the "associations".
ProtoBufObject parent = new ProtoBufObject()
{
Oid = Guid.NewGuid()
};
ChildProtoBufObject child = new ChildProtoBufObject()
{
Oid = Guid.NewGuid()
};
parent.child = child;
child.parent = parent;
The objects will be serialized like this:
ProtoBufFormatter formatter = new ProtoBufFormatter();
HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Post, requestUri);
requestMessage.Content = new ObjectContent<SearchParameters>(searchParameters, formatter);
And than they will be sent via http to a Webapi, where it will be deserialized with the help of WebApiContrib.Formatting.ProtoBuf.
In the Webapi controller i receive the objects with the correct relations BUT the integrity of the relations gone wrong. I dump the objects with Json to a file with 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 a ref=1. The id=3 parent has the correct reference to the child.
So it seams that the top level object will not set up correctly. This is a huge problem with Entity Framework (that's why I came up with this issue) because it uses the reference of the type, not just to properties (which are correct).
I also tried it with ProtoContract(DefaultRefencetype=true) but that made it even worser. Then I received on the parent with id=3 a new child with id=4.
My question is: How I can make the integrity of the objects to work?
What I want is:
[{
"$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: The Entity Framework line
dbContext.Set<ProtoBufObject>.AddRange(myObjects);
throws an InvalidOperationException because the integrity of the models (parent, child.parent) differ.
Additional information: Conflicting changes to the role 'foo_bar_Target' of the relationship 'Entities.Context.foo_bar' have been detected.
If I use the Newtonsoft.Json serializer on the client side and send it through the WebApi (I use the same objects with the same relations as with my Protobuf test) the Entity Framework can handle the objects. So there must be some differences between the deserialised objects from Json and Protobuf. That's why I serialized the objects again to see the differences.
I also put in my Put method a reference check:
if (protoBufObject != protoBufObject.child.parent)
{
throw new Exception("Instance integrity differs!");
}
as expected from the json file this exeption is thrown, so the references are really corrupted.
In the Startup of the WebApi I use following code:
config.Formatters.Add(new ProtoBufFormatter());
Lies there the problem? Do I need to add some more information to the Formatters?