目的和实体框架语义IMigrationMetadata接口目的、语义、实体、框架

由网友(继续丿辉煌、)分享简介:我试图找出什么是在EF System.Data.Entity.Migrations.Infrastructure.IMigrationMetadata接口的语义。我知道,它是用来管理和应用数据库迁移。但我无法找到关于它的详细信息。具体而言,我想知道:是用来做什么来源的财产?为什么它总是空,当我生成使用工具迁移?在什么...

我试图找出什么是在EF System.Data.Entity.Migrations.Infrastructure.IMigrationMetadata接口的语义。我知道,它是用来管理和应用数据库迁移。但我无法找到关于它的详细信息。具体而言,我想知道:

是用来做什么来源的财产?为什么它总是空,当我生成使用工具迁移? 在什么样的目标属性是用来干什么的?我看到,工具是生成一些东西的Base64寻找并放入资源。它是什么?它为什么在这样的非友好的格式生成的? 是否可以手动开发的迁移,无需工具的使用情况?我想这是因为它应该以某种方式产生的目标属性的Base64样的价值并不容易。我说得对? 当此接口实际使用?目前,我发现,迁移中不实现此接口无法自动迁移发现。我对吗?它是该接口的唯一目的是什么? 解决方案

的的 IMigrationMetadata接口有,我知道下面的责任。

通过ID属性标识的迁移,以便它可以识别并包括命令,如更新 - 数据库。 供应模型的快照,因为它是后迁移经由目标属性施加。这被用来确定应包括在一个新的迁移的更改。

我猜测的来源属性通常不是由工具来实现,因为它不需要在的实施添加迁移。这code可能只是比较模式,因为它是在最近,已有来自code产生的模型迁移,以确定需要纳入新的迁移变化的结束。

目标属性返回EDMX格式的模型,已经两个COM pressed使用的GZipStream和连接使用Convert.ToBase64String codeD。我写了下面code到都失code和EN code这些值。你会probaly找到,如果你将要手动编码迁移这个有用。

 使用系统;
使用System.IO;
使用System.IO.Com pression;
使用System.Text;

命名空间ConsoleApplication6
{
    类节目
    {
        静态无效的主要()
        {
            变种minimalModel = File.ReadAllText(Model1.edmx);

            变种EN codedMinimalModel = EN code(minimalModel);

            VAR德codedMinimalModel =德code(EN codedMinimalModel);
        }

        私人静态字符串德code(字符串连接codedText)
        {
            VAR COM pressedBytes = Convert.FromBase64String(EN codedText);

            VAR DECOM pressedBytes = DECOM preSS(COM pressedBytes);

            返回Encoding.UTF8.GetString(DECOM pressedBytes);
        }

        私人静态字符串连接code(字符串明文)
        {
            VAR字节= Encoding.UTF8.GetBytes(明文);

            VAR COM pressedBytes = com的preSS(字节);

            返回Convert.ToBase64String(COM pressedBytes);
        }

        公共静态的byte [] DECOM preSS(byte []的字节)
        {
            使用(VAR memorySteam =新的MemoryStream(字节))
            {
                使用(VAR gzipStream =新GZipStream(memorySteam,COM pressionMode.Decom preSS))
                {
                    返回的toByteArray(gzipStream);
                }
            }
        }

        私有静态的byte []的toByteArray(流流)
        {
            使用(VAR resultMemoryStream =新的MemoryStream())
            {
                stream.CopyTo(resultMemoryStream);

                返回resultMemoryStream.ToArray();
            }
        }

        公共静态的byte []的COM preSS(byte []的字节)
        {
            使用(VAR的MemoryStream =新的MemoryStream())
            {
                使用(VAR gzipStream =新GZipStream(MemoryStream的,COM pressionMode.Com preSS))
                {
                    gzipStream.Write(字节,0,bytes.Length);
                }

                返回memoryStream.ToArray();
            }
        }
    }
}
 

的玉米pression可能解释查询,为什么非人类可读格式被选择。这内容重复至少一次(在目标属性)对于每个迁移,并且可以根据该模型的大小是大的。在COM pression节省了空间。

在这一点,据我所看到的,这是真的只需要它已经被应用后,返回到模型的真实再presentation上次迁移。只有迁移使用添加迁移来计算新移民所需要的变化。如果你正在处理一个非常大的模型和/或一个非常大的数目的迁移,删除这些内容可能是有利的。在这个帖子其余部分将介绍我的目标属性,它可以用在所有,但最近的迁移最小值推导。

目标属性必须返回一个字符串对象 - 一个ArgumentNullException被抛出在System.Data.Entity.Migrations.DbMigrator.ApplyMigration调用System.Convert.FromBase64String时更新数据库被称为如果目标返回null

此外,它必须是一个有效的XML文档。当我返回一个空字符串从目标我得到的消息,一个XmlException缺少根元素。

从这个角度上,我用我上面的code到EN code的值。

我没有得到很远与逐步建立开始,&LT模型;根/> 例如,所以我换过来丢弃的元素从空EDMX文件我生成加入了新的ADO.Net实体数据模型我的项目,然后选择空模型选项。这是结果

 < XML版本=1.0编码=UTF-8&GT?;
< EDMX:EDMX版本=3.0的xmlns:EDMX =htt​​p://schemas.microsoft.com/ado/2009/11/edmx>
  < EDMX:运行>
    < EDMX:StorageModels>
      <模式的xmlns =htt​​p://schemas.microsoft.com/ado/2009/11/edm/ssdl命名空间=Model1.Store别名=自我提供程序=System.Data.SqlClient的ProviderManifestToken = 2005年>
      < /架构>
    < / EDMX:StorageModels>
  < / EDMX:运行>
< / EDMX:EDMX>
 
业界 谷歌发布自然语言框架语义解析器SLING

当我连接codeD这个用我的code从上面,这就是结果。

H4sIAAAAAAAEAJVQy07DMBC8I/EP1t6xExASRA1VVTgWIYK4W/amtfCjeN2q/D12HsqJAxdLOzOe2Z3V+uIsO2MkE3wLNa+AoVdBG79v4ZT6mwdYP11frVC7S/OSH/Y5i++KOH/31BS2hUNKx0YIUgd0krgzKgYKfeIqOCF1ELdV9SjqWhQ5ZFfGRt/3k0/G4YDMWJdClHvcBY2WJiZz3WA+xv4vURBpC+xVOqSjVNjC4F3zkoTANtbIbNmh7YG9xXA2GmOefyih488ySd5926016NMi2ElveqT0Eb4wd5Lz7mHZVozrzoeJPy6biKWGCSh95+kXfT3Qv6UBAAA=

要小心,以确保你留住真正的目标值为每个迁移中的源代码控制的情况下,你需要回滚到早期版本。你可以尝试应用迁移到一个数据库,然后使用Visual Studio生成EDMX文件。另一种方法是将回滚形成模型中的类,然后执行添加迁移。从新创建的迁移采取目标值。

I'm trying to find out what is the semantic of System.Data.Entity.Migrations.Infrastructure.IMigrationMetadata interface in the EF. I know that it's used to manage and apply DB migrations. But I can't find detailed information about it. To be specific I would like to know:

What Source property is used for? Why it's always null when I generate migrations using tools? What Target property is used for? I see that tools is generating something Base64-looking and placed into resources. What is it? Why it's generated in such non-friendly format? Is it possible to develop migration manually without tools usage? I suppose it is not easy because of that Target property Base64-like value which should be generated somehow. Am I right? When this interface is actually used? At the moment I found out that migrations not implementing this interface can't be found automatically by migrator. Am I right? Is it the only purpose of the interface?

解决方案

The IMigrationMetadata Interface has the following responsibilities that I know of.

Identify the migration via the ID property so that is can be recognized and included by commands such as Update-Database. Supply a snapshot of the model as it is after the migration is applied via the Target property. This is used to determine the changes that should be included in a new migration.

I am guessing that the Source property is often not implemented by the tooling as it is not required in the implementation of Add-Migration. That code probably just compares the model as it was at the end of the most recent, existing migration with a model generated from the code to determine the changes that need to be included in the new migration.

The Target property returns a model in EDMX format that has been both compressed using the GZipStream and encoded using Convert.ToBase64String. I wrote the following code to both decode and encode these values. You would probaly find this useful if you are going to be coding migrations manually.

using System;
using System.IO;
using System.IO.Compression;
using System.Text;

namespace ConsoleApplication6
{
    class Program
    {
        static void Main()
        {
            var minimalModel = File.ReadAllText("Model1.edmx");

            var encodedMinimalModel = Encode(minimalModel);

            var decodedMinimalModel = Decode(encodedMinimalModel);
        }

        private static string Decode(string encodedText)
        {
            var compressedBytes = Convert.FromBase64String(encodedText);

            var decompressedBytes = Decompress(compressedBytes);

            return Encoding.UTF8.GetString(decompressedBytes);
        }

        private static string Encode(string plainText)
        {
            var bytes = Encoding.UTF8.GetBytes(plainText);

            var compressedBytes = Compress(bytes);

            return Convert.ToBase64String(compressedBytes);
        }

        public static byte[] Decompress(byte[] bytes)
        {
            using (var memorySteam = new MemoryStream(bytes))
            {
                using (var gzipStream = new GZipStream(memorySteam, CompressionMode.Decompress))
                {
                    return ToByteArray(gzipStream);
                }
            }
        }

        private static byte[] ToByteArray(Stream stream)
        {
            using (var resultMemoryStream = new MemoryStream())
            {
                stream.CopyTo(resultMemoryStream);

                return resultMemoryStream.ToArray();
            }
        }

        public static byte[] Compress(byte[] bytes)
        {
            using (var memoryStream = new MemoryStream())
            {
                using (var gzipStream = new GZipStream(memoryStream, CompressionMode.Compress))
                {
                    gzipStream.Write(bytes,0, bytes.Length);
                }

                return memoryStream.ToArray();
            }
        }
    }
}

The compression probably explains your query as to why a non-human readable format was chosen. This content is repeated at least once (in the Target property) for each migration and can be large depending on the size of the model. The compression saves on space.

On that note, as far as I can see, it is really only the last migration that is required to return a true representation of the model after it has been applied. Only that migration is used by Add-Migration to calculate the changes required in the new migration. If you are dealing with a very large model and/or a very large number of migrations, removing that content could be advantageous. The remainder of this post covers my derivation of a minimal value for the Target property which can be used in all but the most recent migration.

The Target property must return a string object - an ArgumentNullException is thrown in a call to System.Convert.FromBase64String in System.Data.Entity.Migrations.DbMigrator.ApplyMigration when update-database is called if Target returns null.

Further, it must be a valid XML document. When I returned an empty string from Target I got an XmlException with the message "Root element is missing.".

From this point on, I used my code from above to encode the values.

I did not get very far with gradually building up the model starting with <root /> for example so I swapped over to discarding elements from an empty EDMX file that I generated by adding a new 'ADO.Net Entity Data Model' to my project and then choosing the 'Empty Model' option. This was the result.

<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="3.0" xmlns:edmx="http://schemas.microsoft.com/ado/2009/11/edmx">
  <edmx:Runtime>
    <edmx:StorageModels>
      <Schema xmlns="http://schemas.microsoft.com/ado/2009/11/edm/ssdl" Namespace="Model1.Store" Alias="Self" Provider="System.Data.SqlClient" ProviderManifestToken="2005">
      </Schema>
    </edmx:StorageModels>
  </edmx:Runtime>
</edmx:Edmx>

When I encoded this using my code from above, this was the result.

H4sIAAAAAAAEAJVQy07DMBC8I/EP1t6xExASRA1VVTgWIYK4W/amtfCjeN2q/D12HsqJAxdLOzOe2Z3V+uIsO2MkE3wLNa+AoVdBG79v4ZT6mwdYP11frVC7S/OSH/Y5i++KOH/31BS2hUNKx0YIUgd0krgzKgYKfeIqOCF1ELdV9SjqWhQ5ZFfGRt/3k0/G4YDMWJdClHvcBY2WJiZz3WA+xv4vURBpC+xVOqSjVNjC4F3zkoTANtbIbNmh7YG9xXA2GmOefyih488ySd5926016NMi2ElveqT0Eb4wd5Lz7mHZVozrzoeJPy6biKWGCSh95+kXfT3Qv6UBAAA=

Be careful to ensure that you retain the real Target values for each of your migrations in source control in case you need to roll back to an earlier version. You could try applying the migration to a database and then using Visual Studio to generate an EDMX file. Another alternative would be to roll back the classes that form your model and then execute Add-Migration. Take the Target value from the newly created migration.

阅读全文

相关推荐

最新文章