Migrace Code FirstCode First Migrations

Migrace Code First je doporučeným způsobem, jak vyvíjet schéma databáze vaší aplikace, pokud používáte Code First pracovního postupu.Code First Migrations is the recommended way to evolve your application's database schema if you are using the Code First workflow. Migrace poskytují sadu nástrojů, které umožňují:Migrations provide a set of tools that allow:

  1. Vytvoření počáteční databáze, která funguje s EF modeluCreate an initial database that works with your EF model
  2. Generování migrace můžete sledovat změny provedené do modelu EFGenerating migrations to keep track of changes you make to your EF model
  3. Zachovat aktuální tyto změny databázeKeep your database up to date with those changes

Následující návod přináší přehled migrace Code First v rozhraní Entity Framework.The following walkthrough will provide an overview Code First Migrations in Entity Framework. Můžete buď dokončení celého postupu nebo přejděte k tématu, které vás zajímají.You can either complete the entire walkthrough or skip to the topic you are interested in. Jsou pokryta následující témata:The following topics are covered:

Vytváření počáteční modelu & databázeBuilding an Initial Model & Database

Než začneme pomocí migrace musíte projekt a model Code First pro práci s.Before we start using migrations we need a project and a Code First model to work with. V tomto návodu budeme používat kanonickém blogu a příspěvek modelu.For this walkthrough we are going to use the canonical Blog and Post model.

  • Vytvořte nový MigrationsDemo konzolové aplikaceCreate a new MigrationsDemo Console application
  • Přidejte nejnovější verzi EntityFramework balíček NuGet do projektuAdd the latest version of the EntityFramework NuGet package to the project
    • Nástroje –> Správce balíčků knihoven –> Konzola správce balíčkůTools –> Library Package Manager –> Package Manager Console
    • Spustit Install-Package EntityFramework příkazuRun the Install-Package EntityFramework command
  • Přidat Model.cs souboru s kódem je uvedeno níže.Add a Model.cs file with the code shown below. Tento kód definuje jedinou blogu třídu, která tvoří náš model domény a BlogContext třídu, která je náš kontext platforem EF Code FirstThis code defines a single Blog class that makes up our domain model and a BlogContext class that is our EF Code First context
    using System.Data.Entity;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using System.Data.Entity.Infrastructure;

    namespace MigrationsDemo
    {
        public class BlogContext : DbContext
        {
            public DbSet<Blog> Blogs { get; set; }
        }

        public class Blog
        {
            public int BlogId { get; set; }
            public string Name { get; set; }
        }
    }
  • Když teď máme modelu je čas ji používat pro přístup k datům.Now that we have a model it’s time to use it to perform data access. Aktualizace Program.cs souboru s kódem je uvedeno níže.Update the Program.cs file with the code shown below.
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    namespace MigrationsDemo
    {
        class Program
        {
            static void Main(string[] args)
            {
                using (var db = new BlogContext())
                {
                    db.Blogs.Add(new Blog { Name = "Another Blog " });
                    db.SaveChanges();

                    foreach (var blog in db.Blogs)
                    {
                        Console.WriteLine(blog.Name);
                    }
                }

                Console.WriteLine("Press any key to exit...");
                Console.ReadKey();
            }
        }
    }
  • Spusťte aplikaci a uvidíte, že MigrationsCodeDemo.BlogContext databáze se vytvoří za vás.Run your application and you will see that a MigrationsCodeDemo.BlogContext database is created for you.

    Databáze LocalDB

Povolení migraceEnabling Migrations

Je čas provést některé další změny našeho modelu.It’s time to make some more changes to our model.

  • Umožňuje zavést vlastnost adresa Url blogu třídy.Let’s introduce a Url property to the Blog class.
    public string Url { get; set; }

Pokud chcete aplikaci spustit znovu získali byste s oznámením InvalidOperationException model zálohování kontextu 'BlogContext' byl změněn, protože byla vytvořena databáze. Zvažte použití migrace Code First k aktualizaci databáze ( http://go.microsoft.com/fwlink/?LinkId=238269 ).If you were to run the application again you would get an InvalidOperationException stating The model backing the 'BlogContext' context has changed since the database was created. Consider using Code First Migrations to update the database ( http://go.microsoft.com/fwlink/?LinkId=238269).

Jak výjimku naznačuje, je čas začít pomocí migrace Code First.As the exception suggests, it’s time to start using Code First Migrations. Prvním krokem je povolení migrace pro náš kontext.The first step is to enable migrations for our context.

  • Spustit povolení migrace příkazu v konzole Správce balíčkůRun the Enable-Migrations command in Package Manager Console

    Tento příkaz má přidat migrace složku do projektu.This command has added a Migrations folder to our project. Tato nová složka obsahuje dva soubory:This new folder contains two files:

  • Třída konfigurace.The Configuration class. Tato třída umožňuje konfigurovat chování migrace pro váš kontext.This class allows you to configure how Migrations behaves for your context. V tomto návodu budeme používat jenom výchozí konfiguraci.For this walkthrough we will just use the default configuration. Vzhledem k tomu, že existuje pouze jeden kontext Code First ve vašem projektu, má povolení migrace automaticky vyplněna tato konfigurace se vztahuje na typ kontextu.Because there is just a single Code First context in your project, Enable-Migrations has automatically filled in the context type this configuration applies to.

  • Při migraci InitialCreate.An InitialCreate migration. Tato migrace se vygenerovat, protože jsme už měli Code First vytvořit databázi pro nás, než jsme povolili migrace.This migration was generated because we already had Code First create a database for us, before we enabled migrations. Kód v této vygenerované migraci představuje objekty, které již byly vytvořeny v databázi.The code in this scaffolded migration represents the objects that have already been created in the database. V našem, který je blogu tabulky s BlogId a název sloupce.In our case that is the Blog table with a BlogId and Name columns. Název souboru obsahuje časové razítko, které vám pomůžou s řazení.The filename includes a timestamp to help with ordering. Pokud databázi nebyl už vytvořili InitialCreate migrace by byly přidány do projektu. Při prvním říkáme migrace přidat kód k vytvoření těchto tabulek by místo toho automaticky generovaný nové migrace.If the database had not already been created this InitialCreate migration would not have been added to the project. Instead, the first time we call Add-Migration the code to create these tables would be scaffolded to a new migration.

Více modelů, které cílí na stejné databázeMultiple Models Targeting the Same Database

Při použití verze starší než EF6, pouze jeden model Code First může vygenerovat a spravovat schématu databáze.When using versions prior to EF6, only one Code First model could be used to generate/manage the schema of a database. To je výsledkem jednoho _ _MigrationsHistory tabulky na databázi s způsob, jak zjistit položky, které patří do které modelu.This is the result of a single __MigrationsHistory table per database with no way to identify which entries belong to which model.

Počínaje EF6, konfigurace obsahuje třídy ContextKey vlastnost.Starting with EF6, the Configuration class includes a ContextKey property. To slouží jako jedinečný identifikátor pro každý model Code First.This acts as a unique identifier for each Code First model. Odpovídající sloupec ve _ _MigrationsHistory tabulky umožňuje položky z více modelů pro sdílení v tabulce.A corresponding column in the __MigrationsHistory table allows entries from multiple models to share the table. Ve výchozím nastavení je tato vlastnost nastavena na plně kvalifikovaný název kontextu.By default, this property is set to the fully qualified name of your context.

Generování a spuštění migraceGenerating & Running Migrations

Migrace Code First má dva primární příkazy, které se chystáte seznámit se s.Code First Migrations has two primary commands that you are going to become familiar with.

  • Přidejte migraci bude generování uživatelského rozhraní další migrace na základě změn, které jste provedli pro váš model, od vytvoření posledního migraceAdd-Migration will scaffold the next migration based on changes you have made to your model since the last migration was created
  • Aktualizace databáze se použije čekající migrace do databázeUpdate-Database will apply any pending migrations to the database

Potřebujeme scaffold migrace, která se stará o novou vlastnost adresa Url, kterou jsme přidali.We need to scaffold a migration to take care of the new Url property we have added. Přidat migrace příkazu, umožníte nám tyto migrace pojmenujte, stačí pojmenujme náš AddBlogUrl.The Add-Migration command allows us to give these migrations a name, let’s just call ours AddBlogUrl.

  • Spustit přidat migrace AddBlogUrl příkazu v konzole Správce balíčkůRun the Add-Migration AddBlogUrl command in Package Manager Console
  • V migrace složky teď máme nový AddBlogUrl migrace.In the Migrations folder we now have a new AddBlogUrl migration. Název souboru migrace předem vyřešen s časovým razítkem usnadňující řazeníThe migration filename is pre-fixed with a timestamp to help with ordering
    namespace MigrationsDemo.Migrations
    {
        using System;
        using System.Data.Entity.Migrations;

        public partial class AddBlogUrl : DbMigration
        {
            public override void Up()
            {
                AddColumn("dbo.Blogs", "Url", c => c.String());
            }

            public override void Down()
            {
                DropColumn("dbo.Blogs", "Url");
            }
        }
    }

Nyní jsme může upravit nebo přidat do této migrace ale všechno, co vypadá poměrně dobře.We could now edit or add to this migration but everything looks pretty good. Použijeme aktualizace databáze použít tuto migraci do databáze.Let’s use Update-Database to apply this migration to the database.

  • Spustit aktualizace databáze příkazu v konzole Správce balíčkůRun the Update-Database command in Package Manager Console
  • Migrace Code First při porovnání migrace v našich migrace složky na základě těch, které se použily k databázi.Code First Migrations will compare the migrations in our Migrations folder with the ones that have been applied to the database. Je vidět, že AddBlogUrl migrace je potřeba použít a spustíme ji.It will see that the AddBlogUrl migration needs to be applied, and run it.

MigrationsDemo.BlogContext databáze je teď aktualizovaný zahrnout Url sloupec v blogy tabulky.The MigrationsDemo.BlogContext database is now updated to include the Url column in the Blogs table.

Přizpůsobení migraceCustomizing Migrations

Zatím jsme vygeneruje a spuštění migrace beze změn.So far we’ve generated and run a migration without making any changes. Nyní Pojďme se podívat na úpravy kódu, který získá vygenerována ve výchozím nastavení.Now let’s look at editing the code that gets generated by default.

  • Je čas provést některé další změny náš model, přidáme nový hodnocení vlastnost blogu třídyIt’s time to make some more changes to our model, let’s add a new Rating property to the Blog class
    public int Rating { get; set; }
  • Můžeme také přidat nový příspěvek třídyLet's also add a new Post class
    public class Post
    {
        public int PostId { get; set; }
        [MaxLength(200)]
        public string Title { get; set; }
        public string Content { get; set; }

        public int BlogId { get; set; }
        public Blog Blog { get; set; }
    }
  • Přidáme také příspěvky kolekce blogu třídy formuláře druhém konci vztahu mezi blogu a příspěvkuWe'll also add a Posts collection to the Blog class to form the other end of the relationship between Blog and Post
    public virtual List<Post> Posts { get; set; }

Použijeme přidat migrace příkaz, který umožní migrace Code First generování uživatelského rozhraní na migrace pro nás jeho co nejlepší odhad.We'll use the Add-Migration command to let Code First Migrations scaffold its best guess at the migration for us. My budeme volat tuto migraci AddPostClass.We’re going to call this migration AddPostClass.

  • Spustit přidat migrace AddPostClass příkazu v konzole Správce balíčků.Run the Add-Migration AddPostClass command in Package Manager Console.

Migrace Code First nebyla tom docela dobře práce pro generování uživatelského rozhraní tyto změny, ale existují některé možnosti, co chceme změnit:Code First Migrations did a pretty good job of scaffolding these changes, but there are some things we might want to change:

  1. Nejprve nahoru, přidáme jedinečný index k Posts.Title sloupec (přidání řádku 22 & 29 v následujícím kódu).First up, let’s add a unique index to Posts.Title column (Adding in line 22 & 29 in the code below).
  2. Také přidáváme neumožňující Blogs.Rating sloupce.We’re also adding a non-nullable Blogs.Rating column. Pokud není žádná existující data v tabulce ji získat přiřadí výchozí CLR datového typu pro nový sloupec (hodnocení je celé číslo, takže, který bude 0).If there is any existing data in the table it will get assigned the CLR default of the data type for new column (Rating is integer, so that would be 0). Chcete zadat výchozí hodnotu, ale 3 tak v tomto existujícím řádků blogy tabulky budou začínat vrazíme hodnocení.But we want to specify a default value of 3 so that existing rows in the Blogs table will start with a decent rating. (Zobrazí se výchozí hodnota zadaná na řádku 24 kód uvedený níže)(You can see the default value specified on line 24 of the code below)
    namespace MigrationsDemo.Migrations
    {
        using System;
        using System.Data.Entity.Migrations;

        public partial class AddPostClass : DbMigration
        {
            public override void Up()
            {
                CreateTable(
                    "dbo.Posts",
                    c => new
                        {
                            PostId = c.Int(nullable: false, identity: true),
                            Title = c.String(maxLength: 200),
                            Content = c.String(),
                            BlogId = c.Int(nullable: false),
                        })
                    .PrimaryKey(t => t.PostId)
                    .ForeignKey("dbo.Blogs", t => t.BlogId, cascadeDelete: true)
                    .Index(t => t.BlogId)
                    .Index(p => p.Title, unique: true);

                AddColumn("dbo.Blogs", "Rating", c => c.Int(nullable: false, defaultValue: 3));
            }

            public override void Down()
            {
                DropIndex("dbo.Posts", new[] { "Title" });
                DropIndex("dbo.Posts", new[] { "BlogId" });
                DropForeignKey("dbo.Posts", "BlogId", "dbo.Blogs");
                DropColumn("dbo.Blogs", "Rating");
                DropTable("dbo.Posts");
            }
        }
    }

Naše upravených migrace je připraven k přejít, takže použijeme aktualizace databáze uveďte aktuální databázi.Our edited migration is ready to go, so let’s use Update-Database to bring the database up-to-date. Nyní můžeme zadat – Verbose příznak, kde můžete zobrazit SQL, na kterém běží migrace Code First.This time let’s specify the –Verbose flag so that you can see the SQL that Code First Migrations is running.

  • Spustit aktualizace databáze – Verbose příkazu v konzole Správce balíčků.Run the Update-Database –Verbose command in Package Manager Console.

Pohyb dat nebo vlastními SQLData Motion / Custom SQL

Zatím jsme se podívat na migraci, které operace, které nechcete změnit nebo přesunout všechna data, teď Pojďme se podívat na něco, kterou je potřeba pohyb nějaká data.So far we have looked at migration operations that don’t change or move any data, now let’s look at something that needs to move some data around. Neexistuje žádná nativní podpora pro pohybu dat ještě, ale můžeme spustit některé libovolné příkazy SQL v libovolném bodě ve skriptu.There is no native support for data motion yet, but we can run some arbitrary SQL commands at any point in our script.

  • Přidejme Post.Abstract vlastnost našeho modelu.Let’s add a Post.Abstract property to our model. Později, přejdeme k předběžnému naplnění abstraktní existující příspěvky od začátku pomocí nějaký text obsahu sloupce.Later, we’re going to pre-populate the Abstract for existing posts using some text from the start of the Content column.
    public string Abstract { get; set; }

Použijeme přidat migrace příkaz, který umožní migrace Code First generování uživatelského rozhraní na migrace pro nás jeho co nejlepší odhad.We'll use the Add-Migration command to let Code First Migrations scaffold its best guess at the migration for us.

  • Spustit přidat migrace AddPostAbstract příkazu v konzole Správce balíčků.Run the Add-Migration AddPostAbstract command in Package Manager Console.
  • Vygenerovaný migrace se postará o změny schématu, ale také chceme k předběžnému naplnění abstraktní sloupce pomocí prvních 100 znaků obsahu pro jednotlivé příspěvky.The generated migration takes care of the schema changes but we also want to pre-populate the Abstract column using the first 100 characters of content for each post. Můžeme to udělat přetažením na SQL a spuštění aktualizace příkaz poté, co se má přidat sloupec.We can do this by dropping down to SQL and running an UPDATE statement after the column is added. (Přidání řádku 12 v následujícím kódu)(Adding in line 12 in the code below)
    namespace MigrationsDemo.Migrations
    {
        using System;
        using System.Data.Entity.Migrations;

        public partial class AddPostAbstract : DbMigration
        {
            public override void Up()
            {
                AddColumn("dbo.Posts", "Abstract", c => c.String());

                Sql("UPDATE dbo.Posts SET Abstract = LEFT(Content, 100) WHERE Abstract IS NULL");
            }

            public override void Down()
            {
                DropColumn("dbo.Posts", "Abstract");
            }
        }
    }

Naše upravených migrace je v pořádku, takže použijeme aktualizace databáze uveďte aktuální databázi.Our edited migration is looking good, so let’s use Update-Database to bring the database up-to-date. Budete určíme – Verbose příznak, jsme viděli SQL spuštěn na databázi.We’ll specify the –Verbose flag so that we can see the SQL being run against the database.

  • Spustit aktualizace databáze – Verbose příkazu v konzole Správce balíčků.Run the Update-Database –Verbose command in Package Manager Console.

Migrace na konkrétní verzi (včetně Downgrade)Migrate to a Specific Version (Including Downgrade)

Zatím jsme provedli vždy upgrade na nejnovější migrace, ale může nastat situace, kdy chcete upgradovat nebo downgradovat na konkrétní migrace.So far we have always upgraded to the latest migration, but there may be times when you want upgrade/downgrade to a specific migration.

Řekněme, že chceme migrovat databáze do stavu byl po spuštění našich AddBlogUrl migrace.Let’s say we want to migrate our database to the state it was in after running our AddBlogUrl migration. Můžeme použít – TargetMigration přepínač na starší verzi této migrace.We can use the –TargetMigration switch to downgrade to this migration.

  • Spustit aktualizace databáze – TargetMigration: AddBlogUrl příkazu v konzole Správce balíčků.Run the Update-Database –TargetMigration: AddBlogUrl command in Package Manager Console.

Tento příkaz spustí skript dolů pro naše AddBlogAbstract a AddPostClass migrace.This command will run the Down script for our AddBlogAbstract and AddPostClass migrations.

Pokud chcete úplně vrátit zpět na prázdnou databázi, pak můžete použít aktualizace databáze – TargetMigration: $InitialDatabase příkazu.If you want to roll all the way back to an empty database then you can use the Update-Database –TargetMigration: $InitialDatabase command.

Získávání skript SQLGetting a SQL Script

Pokud jiný vývojář chce, aby se tyto změny v jejich počítači se jenom synchronizovat až zkontrolujeme naše změny do správy zdrojového kódu.If another developer wants these changes on their machine they can just sync once we check our changes into source control. Jakmile budou mít naše nové migrace jsou pouze spustit příkaz aktualizace databáze chcete-li změny použít místně.Once they have our new migrations they can just run the Update-Database command to have the changes applied locally. Ale pokud se mají tyto změny vydat na testovací server a nakonec produkčního prostředí, chceme pravděpodobně skriptu SQL, který jsme můžete předat do našich DBA.However if we want to push these changes out to a test server, and eventually production, we probably want a SQL script we can hand off to our DBA.

  • Spustit aktualizace databáze příkazu, ale tentokrát zadejte – skript příznak tak, že změny jsou zapsány do skriptu namísto použití.Run the Update-Database command but this time specify the –Script flag so that changes are written to a script rather than applied. Také určíte zdrojovou a cílovou migrace se vygenerovat skript pro.We’ll also specify a source and target migration to generate the script for. Chceme, aby skript, který bude směřovat prázdnou databázi ($InitialDatabase) na nejnovější verzi (migrace AddPostAbstract).We want a script to go from an empty database ($InitialDatabase) to the latest version (migration AddPostAbstract). Pokud nezadáte target migrace, migrace použije nejnovější migrace jako cíl. Pokud nechcete zadat zdroj migrace, migrace použije aktuální stav databáze.If you don’t specify a target migration, Migrations will use the latest migration as the target. If you don't specify a source migrations, Migrations will use the current state of the database.
  • Spustit aktualizace databáze-skript - SourceMigration: $InitialDatabase - TargetMigration: AddPostAbstract příkazu v konzole Správce balíčkůRun the Update-Database -Script -SourceMigration: $InitialDatabase -TargetMigration: AddPostAbstract command in Package Manager Console

Migrace Code First, spustí se kanál migrace, ale místo ve skutečnosti použití změn ji bude vypsat je do souboru .sql za vás.Code First Migrations will run the migration pipeline but instead of actually applying the changes it will write them out to a .sql file for you. Po vygenerování skript ho je pro vás otevřen v aplikaci Visual Studio, které jsou připravené k zobrazení nebo uložení.Once the script is generated, it is opened for you in Visual Studio, ready for you to view or save.

Generování skriptů IdempotentníGenerating Idempotent Scripts

Počínaje EF6, pokud zadáte – SourceMigration $InitialDatabase generovaný skript bude "idempotentní".Starting with EF6, if you specify –SourceMigration $InitialDatabase then the generated script will be ‘idempotent’. Idempotentní skripty můžete upgradovat databázi aktuálně na žádné verze na nejnovější verzi (nebo zadaná verze, pokud používáte – TargetMigration).Idempotent scripts can upgrade a database currently at any version to the latest version (or the specified version if you use –TargetMigration). Generovaný skript obsahuje logiku pro kontrolu _ _MigrationsHistory tabulky a pouze použití změn, které dříve nebyly použity.The generated script includes logic to check the __MigrationsHistory table and only apply changes that haven't been previously applied.

Automaticky upgrade při spuštění aplikace (MigrateDatabaseToLatestVersion se inicializátor).Automatically Upgrading on Application Startup (MigrateDatabaseToLatestVersion Initializer)

Pokud nasazujete aplikaci můžete ho automaticky upgradovat databázi (s použitím čekající migrace) při spuštění aplikace.If you are deploying your application you may want it to automatically upgrade the database (by applying any pending migrations) when the application launches. Můžete to provést tak, že zaregistrujete MigrateDatabaseToLatestVersion inicializátor databáze.You can do this by registering the MigrateDatabaseToLatestVersion database initializer. Inicializátor databáze obsahuje některé logiku, která se používá k Ujistěte se, že databáze je správně nastavený.A database initializer simply contains some logic that is used to make sure the database is setup correctly. Tato logika je spustit při prvním kontextu se používá v rámci procesu aplikace (AppDomain).This logic is run the first time the context is used within the application process (AppDomain).

Abychom mohli aktualizovat Program.cs souboru, jak je znázorněno níže, chcete-li nastavit MigrateDatabaseToLatestVersion inicializátor pro BlogContext dřív, než kontextu (řádek 14).We can update the Program.cs file, as shown below, to set the MigrateDatabaseToLatestVersion initializer for BlogContext before we use the context (Line 14). Všimněte si, že musíte také přidat sadu pomocí příkazu pro System.Data.Entity obor názvů (řádku 5).Note that you also need to add a using statement for the System.Data.Entity namespace (Line 5).

Když vytvoříme instanci této inicializátoru, musíme určit typ kontextu (BlogContext) a konfiguraci migrace (konfigurace) – konfigurace migrace je třída, která je teď Přidá do našich migrace složky, pokud jsme povolili migrace.When we create an instance of this initializer we need to specify the context type (BlogContext) and the migrations configuration (Configuration) - the migrations configuration is the class that got added to our Migrations folder when we enabled Migrations.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Data.Entity;
    using MigrationsDemo.Migrations;

    namespace MigrationsDemo
    {
        class Program
        {
            static void Main(string[] args)
            {
                Database.SetInitializer(new MigrateDatabaseToLatestVersion<BlogContext, Configuration>());

                using (var db = new BlogContext())
                {
                    db.Blogs.Add(new Blog { Name = "Another Blog " });
                    db.SaveChanges();

                    foreach (var blog in db.Blogs)
                    {
                        Console.WriteLine(blog.Name);
                    }
                }

                Console.WriteLine("Press any key to exit...");
                Console.ReadKey();
            }
        }
    }

Nyní pokaždé, když naše spouštět aplikace, nejprve zjistí, pokud databáze je zaměřen na aktuální a použít všechny probíhající migrace, pokud není.Now whenever our application runs it will first check if the database it is targeting is up-to-date, and apply any pending migrations if it is not.