3

I'm pursuing a suggestion made on this question:

EF6 code first: How to load DbCompiledModel from EDMX file on startup?

I want to serialize a DbCompiledModel to disk, so I can deserialize it later and improve startup time. It needs to serialize properties and fields including private ones.

My three attempts below have failed for the following reasons. How else could I serialize the private contents of DbCompiledModel?

BinaryFormatter

My first attempt via BinaryFormatter:

var compiledModel = modelBuilder.Build(new DbProviderInfo("System.Data.SqlClient", "2012")).Compile();
var bf = new BinaryFormatter();
var fs = new FileStream("C:\\temp\\bf.txt", FileMode.Create);
bf.Serialize(fs, compiledModel);
fs.Close();

Fails due to:

Type 'System.Data.Entity.Infrastructure.DbCompiledModel' in Assembly 'EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' is not marked as serializable.

Json #1

My second attempt via Json with a custom contract resolver to include private fields:

var settings = new JsonSerializerSettings() { ContractResolver = new MyContractResolver()};
var json = JsonConvert.SerializeObject(compiledModel, settings);
System.IO.File.WriteAllText("C:\\temp\\json.json", json);

...
    private class MyContractResolver : Newtonsoft.Json.Serialization.DefaultContractResolver
    {
        protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
        {
            var props = type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
                            .Select(p => base.CreateProperty(p, memberSerialization))
                        .Union(type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
                                   .Select(f => base.CreateProperty(f, memberSerialization)))
                        .ToList();
            props.ForEach(p => { p.Writable = true; p.Readable = true; });
            return props;
        }
    }

Fails due to:

Self referencing loop detected for property 'ProviderManifest' with type 'System.Data.Entity.Core.Metadata.Edm.Provider.EdmProviderManifest'. Path '_workspace._metadataWorkspace._itemsCSpace.ValueForDebugDisplay[0].ProviderManifest._facetDescriptions.['Edm.String'][0].FacetType'.

Json #2

And my third attempt tweaking the ReferenceLoopHandling and PreserveReferencesHandling settings in Json:

var settings = new JsonSerializerSettings() { ContractResolver = new MyContractResolver(), ReferenceLoopHandling = ReferenceLoopHandling.Ignore};
//OR SETTINGS:
var settings = new JsonSerializerSettings() { ContractResolver = new MyContractResolver(), ReferenceLoopHandling = ReferenceLoopHandling.Ignore, PreserveReferencesHandling = PreserveReferencesHandling.Objects };
var json = JsonConvert.SerializeObject(compiledModel, settings);
System.IO.File.WriteAllText("C:\\temp\\json.json", json);

Fail due to StackOverflowException.

Community
  • 1
  • 1
Brendan Hill
  • 3,406
  • 4
  • 32
  • 61
  • seems like we need to focus on getting the code from David Roth's Branch https://entityframework.codeplex.com/workitem/2631 merged, and getting a new release out. – JJS Aug 21 '15 at 17:03
  • Yes JJS - that is the ideal solution. That was my request from earlier this year in fact. The impact of this issue for us is medium to high and it appears that the problem is common. – Brendan Hill Aug 27 '15 at 07:17

0 Answers0