Skip to content

Commit

Permalink
Document passing design-time args
Browse files Browse the repository at this point in the history
Additional changes:

- Add tips about EXEC (fixes #2561)
- Add a tab for Get-Migration
- Update custom operation samples (fixes #1574)
- Fix some bad PMC examples (fixes #2296)
- Add examples using Name= (fixes #2145)
- Mention ExcludeFromMigrations (fixes #750)
- Rearrange connection strings page
- Use OutputDir instead of Namespace

Fixes #1050
  • Loading branch information
bricelam committed Nov 3, 2020
1 parent 73d6b8c commit f0f6905
Show file tree
Hide file tree
Showing 12 changed files with 278 additions and 156 deletions.
11 changes: 10 additions & 1 deletion entity-framework/core/managing-schemas/migrations/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: Migrations Overview - EF Core
description: Overview of using migrations to manage database schemas with Entity Framework Core
author: bricelam
ms.date: 05/06/2020
ms.date: 10/28/2020
uid: core/managing-schemas/migrations/index
---
# Migrations Overview
Expand Down Expand Up @@ -132,6 +132,15 @@ Update-Database

Note that this time, EF detects that the database already exists. In addition, when our first migration was applied above, this fact was recorded in a special migrations history table in your database; this allows EF to automatically apply only the new migration.

### Excluding parts of your model

> [!NOTE]
> This feature was added in EF Core 5.0.
Sometimes you may want to reference types from another DbContext. This can lead to migration conflicts. To prevent this, exclude the type from the migrations of one of the DbContexts.

[!code-csharp[](../../../../samples/core/Modeling/FluentAPI/TableExcludeFromMigrations.cs#TableExcludeFromMigrations)]

### Next steps

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
30 changes: 26 additions & 4 deletions entity-framework/core/managing-schemas/migrations/managing.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: Managing Migrations - EF Core
description: Adding, removing and otherwise managing database schema migrations with Entity Framework Core
author: bricelam
ms.date: 05/06/2020
ms.date: 10/27/2020
uid: core/managing-schemas/migrations/managing
---
# Managing Migrations
Expand Down Expand Up @@ -42,20 +42,26 @@ The timestamp in the filename helps keep them ordered chronologically so you can

### 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 specify the namespace at generation time as follows:
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 specify the directory at generation time as follows:

#### [.NET Core CLI](#tab/dotnet-core-cli)

```dotnetcli
dotnet ef migrations add InitialCreate --namespace Your.Namespace
dotnet ef migrations add InitialCreate --output-dir Your/Directory
```

> [!NOTE]
> In EF Core 5.0, you can also change the namespace independently of the directory using `--namespace`.
#### [Visual Studio](#tab/vs)

```powershell
Add-Migration InitialCreate -Namespace Your.Namespace
Add-Migration InitialCreate -OutputDir Your\Directory
```

> [!NOTE]
> In EF Core 5.0, you can also change the namespace independently of the directory using `-Namespace`.
***

## Customize migration code
Expand Down Expand Up @@ -147,6 +153,9 @@ migrationBuilder.Sql(
RETURN @LastName + @FirstName;')");
```

> [!TIP]
> `EXEC` is used when a statement must be the first or only one in a SQL batch. It can also be used to work around parser errors in idempotent migration scripts that can occur when referenced columns don't currently exist on a table.
This can be used to manage any aspect of your database, including:

* Stored procedures
Expand Down Expand Up @@ -186,10 +195,23 @@ After removing the migration, you can make the additional model changes and add

You can list all existing migrations as follows:

### [.NET Core CLI](#tab/dotnet-core-cli)

```dotnetcli
dotnet ef migrations list
```

### [Visual Studio](#tab/vs)

> [!NOTE]
> This command was added in EF Core 5.0.
```powershell
Get-Migration
```

***

## 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.
Expand Down
109 changes: 10 additions & 99 deletions entity-framework/core/managing-schemas/migrations/operations.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: Custom Migrations Operations - EF Core
description: Managing custom and raw SQL migrations for database schema management with Entity Framework Core
author: bricelam
ms.date: 11/07/2017
ms.date: 10/27/2020
uid: core/managing-schemas/migrations/operations
---
# Custom Migrations Operations
Expand All @@ -19,120 +19,31 @@ migrationBuilder.CreateUser("SQLUser1", "Password");

The easiest way to implement a custom operation is to define an extension method that calls `MigrationBuilder.Sql()`. Here is an example that generates the appropriate Transact-SQL.

```csharp
static MigrationBuilder CreateUser(
this MigrationBuilder migrationBuilder,
string name,
string password)
=> migrationBuilder.Sql($"CREATE USER {name} WITH PASSWORD '{password}';");
```
[!code-csharp[](../../../../samples/core/Schemas/Migrations/CustomOperationSql.cs#snippet_CustomOperationSql)]

> [!TIP]
> Use the `EXEC` function when a statement must be the first or only one in a SQL batch. It might also be needed to work around parser errors in idempotent migration scripts that can occur when referenced columns don't currently exist on a table.
If your migrations need to support multiple database providers, you can use the `MigrationBuilder.ActiveProvider` property. Here's an example supporting both Microsoft SQL Server and PostgreSQL.

```csharp
static MigrationBuilder CreateUser(
this MigrationBuilder migrationBuilder,
string name,
string password)
{
switch (migrationBuilder.ActiveProvider)
{
case "Npgsql.EntityFrameworkCore.PostgreSQL":
return migrationBuilder
.Sql($"CREATE USER {name} WITH PASSWORD '{password}';");

case "Microsoft.EntityFrameworkCore.SqlServer":
return migrationBuilder
.Sql($"CREATE USER {name} WITH PASSWORD = '{password}';");
}

return migrationBuilder;
}
```
[!code-csharp[](../../../../samples/core/Schemas/Migrations/CustomOperationMultiSql.cs#snippet_CustomOperationMultiSql)]

This approach only works if you know every provider where your custom operation will be applied.

## Using a MigrationOperation

To decouple the custom operation from the SQL, you can define your own `MigrationOperation` to represent it. The operation is then passed to the provider so it can determine the appropriate SQL to generate.

```csharp
class CreateUserOperation : MigrationOperation
{
public string Name { get; set; }
public string Password { get; set; }
}
```
[!code-csharp[](../../../../samples/core/Schemas/Migrations/CustomOperation.cs#snippet_CreateUserOperation)]

With this approach, the extension method just needs to add one of these operations to `MigrationBuilder.Operations`.

```csharp
static MigrationBuilder CreateUser(
this MigrationBuilder migrationBuilder,
string name,
string password)
{
migrationBuilder.Operations.Add(
new CreateUserOperation
{
Name = name,
Password = password
});

return migrationBuilder;
}
```
[!code-csharp[](../../../../samples/core/Schemas/Migrations/CustomOperation.cs#snippet_MigrationBuilderExtension)]

This approach requires each provider to know how to generate SQL for this operation in their `IMigrationsSqlGenerator` service. Here is an example overriding the SQL Server's generator to handle the new operation.

```csharp
class MyMigrationsSqlGenerator : SqlServerMigrationsSqlGenerator
{
public MyMigrationsSqlGenerator(
MigrationsSqlGeneratorDependencies dependencies,
IMigrationsAnnotationProvider migrationsAnnotations)
: base(dependencies, migrationsAnnotations)
{
}

protected override void Generate(
MigrationOperation operation,
IModel model,
MigrationCommandListBuilder builder)
{
if (operation is CreateUserOperation createUserOperation)
{
Generate(createUserOperation, builder);
}
else
{
base.Generate(operation, model, builder);
}
}

private void Generate(
CreateUserOperation operation,
MigrationCommandListBuilder builder)
{
var sqlHelper = Dependencies.SqlGenerationHelper;
var stringMapping = Dependencies.TypeMappingSource.FindMapping(typeof(string));

builder
.Append("CREATE USER ")
.Append(sqlHelper.DelimitIdentifier(operation.Name))
.Append(" WITH PASSWORD = ")
.Append(stringMapping.GenerateSqlLiteral(operation.Password))
.AppendLine(sqlHelper.StatementTerminator)
.EndCommand();
}
}
```
[!code-csharp[](../../../../samples/core/Schemas/Migrations/CustomOperation.cs#snippet_MigrationsSqlGenerator)]

Replace the default migrations sql generator service with the updated one.

```csharp
protected override void OnConfiguring(DbContextOptionsBuilder options)
=> options
.UseSqlServer(connectionString)
.ReplaceService<IMigrationsSqlGenerator, MyMigrationsSqlGenerator>();
```
[!code-csharp[](../../../../samples/core/Schemas/Migrations/CustomOperation.cs#snippet_OnConfiguring)]
26 changes: 24 additions & 2 deletions entity-framework/core/miscellaneous/cli/dbcontext-creation.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: Design-time DbContext Creation - EF Core
description: Strategies for creating a design-time DbContext with Entity Framework Core
author: bricelam
ms.date: 09/16/2019
ms.date: 10/27/2020
uid: core/miscellaneous/cli/dbcontext-creation
---
# Design-time DbContext Creation
Expand Down Expand Up @@ -39,7 +39,29 @@ You can also tell the tools how to create your DbContext by implementing the `ID
> This is fixed in EFCore 5.0 and any additional design-time arguments
> are passed into the application through that parameter.
A design-time factory can be especially useful if you need to configure the DbContext differently for design time than at run time, if the `DbContext` constructor takes additional parameters are not registered in DI, if you are not using DI at all, or if for some reason you prefer not to have a `BuildWebHost` method in your ASP.NET Core application's `Main` class.
A design-time factory can be especially useful if you need to configure the DbContext differently for design time than at run time, if the `DbContext` constructor takes additional parameters are not registered in DI, if you are not using DI at all, or if for some reason you prefer not to have a `CreateHostBuilder` method in your ASP.NET Core application's `Main` class.

## Args

Both IDesignTimeDbContextFactory.CreateDbContext and Program.CreateHostBuilder accept command line arguments.

Starting in EF Core 5.0, you can specify these arguments from the tools:

### [.NET Core CLI](#tab/dotnet-core-cli)

```dotnetcli
dotnet ef database update -- --environment Production
```

The `--` token directs `dotnet ef` to treat everything that follows as an argument and not try to parse them as options. Any extra arguments not used by `dotnet ef` are forwarded to the app.

### [Visual Studio](#tab/vs)

```powershell
Update-Database -Args '--environment Production'
```

***

[1]: xref:core/managing-schemas/migrations/index
[2]: xref:core/miscellaneous/configuring-dbcontext
Expand Down
20 changes: 18 additions & 2 deletions entity-framework/core/miscellaneous/cli/dotnet.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: EF Core tools reference (.NET CLI) - EF Core
description: Reference guide for the Entity Framework Core .NET Core CLI tools
author: bricelam
ms.date: 10/13/2020
ms.date: 10/27/2020
uid: core/miscellaneous/cli/dotnet
---

Expand Down Expand Up @@ -93,7 +93,16 @@ Why is a dummy project required? As mentioned earlier, the tools have to execute

### ASP.NET Core environment

To specify the environment for ASP.NET Core projects, set the **ASPNETCORE_ENVIRONMENT** environment variable before running commands.
To specify [the environment](/aspnet/core/fundamentals/environments) for ASP.NET Core projects, set the **ASPNETCORE_ENVIRONMENT** environment variable before running commands.

Starting in EF Core 5.0, additional arguments can also be passed into Program.CreateHostBuilder allowing you to specify the environment on the command-line:

```dotnetcli
dotnet ef database update -- --environment Production
```

> [!TIP]
> The `--` token directs `dotnet ef` to treat everything that follows as an argument and not try to parse them as options. Any extra arguments not used by `dotnet ef` are forwarded to the app.
## Common options

Expand Down Expand Up @@ -206,6 +215,13 @@ The following example scaffolds only selected tables and creates the context in
dotnet ef dbcontext scaffold "Server=(localdb)\mssqllocaldb;Database=Blogging;Trusted_Connection=True;" Microsoft.EntityFrameworkCore.SqlServer -o Models -t Blog -t Post --context-dir Context -c BlogContext --context-namespace New.Namespace
```

The following example reads the connection string from the project's configuration set using the [Secret Manager tool](/aspnet/core/security/app-secrets#secret-manager).

```dotnetcli
dotnet user-secrets set ConnectionStrings.Blogging "Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=Blogging"
dotnet ef dbcontext scaffold Name=ConnectionStrings.Blogging Microsoft.EntityFrameworkCore.SqlServer
```

## dotnet ef dbcontext script

Generates a SQL script from the DbContext. Bypasses any migrations. Added in EF Core 3.0.
Expand Down
28 changes: 20 additions & 8 deletions entity-framework/core/miscellaneous/cli/powershell.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: EF Core tools reference (Package Manager Console) - EF Core
description: Reference guide for the Entity Framework Core Visual Studio Package Manager Console
author: bricelam
ms.date: 10/13/2020
ms.date: 10/27/2020
uid: core/miscellaneous/cli/powershell
---
# Entity Framework Core tools reference - Package Manager Console in Visual Studio
Expand Down Expand Up @@ -84,7 +84,13 @@ Why is a dummy project required? As mentioned earlier, the tools have to execute

### ASP.NET Core environment

To specify the environment for ASP.NET Core projects, set **env:ASPNETCORE_ENVIRONMENT** before running commands.
To specify [the environment](/aspnet/core/fundamentals/environments) for ASP.NET Core projects, set **env:ASPNETCORE_ENVIRONMENT** before running commands.

Starting in EF Core 5.0, additional arguments can also be passed into Program.CreateHostBuilder allowing you to specify the environment on the command-line:

```powershell
Update-Database -Args '--environment Production'
```

## Common parameters

Expand Down Expand Up @@ -197,6 +203,12 @@ Example that scaffolds only selected tables and creates the context in a separat
Scaffold-DbContext "Server=(localdb)\mssqllocaldb;Database=Blogging;Trusted_Connection=True;" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models -Tables "Blog","Post" -ContextDir Context -Context BlogContext -ContextNamespace New.Namespace
```

The following example reads the connection string from the project's configuration possibly set using the [Secret Manager tool](/aspnet/core/security/app-secrets#secret-manager).

```powershell
Scaffold-DbContext "Name=ConnectionStrings.Blogging" Microsoft.EntityFrameworkCore.SqlServer
```

## Script-DbContext

Generates a SQL script from the DbContext. Bypasses any migrations. Added in EF Core 3.0.
Expand Down Expand Up @@ -228,16 +240,16 @@ The [common parameters](#common-parameters) are listed above.
> [!TIP]
> The To, From, and Output parameters support tab-expansion.
The following example creates a script for the InitialCreate migration, using the migration name.
The following example creates a script for the InitialCreate migration (from a database without any migrations), using the migration name.

```powershell
Script-Migration -To InitialCreate
Script-Migration 0 InitialCreate
```

The following example creates a script for all migrations after the InitialCreate migration, using the migration ID.

```powershell
Script-Migration -From 20180904195021_InitialCreate
Script-Migration 20180904195021_InitialCreate
```

## Update-Database
Expand All @@ -257,14 +269,14 @@ The [common parameters](#common-parameters) are listed above.
The following example reverts all migrations.

```powershell
Update-Database -Migration 0
Update-Database 0
```

The following examples update the database to a specified migration. The first uses the migration name and the second uses the migration ID and a specified connection:

```powershell
Update-Database -Migration InitialCreate
Update-Database -Migration 20180904195021_InitialCreate -Connection your_connection_string
Update-Database InitialCreate
Update-Database 20180904195021_InitialCreate -Connection your_connection_string
```

## Additional resources
Expand Down
Loading

0 comments on commit f0f6905

Please sign in to comment.