Reputation: 150138
How can I serialize an Entity Framework Code First Proxy when the class it is proxying is decorated with DataContractAttribute(IsReference = true)
?
When using DataContractSerializer with ProxyContractResolver, I get the following:
The IsReference setting for type 'System.Data.Entity.DynamicProxies.MyType_59A83378572C10D0B31B6892FB6C3E7428C4BA214322C7A77BD5E1EB19E529CA' is 'False', but the same setting for its parent class 'My.Namespace.MyType' is 'True'. Derived types must have the same value for IsReference as the base type. Change the setting on type
It seems that the EF Proxy Generator is not respecting the IsReference attribute, which I do need on the POCO (otherwise I end up with a stack overflow due to mutual referencing).
Is there any mechanism at all to serialize an EF Proxy under these circumstances? How?
Upvotes: 2
Views: 3123
Reputation: 11
Notice that using the ProxyDataContractResolver()
only works if the proxied class specifies IsReference=true
directly.
It does NOT currently work if it is done on a base class as noted in the first comment above.
Upvotes: 1
Reputation: 364349
I just did following very simple example and ProxyDataContractResolver
works as expected - graph of proxied entities with cycles was correctly serialized.
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Objects;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
namespace CFSerialization
{
class Program
{
static void Main(string[] args)
{
using (var context = new Context())
{
context.Database.Delete();
context.Database.CreateIfNotExists();
context.Masters.Add(new Master
{
Name = "abc",
Details = new List<Detail>
{
new Detail { Name = "a" },
new Detail { Name = "b" },
new Detail { Name = "c" }
}
});
context.SaveChanges();
}
using (var context = new Context())
{
// This will get proxied Master
var master = context.Masters.First();
var serializer = new DataContractSerializer(typeof(Master), new DataContractSerializerSettings()
{
DataContractResolver = new ProxyDataContractResolver()
});
using (var stream = new MemoryStream())
{
// This will also lazy load all details
serializer.WriteObject(stream, master);
stream.Seek(0, SeekOrigin.Begin);
var newMaster = (Master)serializer.ReadObject(stream);
}
}
}
}
[DataContract(IsReference=true)]
public class Master
{
[DataMember]
public int Id { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public virtual ICollection<Detail> Details { get; set; }
}
[DataContract(IsReference=true)]
public class Detail
{
[DataMember]
public int Id { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public virtual Master Master { get; set; }
}
public class Context : DbContext
{
public DbSet<Master> Masters { get; set; }
}
}
There must be something more complicated in your model to break the functionality - are all your entities marked with DataContract(IsReference=true)
?
Note: I tested it in .NET 4.5.
Upvotes: 4