zoukankan      html  css  js  c++  java
  • EF CodeFirst系列(8)---添加初始化数据和数据库迁移策略

    1.添加初始化数据(Seed)

      我们可以在初始化数据库的过程中给数据库添加一些数据。为了实现初始化数据(seed data)我们必须创建一个自定义的数据库初始化器(DB initializer),并重写其中的Seed方法。

      下边的栗子展示在School数据库中给Standard表添加默认的数据:

    第一步:创建自定义初始化器

    //继承三种内置的初始化器中的DropCreateDatabaseAlways
    public class SchoolDBInitializer : DropCreateDatabaseAlways<SchoolDBContext>
    {
        protected override void Seed(SchoolDBContext context)
        {
            IList<Standard> defaultStandards = new List<Standard>();
    
            defaultStandards.Add(new Standard() { StandardName = "Standard 1", Description = "First Standard" });
            defaultStandards.Add(new Standard() { StandardName = "Standard 2", Description = "Second Standard" });
            defaultStandards.Add(new Standard() { StandardName = "Standard 3", Description = "Third Standard" });
    
            context.Standards.AddRange(defaultStandards);
         //初始化数据
            base.Seed(context);
        }
    }

    第二步.将自定义的数据库初始化器添加到context中

    public class SchoolContext: DbContext 
    {
        public SchoolContext(): base("SchoolDB") 
        {
            Database.SetInitializer(new SchoolDBInitializer());
        }
        
        public DbSet<Student> Students { get; set; }
        public DbSet<Standard> Standards { get; set; }
    }

    2.数据库迁移策略

      前边我们已经知道了EF中的数据库迁移策略(CreateDatabaseIfNotExists,DropCreateDatabaseIfModelChanges, and DropCreateDatabaseAlways.),但是因为这些策略都是删除旧的数据库然后创建一个新的数据库,所以使用这些策略会造成数据库中的数据(不是seed data的数据)、存储过程、触发器等内容丢失

      针对上边的问题,EF提供了一个新的数据库初始化器 MigrateDatabaseToLastestVersion,这个工具在实体模型改变时自动帮我们更新数据库,且不会造成数据丢失。

    下边介绍两种更新数据库的方法:

    1.自动迁移

    第一步:

    在程序包管理器控制台输入

    enable-migrations –EnableAutomaticMigration:$true

    执行成功后,EFAp创建了一个继承自DbMigrationConfiguration类的Configuration类,如下

        internal sealed class Configuration : DbMigrationsConfiguration<EF6Demo.SchoolContext>
        {
            public Configuration()
            {
                AutomaticMigrationsEnabled = true;//自动迁移为true
                AutomaticMigrationDataLossAllowed = true;//允许数据丢失,默认生成时没有这一项(不添加这一项时,只在添加/删除实体类时自动生成,如果我们删除了实体类的一个属性就会抛出异常)
                ContextKey = "EF6Demo.SchoolContext";
            }
    
            protected override void Seed(EF6Demo.SchoolContext context)
            {
                //  This method will be called after migrating to the latest version.
    
                //  You can use the DbSet<T>.AddOrUpdate() helper extension method 
                //  to avoid creating duplicate seed data.
            }
        }

    第二步:

    把数据库初始化器添加到配置中,context代码如下:

        public class SchoolContext : DbContext
        {
            public SchoolContext() {
                //添加MigrateDatabaseToLatestVersion数据库初始化器
                Database.SetInitializer(new MigrateDatabaseToLatestVersion<SchoolContext, Configuration>());
            }
            public virtual DbSet<Student> Students { get; set; }
            public virtual DbSet<Standard> Standards { get; set; }
            
            protected override void OnModelCreating(DbModelBuilder modelBuilder)
            {
                base.OnModelCreating(modelBuilder);
            }
        }

    完成上边两步,当我们修改实体类时运行程序就会自动更新数据库。

    2.使用代码迁移

       上边我们了解了通过自动迁移来更新数据库,这里介绍通过代码更新数据库的方法。通过代码更新数据库的功能更强大,如我们可以给数据库的列添加默认值,添加计算列等。

      使用代码迁移,我们在程序包控制台执行以下过程:

    1.Enable-Migrations [-f]

      这条命令会生成一个Configuration文件,当配置文件存在时可通过-f后缀强制覆盖旧文件。执行成功后添加了Migrations文件夹,文件夹中包含一个Configuration配置类,如下:

    Configuration配置类代码如下:

        internal sealed class Configuration : DbMigrationsConfiguration<EF6Demo.SchoolContext>
        {
            public Configuration()
            {
                AutomaticMigrationsEnabled = false;
                ContextKey = "EF6Demo.SchoolContext";
            }
    
            protected override void Seed(EF6Demo.SchoolContext context)
            {
                //  This method will be called after migrating to the latest version.
    
                //  You can use the DbSet<T>.AddOrUpdate() helper extension method 
                //  to avoid creating duplicate seed data.
            }
        }

    2.Add-Migration [MigName]

      首先在context类中指定初始化器是MigrateDatabaseToLatestVersion初始化器,如下:

       public class SchoolContext : DbContext
        {
            public SchoolContext() {
                //添加MigrateDatabaseToLatestVersion数据库初始化器
                Database.SetInitializer(new MigrateDatabaseToLatestVersion<SchoolContext, Configuration>());
      
            }
            public virtual DbSet<Student> Students { get; set; }
            public virtual DbSet<Standard> Standards { get; set; }
            
            protected override void OnModelCreating(DbModelBuilder modelBuilder)
            {
                base.OnModelCreating(modelBuilder);
            }
        }

    在包管理器控制台执行:

     Add-Migration FirstInit

    这会在Migration文件夹中生成一个<stamp>_name的迁移类:

     迁移类的代码如下:

        public partial class FirstInit : DbMigration
        {
            //升级
            public override void Up()
            {
                CreateTable(
                    "dbo.Standards",
                    c => new
                        {
                            StandardId = c.Int(nullable: false, identity: true),
                            StandardName = c.String(),
                        })
                    .PrimaryKey(t => t.StandardId);
                
                CreateTable(
                    "dbo.Students",
                    c => new
                        {
                            StudentId = c.Int(nullable: false, identity: true),
                            StudentName = c.String(),
                            Standard_StandardId = c.Int(),
                        })
                    .PrimaryKey(t => t.StudentId)
                    .ForeignKey("dbo.Standards", t => t.Standard_StandardId)
                    .Index(t => t.Standard_StandardId);
                
            }
            //降级
            public override void Down()
            {
                DropForeignKey("dbo.Students", "Standard_StandardId", "dbo.Standards");
                DropIndex("dbo.Students", new[] { "Standard_StandardId" });
                DropTable("dbo.Students");
                DropTable("dbo.Standards");
            }
        }

    我们可以看到迁移类中包含Up()和Down()方法,分别用于数据库的更新和回退。

    3.Update-Database 

    ① updata-database [-verbose]

      在程序包控制台中执行这条命令时,会执行Add-Migration命令创建的最新的迁移文件,并更新数据库

    执行完上边三步数据库就生成了,以后当我们修改实体类时,执行Add-Migration [MigName]后再执行Update-Database [-verbose],就可方便地根据模型的变化更新数据库。

    ② update-database -TargetMigration:xxx

    如果我们想回退到某一个版本时执行:

    update-database -TargetMigration:FirstInit//数据库回退到第一次的版本

     3.codeFirst中的设计器

      我们知道codeFirst模式中不支持设计器,设计器对我们理解实体间关系还是很有用的,怎么在code-first中使用设计器呢?Visual Studio Marketplace.点击链接下载工具,安装即可,安装完成重启VS,在context上点击右键,然后会有一个Entity Framework选项,如下图:

    点击ViewEntity Data Model选项就可以自动生成设计器,如下:

    这个工具十分好用,同时也支持生成Model XML和DDL SQL推荐使用。

  • 相关阅读:
    无监督学习在反欺诈中的应用
    Java中Object对象方法
    ambari下httpfs安装
    深入理解spark-rdd详解
    Tensorflow实践Basic Classification
    深入理解spark-两种调度模式FIFO,FAIR模式
    深入理解spark-taskScheduler,schedulerBackend源码分析
    js模仿页面点击
    记一次请求走私学习
    十种常见的报错注入
  • 原文地址:https://www.cnblogs.com/wyy1234/p/9700446.html
Copyright © 2011-2022 走看看