开发者

Migrate serialized objects to new version

I would like to migrate me previously serialized objects in database to new schema.

My previous object.

Public interface MyReport
{

    string Id { get; set;}

    string Name { get; set;}

    Dictionary<string, string> PropCol开发者_Go百科l { get; set;}
}

But for some reasons we had to make interface changes

Public interface IMarkme
{
}

Public interface MyReport<T> where T : Imarkme
{

    string Id { get; set;}

    string Name { get; set;}

    T ExtendedProp { get; set;}
}

Public NewProp : Imarkme
{
    /// some code here 
}

So as you can see my interface has been modified and I would like to migrate my serialized objects which were serialized based on MyReport to MyReport Can someone provide me some input as what kind of utility I should aim to write which can help me achieve migrating my serialized object to new modified interface version.

Thanks, AG


I have actually done something similar recently, where I have created a simple console application to be able to transform some serialized objects from one version to another. I have simply used both versions of dlls and reflection to read and write the values of different properties. Probably you'll find this helpful as an inspiration ;)

static void Main(string[] args)
    {
        object test;

        AppDomain.CurrentDomain.AssemblyResolve += domain_AssemblyResolve;


        using (var con = new SqlConnection(connectionString))
        {
            using (var cmd = new SqlCommand())
            {
                cmd.CommandText = "select top 1 Data_Blob from dbo.Serialized";
                cmd.CommandType = CommandType.Text;
                cmd.Connection = con;

                con.Open();
                var blob = (byte[])cmd.ExecuteScalar();

                var bf = new BinaryFormatter();
                var stream = new MemoryStream(blob);
                bf.AssemblyFormat = FormatterAssemblyStyle.Full;
                test = bf.Deserialize(stream);
            }
        }

        var objNewVersion = Activator.CreateInstance(Type.GetType("ObjectGraphLibrary.Test, ObjectGraphLibrary, Version=1.0.0.10, Culture=neutral, PublicKeyToken=33c7c38cf0d65826"));


        var oldType = test.GetType();
        var newType = objNewVersion.GetType();

        var oldName = (string) oldType.GetProperty("Name").GetValue(test, null);
        var oldAge = (int) oldType.GetProperty("Age").GetValue(test, null);

        newType.GetProperty("Name").SetValue(objNewVersion, oldName, null);
        newType.GetProperty("DateOfBirth").SetValue(objNewVersion, DateTime.Now.AddYears(-oldAge), null);


        Console.Read();
    }

    static Assembly domain_AssemblyResolve(object sender, ResolveEventArgs args)
    {
        var assName = new AssemblyName(args.Name);

        var uriBuilder = new UriBuilder(Assembly.GetExecutingAssembly().CodeBase);
        var assemblyPath = Uri.UnescapeDataString(uriBuilder.Path);
        var codeBase = Path.GetDirectoryName(assemblyPath);

        var assPath = Path.Combine(codeBase, string.Format("old\\{0}.{1}.{2}.{3}\\{4}.dll", assName.Version.Major,
                                                 assName.Version.Minor, assName.Version.Build,
                                                 assName.Version.Revision, assName.Name));

        return File.Exists(assPath) ? Assembly.LoadFile(assPath) : null;
    }


1) Write a utility that reads the serialized objects in the old object definition.

2) The utility writes your objects into the DB in a non-serialized manner (ie, with one piece of data in every field, etc...).

Don't get into the habit of serializing objects, and storing the somewhere in persistent storage for retrieval (much) later. Serialization was not built for that.

You have run into the problem of C programmers in the old days: they would create a struct in memory, save that struct into a file. Then the struct's members would change, and they woudl wonder how to read it back, since the data was encoded differently.

then along came database formats, INI files, and so on, specifically to address this need, so saving data in one format, and then being able to read it without error.

So don't repeat errors of the past. Serialization was created to facilitate short-term binary storage and the ability to, say, transmit an object over TCP/IP.

At worst, store your data as XML, not as serialized binary stream. Also, there is no assurance that I know about from MS that says that serialized data from one version of .NET will be able to be read from another. Convert your data to a legible format while you can.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜