diff --git a/entity-framework/core/managing-schemas/migrations/applying.md b/entity-framework/core/managing-schemas/migrations/applying.md new file mode 100644 index 0000000000..fbb2ebbe61 --- /dev/null +++ b/entity-framework/core/managing-schemas/migrations/applying.md @@ -0,0 +1,183 @@ +--- +title: Applying Migrations - EF Core +author: bricelam +ms.author: bricelam +ms.date: 05/06/2020 +uid: core/managing-schemas/migrations/applying +--- +# Applying Migrations + +Once your migrations have been added, they need to be deployed and applied to your databases. There are various strategies for doing this, with some being more appropriate for production environments, and others for the development lifecycle. + +> [!NOTE] +> Whatever your deployment strategy, always inspect the generated migrations and test them applying to a production database. A migration may drop a column when the intent was to rename it, or may fail for various when applied to a database. + +## SQL scripts + +The recommended way to deploy migrations to a production database is by generating SQL scripts. The advantages of this strategy include the following: + +* SQL scripts can be reviewed for accuracy; this is important since applying schema changes to production databases is a potentially dangerous operation that could involve data loss. +* In some cases, the scripts can be tuned to fit the specific needs of a production database. +* SQL scripts can be used in conjunction with a deployment technology. +* SQL scripts can be provided to a DBA, and can be managed and archived separately. + +### [.NET Core CLI](#tab/dotnet-core-cli) + +#### Basic Usage + +The following generates a SQL script from a blank database to the latest migration: + +```dotnetcli +dotnet ef migrations script +``` + +#### With From (to implied) + +The following generates a SQL script from the given migration to the latest migration. + +```dotnetcli +dotnet ef migrations script AddNewTables +``` + +#### With From and To + +The following generates a SQL script from the `from` migration to the specified `to` migration. + +```dotnetcli +dotnet ef migrations script AddNewTables AddAuditTable +``` + +You can use a `from` that is newer than the `to` in order to generate a rollback script. *Please take note of potential data loss scenarios.* + +### [Visual Studio](#tab/vs) + +The following generates a SQL script from a blank database to the latest migration: + +#### Basic Usage + +``` powershell +Script-Migration +``` + +#### With From (to implied) + +The following generates a SQL script from this migration to the latest migration. + +```powershell +Script-Migration AddNewTables +``` + +#### With From and To + +The following generates a SQL script from the `from` migration to the specified `to` migration. + +```powershell +Script-Migration AddNewTables AddAuditTable +``` +You can use a `from` that is newer than the `to` in order to generate a rollback script. *Please take note of potential data loss scenarios.* + +*** + +There are several options to this command. + +The **from** migration should be the last migration applied to the database before running the script. If no migrations have been applied, specify `0` (this is the default). + +The **to** migration is the last migration that will be applied to the database after running the script. This defaults to the last migration in your project. + +## Idempotent SQL scripts + +The SQL scripts generated above can only be applied to change your schema from one migration to another; it is your responsibility to apply the script appropriately, and only to database in the correct migration state. EF Core also supports generating **idempotent** scripts, which internally check which migrations have already been applied, and only apply missing ones. This is useful if you don't exactly know what the last migration applied to the database was, or if you are deploying to multiple databases that may each be at a different migration. + +The following generates idempotent migrations: + +#### [.NET Core CLI](#tab/dotnet-core-cli) + +```dotnetcli +dotnet ef migrations add AddNewTables --idempotent +``` + +#### [Visual Studio](#tab/vs) + +``` powershell +Add-Migration AddNewTables -Idempotent +``` + +> [!WARNING] +> Idempotent scripts have some known limitations and will not work in all scenarios. + +*** + +## Command-line tools + +The EF command-line tools can be used to apply migrations to a database. While productive for local development and testing of migrations, this approach is inappropriate for management of production databases: + +* The SQL commands are applied directly by the tool, without giving the developer a change to inspect or modify them. This can be dangerous in a production environment. +* The .NET SDK and the EF tool must be installed on production servers. + +### [.NET Core CLI](#tab/dotnet-core-cli) + +The following updates your database to the latest migration: + +```dotnetcli +dotnet ef database update +``` + +The following updates your database to a given migration: + +```dotnetcli +dotnet ef database update AddNewTables +``` + +### [Visual Studio](#tab/vs) + +The following updates your database to the latest migration: + +``` powershell +Update-Database +``` + +The following updates your database to a given migration: + +``` powershell +Update-Database AddNewTables +``` + +*** + +Note that this can be used to roll back to an earlier migration as well. *Please take note of potential data loss scenarios.* + +For more information on applying migrations via the command-line tools, see the [EF Core tools reference](xref:core/miscellaneous/cli/index). + +## Apply migrations at runtime + +It's possible for the application itself to apply migrations programmatically, typically during startup. While productive for local development and testing of migrations, this approach is inappropriate for management of production databases: + +* If multiple instances of your application are running, both applications could attempt to apply the migration concurrently and fail (or worse, cause data corruption). +* Similarly, if an application is accessing the database while another application migrates it, this can cause severe issues. +* This requires the application to have elevated access to modify the database schema. It's generally good practice to limit the application's database permissions in production. +* It's important to be able to roll back an applied migration in case of an issue. The other strategies provide this easily and out of the box. +* The SQL commands are applied directly by the program, without giving the developer a change to inspect or modify them. This can be dangerous in a production environment. + +To apply migrations programmatically, call `myDbContext.Database.Migrate()`. For example, a typical ASP.NET application can do the following: + +```c# +public static void Main(string[] args) +{ + var host = CreateHostBuilder(args).Build(); + + using (var scope = host.Services.CreateScope()) + { + var db = scope.ServiceProvider.GetRequiredService(); + db.Database.Migrate(); + } + + host.Run(); +} +``` + +Note that `Migrate()` builds on top of the `IMigrator` service, which can be used for more advanced scenarios. Use `myDbContext.GetInfrastructure().GetService()` to access it. + +> [!WARNING] +> +> * Carefully consider before using this approach in production. Experience has shown that the simplicity of this deployment strategy is outweighed by the problem it brings. Consider using SQL scripts instead. +> * Don't call `EnsureCreated()` before `Migrate()`. `EnsureCreated()` bypasses Migrations to create the schema, which causes `Migrate()` to fail. diff --git a/entity-framework/core/managing-schemas/migrations/index.md b/entity-framework/core/managing-schemas/migrations/index.md index 8ee0360ab3..002cb98dab 100644 --- a/entity-framework/core/managing-schemas/migrations/index.md +++ b/entity-framework/core/managing-schemas/migrations/index.md @@ -1,294 +1,184 @@ --- -title: Migrations - EF Core +title: Migrations Overview - EF Core author: bricelam ms.author: bricelam -ms.date: 10/05/2018 +ms.date: 05/06/2020 uid: core/managing-schemas/migrations/index --- -# Migrations +# Migrations Overview -A data model changes during development and gets out of sync with the database. You can drop the database and let EF create a new one that matches the model, but this procedure results in the loss of data. The migrations feature in EF Core provides a way to incrementally update the database schema to keep it in sync with the application's data model while preserving existing data in the database. +In real life projects, data models change as features get implemented: new entities or properties are added and removed, and databases schema needs to be changed accordingly to be kept in sync with the application. The migrations feature in EF Core provides a way to incrementally update the database schema to keep it in sync with the application's data model while preserving existing data in the database. -Migrations includes command-line tools and APIs that help with the following tasks: +At a high level, migrations functions in the following way: -* [Create a migration](#create-a-migration). Generate code that can update the database to sync it with a set of model changes. -* [Update the database](#update-the-database). Apply pending migrations to update the database schema. -* [Customize migration code](#customize-migration-code). Sometimes the generated code needs to be modified or supplemented. -* [Remove a migration](#remove-a-migration). Delete the generated code. -* [Revert a migration](#revert-a-migration). Undo the database changes. -* [Generate SQL scripts](#generate-sql-scripts). You might need a script to update a production database or to troubleshoot migration code. -* [Apply migrations at runtime](#apply-migrations-at-runtime). When design-time updates and running scripts aren't the best options, call the `Migrate()` method. +* When a data model change is introduced, the developer uses EF Core tools to add a corresponding migration describing the updates necessary to keep the database schema in sync. EF Core compares the current model against a snapshot of the old model to find out the differences, and generates migration source files; the files are kept in your project's source control like any other source file. +* Once a new migration has been generated, it can be deployed to a database in various ways. EF Core uses a migrations history table in the database which records all migrations which have already been applied; this allows EF Core to know which state your database is in. -> [!TIP] -> If the `DbContext` is in a different assembly than the startup project, you can explicitly specify the target and startup projects in either the [Package Manager Console tools](xref:core/miscellaneous/cli/powershell#target-and-startup-project) or the [.NET Core CLI tools](xref:core/miscellaneous/cli/dotnet#target-project-and-startup-project). +## Tutorial -## Install the tools +Let's assume you've just completed your first EF Core application, which contains the following simple model: -Install the [command-line tools](xref:core/miscellaneous/cli/index): - -* For Visual Studio, we recommend the [Package Manager Console tools](xref:core/miscellaneous/cli/powershell). -* For other development environments, choose the [.NET Core CLI tools](xref:core/miscellaneous/cli/dotnet). - -## Create a migration - -After you've [defined your initial model](xref:core/modeling/index), it's time to create the database. To add an initial migration, run the following command. - -### [.NET Core CLI](#tab/dotnet-core-cli) - -```dotnetcli -dotnet ef migrations add InitialCreate -``` - -### [Visual Studio](#tab/vs) - -``` powershell -Add-Migration InitialCreate +```c# +public class Blog +{ + public int Id { get; set; } + public string Name { get; set; } +} ``` -*** - -Three files are added to your project under the **Migrations** directory: +During development, you may have used the [Create and Drop APIs](xref:core/managing-schemas/ensure-created) to iterate quickly; but now that your application is going to production, you need a way to evolve the schema without dropping the entire database. -* **XXXXXXXXXXXXXX_InitialCreate.cs**--The main migrations file. Contains the operations necessary to apply the migration (in `Up()`) and to revert it (in `Down()`). -* **XXXXXXXXXXXXXX_InitialCreate.Designer.cs**--The migrations metadata file. Contains information used by EF. -* **MyContextModelSnapshot.cs**--A snapshot of your current model. Used to determine what changed when adding the next migration. +### Install the tools -The timestamp in the filename helps keep them ordered chronologically so you can see the progression of changes. +First, you'll have to install the [EF Core command-line tools](xref:core/miscellaneous/cli/index): -### Namespaces +* We generally recommend using the [.NET Core CLI tools](xref:core/miscellaneous/cli/dotnet), which work on all platforms. +* If you're more comfortable working inside Visual Studio or have experience with EF6 migrations, you can also use the [Package Manager Console tools](xref:core/miscellaneous/cli/powershell). -You are free to move Migrations files and change their namespace manually. New migrations are created as siblings of the last migration. +### Create your first migration -Alternatively you can use `-Namespace` (Package Manager Console) or `--namespace` (.NET Core CLI) to specify the namespace at generation time. +You're now ready to add your first migration! Instruct EF Core to create a migrations named **InitialCreate**: -### [.NET Core CLI](#tab/dotnet-core-cli) +#### [.NET Core CLI](#tab/dotnet-core-cli) ```dotnetcli -dotnet ef migrations add InitialCreate --namespace Your.Namespace +dotnet ef migrations add InitialCreate ``` -### [Visual Studio](#tab/vs) +#### [Visual Studio](#tab/vs) ``` powershell -Add-Migration InitialCreate -Namespace Your.Namespace +Add-Migration InitialCreate ``` *** -## Update the database +EF Core will create a directory called **Migrations**, and generated some files. In general, it's a good idea to inspect what exactly EF Core generated - and possibly amend it - but we'll skip over that for now. -Next, apply the migration to the database to create the schema. +### Create a migration SQL script -### [.NET Core CLI](#tab/dotnet-core-cli) +You now want to create your first production database and apply your migration there. In production scenarios, you typically need to create the database yourself, e.g. by using a cloud service user interface, or asking your DBA. Once an empty database is available, you can generate an *SQL script* from the migration we've just created: -```dotnetcli -dotnet ef database update -``` - -### [Visual Studio](#tab/vs) - -``` powershell -Update-Database -``` - -*** - -## Customize migration code - -After making changes to your EF Core model, the database schema might be out of sync. To bring it up to date, add another migration. The migration name can be used like a commit message in a version control system. For example, you might choose a name like *AddProductReviews* if the change is a new entity class for reviews. - -### [.NET Core CLI](#tab/dotnet-core-cli) +#### [.NET Core CLI](#tab/dotnet-core-cli) ```dotnetcli -dotnet ef migrations add AddProductReviews +dotnet ef migrations script -o InitialCreate.sql ``` - -### [Visual Studio](#tab/vs) +#### [Visual Studio](#tab/vs) ``` powershell -Add-Migration AddProductReviews +Script-Migration -Output InitialCreate.sql ``` *** -Once the migration is scaffolded (code generated for it), review the code for accuracy and add, remove or modify any operations required to apply it correctly. - -For example, a migration might contain the following operations: - -``` csharp -migrationBuilder.DropColumn( - name: "FirstName", - table: "Customer"); - -migrationBuilder.DropColumn( - name: "LastName", - table: "Customer"); +You now have an **InitialCreate.sql** script which can be executed against your empty database to create the schema corresponding to your model. If you're using SQL Server, the script should resemble the following: -migrationBuilder.AddColumn( - name: "Name", - table: "Customer", - nullable: true); -``` +```sql +IF OBJECT_ID(N'[__EFMigrationsHistory]') IS NULL +BEGIN + CREATE TABLE [__EFMigrationsHistory] ( + [MigrationId] nvarchar(150) NOT NULL, + [ProductVersion] nvarchar(32) NOT NULL, + CONSTRAINT [PK___EFMigrationsHistory] PRIMARY KEY ([MigrationId]) + ); +END; -While these operations make the database schema compatible, they don't preserve the existing customer names. To make it better, rewrite it as follows. +GO -``` csharp -migrationBuilder.AddColumn( - name: "Name", - table: "Customer", - nullable: true); +CREATE TABLE [Blogs] ( + [Id] int NOT NULL IDENTITY, + [Name] nvarchar(max) NULL, + CONSTRAINT [PK_Blogs] PRIMARY KEY ([Id]) +); -migrationBuilder.Sql( -@" - UPDATE Customer - SET Name = FirstName + ' ' + LastName; -"); +GO -migrationBuilder.DropColumn( - name: "FirstName", - table: "Customer"); +INSERT INTO [__EFMigrationsHistory] ([MigrationId], [ProductVersion]) +VALUES (N'20200604212813_InitialCreate', N'3.1.4'); -migrationBuilder.DropColumn( - name: "LastName", - table: "Customer"); +GO ``` -> [!TIP] -> The migration scaffolding process warns when an operation might result in data loss (like dropping a column). If you see that warning, be especially sure to review the migrations code for accuracy. - -Apply the migration to the database using the appropriate command. +The script contains three parts: -### [.NET Core CLI](#tab/dotnet-core-cli) +1. The migrations history table is created; this table will store all migrations applied to this database. It only occurs only in the very first migration. +2. Our `Blogs` table is created, based on our code model. This is the actual migration action. +3. A row is inserted into the migrations history table, to record that the **InitialCreate** migration was applied. -```dotnetcli -dotnet ef database update -``` +### Apply the script to your database -### [Visual Studio](#tab/vs) +After we've examined the SQL script and are satisfied with it, we can execute it on our empty database. How this is done varies across databases, but with SQL Server you can use `sqlcmd`: -``` powershell -Update-Database +```console +sqlcmd -S -U -d -i InitialCreate.sql ``` -*** - -### Empty migrations - -Sometimes it's useful to add a migration without making any model changes. In this case, adding a new migration creates code files with empty classes. You can customize this migration to perform operations that don't directly relate to the EF Core model. Some things you might want to manage this way are: +Congratulations, you've just applied your first migration! -* Full-Text Search -* Functions -* Stored procedures -* Triggers -* Views +### Evolving your model -## Remove a migration +A few days have passed, and you're asked to add a creation timestamp to your blogs. You've done the necessary changes to your application, and your model now looks like this: -Sometimes you add a migration and realize you need to make additional changes to your EF Core model before applying it. To remove the last migration, use this command. - -### [.NET Core CLI](#tab/dotnet-core-cli) - -```dotnetcli -dotnet ef migrations remove -``` - -### [Visual Studio](#tab/vs) - -``` powershell -Remove-Migration +```c# +public class Blog +{ + public int Id { get; set; } + public string Name { get; set; } + public DateTime CreatedTimestamp { get; set; } +} ``` -*** +Your model and your production database are now out of sync - we must add a new column to your database schema. Let's create a new migration for this: -After removing the migration, you can make the additional model changes and add it again. -## Revert a migration - -If you already applied a migration (or several migrations) to the database but need to revert it, you can use the same command to apply migrations, but specify the name of the migration you want to roll back to. - -### [.NET Core CLI](#tab/dotnet-core-cli) +#### [.NET Core CLI](#tab/dotnet-core-cli) ```dotnetcli -dotnet ef database update LastGoodMigration +dotnet ef migrations add AddBlogCreatedTimestamp ``` -### [Visual Studio](#tab/vs) +#### [Visual Studio](#tab/vs) ``` powershell -Update-Database LastGoodMigration +Add-Migration AddBlogCreatedTimestamp ``` *** -## Generate SQL scripts - -When debugging your migrations or deploying them to a production database, it's useful to generate a SQL script. The script can then be further reviewed for accuracy and tuned to fit the needs of a production database. The script can also be used in conjunction with a deployment technology. The basic command is as follows. - -### [.NET Core CLI](#tab/dotnet-core-cli) +Note that we give migrations a descriptive name, to make it easier to understand the project history later. Since this isn't the project's first migration, EF Core now compares your updated model against a snapshot of the old model, before the column was added; the model snapshot is one of the files generated by EF Core when you add a migration, and is checked into source control. Based on that comparison, EF Core detects that a column has been added, and adds the appropriate migration. -#### Basic Usage -```dotnetcli -dotnet ef migrations script -``` +We now want to generate an SQL script, just like before. However, the **InitialCreate** migration has already been applied to our database, so our new script should contain only the schema changes since that point: -#### With From (to implied) -This will generate a SQL script from this migration to the latest migration. -```dotnetcli -dotnet ef migrations script 20190725054716_Add_new_tables -``` +#### [.NET Core CLI](#tab/dotnet-core-cli) -#### With From and To -This will generate a SQL script from the `from` migration to the specified `to` migration. ```dotnetcli -dotnet ef migrations script 20190725054716_Add_new_tables 20190829031257_Add_audit_table +dotnet ef migrations script -o AddBlogCreatedTimestamp.sql InitialCreate ``` -You can use a `from` that is newer than the `to` in order to generate a rollback script. *Please take note of potential data loss scenarios.* +#### [Visual Studio](#tab/vs) -### [Visual Studio](#tab/vs) - -#### Basic Usage ``` powershell -Script-Migration -``` - -#### With From (to implied) -This will generate a SQL script from this migration to the latest migration. -```powershell -Script-Migration 20190725054716_Add_new_tables +Script-Migration -Output AddBlogCreatedTimestamp.sql InitialCreate ``` -#### With From and To -This will generate a SQL script from the `from` migration to the specified `to` migration. -```powershell -Script-Migration 20190725054716_Add_new_tables 20190829031257_Add_audit_table -``` -You can use a `from` that is newer than the `to` in order to generate a rollback script. *Please take note of potential data loss scenarios.* - *** -There are several options to this command. - -The **from** migration should be the last migration applied to the database before running the script. If no migrations have been applied, specify `0` (this is the default). - -The **to** migration is the last migration that will be applied to the database after running the script. This defaults to the last migration in your project. +Note the new parameter, which instructs EF Core to generate a script *since* the given migration. Our new SQL script should look the following: -An **idempotent** script can optionally be generated. This script only applies migrations if they haven't already been applied to the database. This is useful if you don't exactly know what the last migration applied to the database was or if you are deploying to multiple databases that may each be at a different migration. -## Apply migrations at runtime +```sql +ALTER TABLE [Blogs] ADD [CreatedTimestamp] datetime2 NOT NULL DEFAULT '0001-01-01T00:00:00.0000000'; -Some apps may want to apply migrations at runtime during startup or first run. Do this using the `Migrate()` method. +GO -This method builds on top of the `IMigrator` service, which can be used for more advanced scenarios. Use `myDbContext.GetInfrastructure().GetService()` to access it. +INSERT INTO [__EFMigrationsHistory] ([MigrationId], [ProductVersion]) +VALUES (N'20200604214444_AddBlogCreatedTimestamp', N'3.1.4'); -``` csharp -myDbContext.Database.Migrate(); +GO ``` -> [!WARNING] -> -> * This approach isn't for everyone. While it's great for apps with a local database, most applications will require more robust deployment strategy like generating SQL scripts. -> * Don't call `EnsureCreated()` before `Migrate()`. `EnsureCreated()` bypasses Migrations to create the schema, which causes `Migrate()` to fail. +The script first adds our new column to the database, and then records that the migration has been applied in the migrations history table. -## Next steps +### Next steps -For more information, see . +The above was only a brief introduction to migrations, please consult the other documentation pages to learn more about [managing migrations](xref:core/managing-schemas/migrations/managing), [applying them](xref:core/managing-schemas/migrations/applying), and other aspects. The [.NET Core CLI tool reference](xref:core/miscellaneous/cli/index) also contains useful information on the different commands diff --git a/entity-framework/core/managing-schemas/migrations/managing.md b/entity-framework/core/managing-schemas/migrations/managing.md new file mode 100644 index 0000000000..dc87922ff0 --- /dev/null +++ b/entity-framework/core/managing-schemas/migrations/managing.md @@ -0,0 +1,201 @@ +--- +title: Managing Migrations - EF Core +author: bricelam +ms.author: bricelam +ms.date: 05/06/2020 +uid: core/managing-schemas/migrations/managing +--- +# Managing Migrations + +As your model changes, migrations are added and removed as part of normal development, and the results are checked into your project's source control. To manage migrations, you must first install the [EF Core command-line tools](xref:core/miscellaneous/cli/index). + +> [!TIP] +> If the `DbContext` is in a different assembly than the startup project, you can explicitly specify the target and startup projects in either the [Package Manager Console tools](xref:core/miscellaneous/cli/powershell#target-and-startup-project) or the [.NET Core CLI tools](xref:core/miscellaneous/cli/dotnet#target-project-and-startup-project). + +## Add a migration + +After your model has been changed, you can add a migration for that change: + +### [.NET Core CLI](#tab/dotnet-core-cli) + +```dotnetcli +dotnet ef migrations add AddCreatedTimestamp +``` + +### [Visual Studio](#tab/vs) + +``` powershell +Add-Migration AddCreatedTimestamp +``` + +*** + +The migration name can be used like a commit message in a version control system. For example, you might choose a name like *AddBlogCreatedTimestamp* if the change is a new `CreatedTimestamp` property on your `Blog` entity. + +Three files are added to your project under the **Migrations** directory: + +* **XXXXXXXXXXXXXX_AddCreatedTimestamp.cs**--The main migrations file. Contains the operations necessary to apply the migration (in `Up()`) and to revert it (in `Down()`). +* **XXXXXXXXXXXXXX_AddCreatedTimestamp.Designer.cs**--The migrations metadata file. Contains information used by EF. +* **MyContextModelSnapshot.cs**--A snapshot of your current model. Used to determine what changed when adding the next migration. + +The timestamp in the filename helps keep them ordered chronologically so you can see the progression of changes. + +### Namespaces + +You are free to move Migrations files and change their namespace manually. New migrations are created as siblings of the last migration. + +Alternatively you can use `-Namespace` (Package Manager Console) or `--namespace` (.NET Core CLI) to specify the namespace at generation time. + +### [.NET Core CLI](#tab/dotnet-core-cli) + +```dotnetcli +dotnet ef migrations add InitialCreate --namespace Your.Namespace +``` + +### [Visual Studio](#tab/vs) + +``` powershell +Add-Migration InitialCreate -Namespace Your.Namespace +``` + +*** + +## Customize migration code + +While EF Core generally creates accurate migrations, you should always review the code and make sure it corresponds to the desired change. Although migration code is generated by EF Core, in many cases it is good practice to edit them and customize them appropriately. + +### Column renames + +One notable examine where customizing migrations is required is when renaming a property. For example, if you rename a property from `Name` to `FullName`, EF Core will generate the following migration: + +```c# +migrationBuilder.DropColumn( + name: "Name", + table: "Customers"); + +migrationBuilder.AddColumn( + name: "FullName", + table: "Customers", + nullable: true); +``` + +If applied as-is, this migration will cause you to lose all your customer names; EF Core is unable to know when the intention is to rename a column, and when it is the intention to drop and create a new column. In these cases, modify the generated migration as follows: + +```c# +migrationBuilder.RenameColumn( + name: "Name", + table: "Customers", + newName: "FullName"); +``` + +### Adding raw SQL + +While renaming a column can be achieved via a built-in API, in many cases that is not possible. For example, we may want to replace existing `FirstName` and `LastColumn` properties with a single, new `FullName` property. The migration generated by EF Core will be the following: + +``` csharp +migrationBuilder.DropColumn( + name: "FirstName", + table: "Customer"); + +migrationBuilder.DropColumn( + name: "LastName", + table: "Customer"); + +migrationBuilder.AddColumn( + name: "Name", + table: "Customer", + nullable: true); +``` + +As before, this would cause unwanted data loss. To transfer the data from the old columns, we rearrange the migrations and introduce a raw SQL operation as follows: + +``` csharp +migrationBuilder.AddColumn( + name: "Name", + table: "Customer", + nullable: true); + +migrationBuilder.Sql( +@" + UPDATE Customer + SET Name = FirstName + ' ' + LastName; +"); + +migrationBuilder.DropColumn( + name: "FirstName", + table: "Customer"); + +migrationBuilder.DropColumn( + name: "LastName", + table: "Customer"); +``` + +> [!TIP] +> The migration scaffolding process warns when an operation might result in data loss (like dropping a column). If you see that warning, be especially sure to review the migrations code for accuracy. + +### Arbitrary changes via raw SQL + +Raw SQL can also be used to manage database objects that EF Core isn't aware of. To do this, add a migration without making any model change; an empty migration will be generated, which you can populate with raw SQL operations. + +For example, the following migration creates a SQL Server stored procedure: + +```c# +migrationBuilder.Sql( +@" + CREATE PROCEDURE getFullName + @LastName nvarchar(50), + @FirstName nvarchar(50) + AS + RETURN @LastName + @FirstName; +"); +``` + +This can be used to manage any aspect of your database, including: + +* Stored procedures +* Full-Text Search +* Functions +* Triggers +* Views + +## Remove a migration + +Sometimes you add a migration and realize you need to make additional changes to your EF Core model before applying it. To remove the last migration, use this command. + +### [.NET Core CLI](#tab/dotnet-core-cli) + +```dotnetcli +dotnet ef migrations remove +``` + +### [Visual Studio](#tab/vs) + +``` powershell +Remove-Migration +``` + +*** + +After removing the migration, you can make the additional model changes and add it again. + +> [!WARNING] +> Take care not to remove any migrations which are already applied to production databases. + +## Listing migrations + +You can list all existing migrations as follows: + +```dotnetcli +dotnet ef migrations list +``` + +## Resetting all migrations + +In some extreme cases, it may be necessary to remove all migrations and start over. This can be easily done by deleting your **Migrations** folder and dropping your database. At that point you can create a new initial migration, which will contain you entire current schema. + +It's also possible to reset all migrations and create a single one without losing your data. This is sometimes called "squashing", and involves some manual work: + +* Delete your **Migrations** folder +* Create a new migration and generate a SQL script for it +* In your database, delete all rows from the migrations history table +* Insert a single row into the migrations history - this is the last operation in the SQL script generated above. diff --git a/entity-framework/toc.yml b/entity-framework/toc.yml index 048af9ba24..56bf42e863 100644 --- a/entity-framework/toc.yml +++ b/entity-framework/toc.yml @@ -141,6 +141,10 @@ items: - name: Overview href: core/managing-schemas/migrations/index.md + - name: Managing migrations + href: core/managing-schemas/migrations/managing.md + - name: Applying migrations + href: core/managing-schemas/migrations/applying.md - name: Team environments href: core/managing-schemas/migrations/teams.md - name: Custom operations