0

I have the EF databaseModel. I serialize my class thet contains field with EF DB Table Type. I try to deserealize and i have the field with null fields.

class Myclass
{
    public EFTable table {get;set;}
}

EFTable

  • string str;
  • int num;

[global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(EntityKeyProperty=true, IsNullable=false)] [global::System.Runtime.Serialization.DataMemberAttribute()] [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")]

After deserialization EFTable - string str=null - int num=0

why? how fix it without creating temp classes?

public static byte[] Serialize(BaseInspection inspection)
{
    using (var file = File.Create(path.ToString()))
    {
        Serializer.Serialize(file, inspection);
    }
    return File.ReadAllBytes(path.ToString());
}

static BaseInspection Desirialize(byte[] path)
{

    using (Stream stream = new MemoryStream(path))
        return Serializer.Deserialize<BaseInspection>(stream);           
}
Sergey Litvinov
  • 7,408
  • 5
  • 46
  • 67
Risa
  • 147
  • 1
  • 2
  • 15
  • Post your EFTable. Do have any Proto attributes on properties of EFTable? – Sergey Litvinov Jan 14 '14 at 08:55
  • All are standart when create the EF DataBase Model\Scheme – Risa Jan 14 '14 at 08:56
  • ProtoBuf has two ways to specify order of fields. First one is to specify Attributes on each property. Second one - is to create this `RuntimeTypeModel` in runtime and fill it with reflection – Sergey Litvinov Jan 14 '14 at 08:58
  • Ok, I know that I do not set attributes to EF model, it is too long and I generete my db model many times, it means that I sould rewrite attributes again many time. How I can do it fast? – Risa Jan 14 '14 at 09:00

2 Answers2

1

If you can't specify attributes under your model, you can go with second approach to fill RuntimeTypeModel at application start. Here is a sample given my Marc Gravell - Protobuf-net serialization without annotation

Code sample for your EFTable:

RuntimeTypeModel.Default.Add(typeof(EFTable), false).Add("str", "num",);

Or you can fill it with reflection based on your EFTable properties, and then it should serialize correctly.

But beware, as Protobuf is critical to properties order. And if you fill this RuntimeTypeModel object dynamically by reflection, and then you will add new property, then data that was serialized with previous version, won`t work in new version, as properties order will be changed.

UPDATE1

As I mentioned you can also use reflection to populate fields dynamically. Here is a sample of such method:

public static void Generate(IEnumerable<Type> types)
{
    var model = RuntimeTypeModel.Default;

    foreach (var type in types)
    {
        int counter = 1;
        var metaType = model.Add(type, false);

        var properties = type.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public);
        foreach (var propertyInfo in properties)
        {
            metaType.Add(counter++, propertyInfo.Name);
        }

    }
}   

And usage sample:

Generate(new List<Type>() { // list of objects that should be registered with ProtoBuf-Net
    typeof(ASPStateTempSession),  
    typeof(ASPStateTempApplication) 
});

But as i previously said, if you add new property in new version of your application, then old saved cached data won't work, as order of properties will be changed.

Community
  • 1
  • 1
Sergey Litvinov
  • 7,408
  • 5
  • 46
  • 67
  • think it will be "ppc", I have 27 tables >.< thank you, will try – Risa Jan 14 '14 at 09:11
  • sorry for long answer. I've added a sample how to fill them dynamically – Sergey Litvinov Jan 14 '14 at 10:21
  • thank you, I used my own code to dynamically fill RuntimeTypeModel.Default =) But now I selected BinaryBufferization because I need save delegates too... I know that this is not good... but now I can't change anything in programm... – Risa Jan 15 '14 at 06:09
1

If the classes are being generated, it is very likely they are being generated as partial classes. In which case, you can add the attributes separately in a separate code file:

namespace YourNamespace
{
    [ProtoContract]
    [ProtoPartialMember(1, "table")]
    partial class Myclass {}
}

This will be merged at compile-time, and protobuf-net knows to look for the ProtoPartialMember alternative form.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • Hi Marc, just curios, will it work with `MetadataTypeAttribute` attribute that can be used with EntityFramework to specify attributes for domain object in separate partial class? I'm talking about this one - http://msdn.microsoft.com/en-us/library/ee707339(v=vs.91).aspx . If I specify Proto attributes in MetaData class, will ProtoBuf use it? – Sergey Litvinov Jan 15 '14 at 14:16
  • 1
    @SergeyLitvinov not at the current time, but it is something worth considering – Marc Gravell Jan 15 '14 at 15:15
  • Got it. Thank you for the answer. I'm not sure that it will be very useful, but it can be. – Sergey Litvinov Jan 15 '14 at 15:57