Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add documentation for MSBuild integration #4870

Merged
merged 1 commit into from
Nov 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions entity-framework/core/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: SamMonoRT
ms.date: 11/15/2021
ms.date: 11/08/2024
uid: core/cli/dotnet
---

Expand Down Expand Up @@ -171,18 +171,27 @@ Lists available `DbContext` types.

The [common options](#common-options) are listed above.

<a name="optimize"></a>

## `dotnet ef dbcontext optimize`

Generates a compiled version of the model used by the `DbContext`.
Generates a compiled version of the model used by the `DbContext` and precompiles queries.

See [Compiled models](xref:core/performance/advanced-performance-topics#compiled-models) for more information.

Options:

| Option | Short | Description |
|:-----------------------------------------|:------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Option | Short | Description |
|:-----------------------------------------------------|:------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| <nobr>`--output-dir <PATH>`</nobr> | `-o` | The directory to put files in. Paths are relative to the project directory. |
| <nobr>`--namespace <NAMESPACE>`</nobr> | `-n` | The namespace to use for all generated classes. Defaults to generated from the root namespace and the output directory plus `CompiledModels`. |
| <nobr>`--suffix <SUFFIX>`</nobr> | | The suffix to attach to the name of all the generated files. E.g. `.g` could be used to indicate that these files contain generated code |
| <nobr>`--no-scaffold`</nobr> | | Don't generate a compiled model. This is used when the compiled model has already been generated. |
| <nobr>`--precompile-queries`</nobr> | | Generate precompiled queries. This is required for NativeAOT compilation if the target project contains any queries |
| <nobr>`--nativeaot`</nobr> | | Generate additional code in the compiled model required for NativeAOT compilation and precompiled queries |

> [!NOTE]
> NativeAOT support and precompiled queries are considered experimental in EF 9 and could change dramatically in the next release.

The [common options](#common-options) are listed above.

Expand Down
49 changes: 49 additions & 0 deletions entity-framework/core/cli/msbuild.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
---
title: EF Core MSBuild tasks - EF Core
description: Reference guide for the Entity Framework Core .NET MSBuild tasks
author: AndriySvyryd
ms.date: 11/08/2024
uid: core/cli/msbuild
---

# Entity Framework Core MSBuild integration

Starting with EF 9, you can use an MSBuild task to generate the compiled model and precompiled queries automatically either when the project is built or when it's published. This is mainly intended to be used with NativeAOT publishing.

> [!WARNING]
> NativeAOT support and the MSBuild integration are experimental features, and are not yet suited for production use.

## Installing the tasks

To get started, install the [Microsoft.EntityFrameworkCore.Tasks](https://www.nuget.org/packages/Microsoft.EntityFrameworkCore.Tasks) NuGet package. For example:

```dotnetcli
dotnet add package Microsoft.EntityFrameworkCore.Tasks
```

> [!NOTE]
> **Every** project that needs to be compiled with generated files should reference the NuGet package, it is not transitive by default.

## Using the tasks

If the project specifies `<PublishAot>true</PublishAot>` then by default the MSBuild task will generate a compiled model and precompiled queries during publishing. Otherwise, you can set the following properties to control the generation behavior:

| MSBuild property | Description |
|--------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| EFOptimizeContext | Set to `true` to enable MSBuild integration. |
| EFScaffoldModelStage | Set to `publish`, `build` or `none` to indicate at which stage the compiled model will be generated. Defaults to `publish`. |
| EFPrecompileQueriesStage | Set to `publish`, `build` or `none` to indicate at which stage the precompiled queries will be generated. Defaults to `publish`. |
| DbContextName | The derived `DbContext` class to use. Class name only or fully qualified with namespaces. If this option is omitted, EF Core will perform generation for all context classes in the project. |
| EFTargetNamespace | The namespace to use for all generated classes. If this option is omitted, EF Core will use `$(RootNamespace)`. |
| EFOutputDir | The folder to put the generated files before the project is compiled. If this option is omitted, EF Core will use `$(IntermediateOutputPath)`. |
| EFNullable | Whether nullable reference types will be used in the generated code. If this option is omitted, EF Core will use `$(Nullable)`. |

## Limitations

* A different startup project cannot be specified when using this approach as it would introduce an inverse build dependency. This means that the context project needs to be autosuficient in terms of configuration, so if your app normally configures the context using a host builder in a different project you'd need to [implement _IDesignTimeDbContextFactory&lt;TContext&gt;_](xref:core/cli/dbcontext-creation#from-a-design-time-factory) in the context project.
* Since the project needs to be compilable before the compiled model is generated this approach doesn't support partial method implementations for customization of the compiled model.
* Currently, this will always generate additional code in the compiled model that's required for NativeAOT. If you are not planning to enable NativeAOT then [generate the compiled model using the CLI tools](xref:core/cli/dotnet#optimize).

## Additional resources

* [Compiled models](xref:core/performance/advanced-performance-topics#compiled-models)
7 changes: 5 additions & 2 deletions entity-framework/core/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: SamMonoRT
ms.date: 11/15/2021
ms.date: 11/08/2024
uid: core/cli/powershell
---
# Entity Framework Core tools reference - Package Manager Console in Visual Studio
Expand Down Expand Up @@ -185,6 +185,9 @@ Parameters:

The [common parameters](#common-parameters) are listed above.

> [!NOTE]
> The PMC tools currently don't support generating code required for NativeAOT compilation and precompiled queries.

The following example uses the defaults and works if there is only one `DbContext` in the project:

```powershell
Expand Down Expand Up @@ -246,7 +249,7 @@ 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).
The following example [reads the connection string using Configuration](xref:core/miscellaneous/connection-strings#aspnet-core).

```powershell
Scaffold-DbContext "Name=ConnectionStrings:Blogging" Microsoft.EntityFrameworkCore.SqlServer
Expand Down
4 changes: 2 additions & 2 deletions entity-framework/core/dbcontext-configuration/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,13 @@ ASP.NET Core applications are [configured using dependency injection](/aspnet/co
services.AddControllers();

services.AddDbContext<ApplicationDbContext>(
options => options.UseSqlServer("name=ConnectionStrings:DefaultConnection"));
options => options.UseSqlServer("name=DefaultConnection"));
}
-->

[!code-csharp[snippet_1](../../../samples/core/Miscellaneous/ConfiguringDbContext/WebApp9/Program9.cs?name=snippet_1)]

The preceding code registers `ApplicationDbContext`, a subclass of `DbContext`, as a scoped service in the ASP.NET Core app service provider. The service provider is also known as the dependency injection container. The context is configured to use the SQL Server database provider and reads the connection string from ASP.NET Core configuration.
The preceding code registers `ApplicationDbContext`, a subclass of `DbContext`, as a scoped service in the ASP.NET Core app service provider. The service provider is also known as the dependency injection container. The context is configured to use the SQL Server database provider and reads the connection string from [ASP.NET Core configuration](xref:core/miscellaneous/connection-strings#aspnet-core).

The `ApplicationDbContext` class must expose a public constructor with a `DbContextOptions<ApplicationDbContext>` parameter. This is how context configuration from `AddDbContext` is passed to the `DbContext`. For example:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: Applying Migrations - EF Core
description: Strategies for applying schema migrations to production and development databases using Entity Framework Core
author: SamMonoRT
ms.date: 11/02/2021
ms.date: 10/29/2024
uid: core/managing-schemas/migrations/applying
---
# Applying Migrations
Expand Down Expand Up @@ -117,9 +117,6 @@ The EF command-line tools can be used to apply migrations to a database. While p
* The SQL commands are applied directly by the tool, without giving the developer a chance 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 and requires the project's source code.

> [!NOTE]
> Each migration is applied in its own transaction. See [GitHub issue #22616](https://github.com/dotnet/efcore/issues/22616) for a discussion of possible future enhancements in this area.

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

The following updates your database to the latest migration:
Expand Down
65 changes: 3 additions & 62 deletions entity-framework/core/managing-schemas/scaffolding/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ How the connection string is quoted and escaped depends on the shell that is use

The following example scaffolds entity types and a `DbContext` from the `Chinook` database located on the machine's SQL Server LocalDB instance, making use of the `Microsoft.EntityFrameworkCore.SqlServer` database provider.

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

```dotnetcli
dotnet ef dbcontext scaffold "Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=Chinook" Microsoft.EntityFrameworkCore.SqlServer
Expand All @@ -49,67 +49,8 @@ Scaffold-DbContext 'Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=Chinook'

***

#### User secrets for connection strings

If you have a .NET application that uses the hosting model and configuration system, such as an ASP.NET Core project, then you can use the `Name=<connection-string>` syntax to read the connection string from configuration.

For example, consider an ASP.NET Core application with the following configuration file:

```json
{
"ConnectionStrings": {
"Chinook": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=Chinook"
}
}
```

This connection string in the config file can be used to scaffold from a database using:

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

```dotnetcli
dotnet ef dbcontext scaffold "Name=ConnectionStrings:Chinook" Microsoft.EntityFrameworkCore.SqlServer
```

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

```powershell
Scaffold-DbContext 'Name=ConnectionStrings:Chinook' Microsoft.EntityFrameworkCore.SqlServer
```

***

However, storing connection strings in configuration files is not a good idea, since it is too easy to accidentally expose them, for example, by pushing to source control. Instead, connection strings should be stored in a secure way, such as using [Azure Key Vault](/azure/key-vault/keys/quick-create-net) or, when working locally, the [Secret Manager tool](/aspnet/core/security/app-secrets#secret-manager), aka "User Secrets".

For example, to use the User Secrets, first remove the connection string from your ASP.NET Core configuration file. Next, initialize User Secrets by executing the following command in the same directory as the ASP.NET Core project:

```dotnetcli
dotnet user-secrets init
```

This command sets up storage on your computer separate from your source code and adds a key for this storage to the project.

Next, store the connection string in user secrets. For example:

```dotnetcli
dotnet user-secrets set ConnectionStrings:Chinook "Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=Chinook"
```

Now the same command that previous used the named connection string from the config file will instead use the connection string stored in User Secrets. For example:

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

```dotnetcli
dotnet ef dbcontext scaffold "Name=ConnectionStrings:Chinook" Microsoft.EntityFrameworkCore.SqlServer
```

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

```powershell
Scaffold-DbContext 'Name=ConnectionStrings:Chinook' Microsoft.EntityFrameworkCore.SqlServer
```

***
> [!TIP]
> You can [use Configuration to store and retrieve the connection string](xref:core/miscellaneous/connection-strings#aspnet-core)

#### Connection strings in the scaffolded code

Expand Down
17 changes: 17 additions & 0 deletions entity-framework/core/miscellaneous/connection-strings.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ The ASP.NET Core configuration can store connection strings with various provide

* In the `appsettings.Development.json` or `appsettings.json` file.
* In an environment variable
* Using [Azure Key Vault](/azure/key-vault/keys/quick-create-net)
* Using the [Secret Manager tool](/aspnet/core/security/app-secrets#secret-manager)

> [!WARNING]
Expand All @@ -30,10 +31,26 @@ For example, the [Secret Manager tool](/aspnet/core/security/app-secrets#secret-
See the [Configuration section of the ASP.NET Core documentation](/aspnet/core/fundamentals/configuration) for more information.

```dotnetcli
dotnet user-secrets init
dotnet user-secrets set ConnectionStrings:YourDatabaseAlias "Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=YourDatabase"
```

Then, in scaffolding, use a connection string that consists of `Name=<database-alias>`.

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

```dotnetcli
dotnet ef dbcontext scaffold Name=ConnectionStrings:YourDatabaseAlias Microsoft.EntityFrameworkCore.SqlServer
```

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

```powershell
Scaffold-DbContext 'Name=ConnectionStrings:YourDatabaseAlias' Microsoft.EntityFrameworkCore.SqlServer
```

***

[!INCLUDE [managed-identities-test-non-production](~/core/includes/managed-identities-test-non-production.md)]

The following example shows the connection string stored in `appsettings.json`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,15 @@ C# interceptors are currently an experimental feature, and require a special opt
</PropertyGroup>
```

Finally, the [`Microsoft.EntityFrameworkCore.Tasks`](https://www.nuget.org/packages/Microsoft.EntityFrameworkCore.Tasks) package contains MSBuild integration that will perform the query precompilation (and generate the required compiled model) when you publish your application:
Finally, the [`Microsoft.EntityFrameworkCore.Tasks`](https://www.nuget.org/packages/Microsoft.EntityFrameworkCore.Tasks) package contains [MSBuild integration](xref:core/cli/msbuild) that will perform the query precompilation (and generate the required compiled model) when you publish your application:

```xml
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="..." />
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Tasks" Version="9.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
```

You're now ready to publish your EF NativeAOT application:
Expand All @@ -50,7 +55,7 @@ You're now ready to publish your EF NativeAOT application:
dotnet publish -r linux-arm64 -c Release
```

This shows publishing a NativeAOT publishing for Linux running on ARM64; [consult this catalog](/dotnet/core/rid-catalog) to find your runtime identifier. If you'd like to generate the interceptors without publishing - for example to examine the generated sources - you can do so via the `net ef dbcontext optimize --precompile-queries --nativeaot` command.
This shows publishing a NativeAOT publishing for Linux running on ARM64; [consult this catalog](/dotnet/core/rid-catalog) to find your runtime identifier. If you'd like to generate the interceptors without publishing - for example to examine the generated sources - you can do so via the `dotnet ef dbcontext optimize --precompile-queries --nativeaot` command.

Due to the way C# interceptors work, any change in the application source invalidates them and requires repeating the above process. As a result, interceptor generation and actual publishing aren't expected to happen in the inner loop, as the developer is working on code; instead, both `dotnet ef dbcontext optimize` and `dotnet publish` can be executed in a publishing/deployment workflow, in a CI/CD system.

Expand Down
Loading
Loading