代码之家  ›  专栏  ›  技术社区  ›  netmatrix01

将序列化对象迁移到新版本

  •  1
  • netmatrix01  · 技术社区  · 16 年前

    我想将数据库中以前序列化的对象迁移到新模式。

    我以前的目标。

    Public interface MyReport
    {
    
        string Id { get; set;}
    
        string Name { get; set;}
    
        Dictionary<string, string> PropColl { get; set;}
    }
    

    但由于某些原因,我们不得不对接口进行更改

    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 
    }
    

    如您所见,我的接口已被修改,我希望将基于MyReport序列化的序列化对象迁移到MyReport 有人能给我提供一些输入吗?我应该编写什么样的实用程序来帮助我实现将序列化对象迁移到新的修改接口版本。

    谢谢 银

    2 回复  |  直到 16 年前
        1
  •  3
  •   Tomas Vana    16 年前

    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;
        }
    
        2
  •  1
  •   Gabriel Magana    16 年前

    1) 编写一个实用程序,读取旧对象定义中的序列化对象。

    2) 该实用程序以非序列化的方式将对象写入数据库(即,每个字段中都有一段数据,等等)。

    不要养成序列化对象的习惯,不要将对象存储在持久性存储中的某个地方,以便以后检索。序列化不是为此而构建的。

    在过去,您遇到了C程序员的问题:他们会在内存中创建一个结构,然后将该结构保存到文件中。然后结构的成员会改变,他们会想知道如何读回它,因为数据的编码不同。

    随后出现了数据库格式、INI文件等,专门用于满足这一需求,因此以一种格式保存数据,然后能够无误地读取数据。

    所以不要重复过去的错误。创建序列化是为了促进短期二进制存储和通过TCP/IP传输对象的能力。

    最坏的情况是,将数据存储为XML,而不是序列化的二进制流。另外,据我所知,微软并不能保证从一个.NET版本的序列化数据可以从另一个版本读取。尽可能将数据转换为清晰的格式。