diff --git a/docs/database/azure-sql-entity-framework-integration.md b/docs/database/azure-sql-entity-framework-integration.md new file mode 100644 index 0000000000..d51ef3311b --- /dev/null +++ b/docs/database/azure-sql-entity-framework-integration.md @@ -0,0 +1,28 @@ +--- +title: .NET Aspire Azure SQL Entity Framework Core integration +description: Learn how to use the .NET Aspire Azure SQL integration with Entity Framework Core, which includes both hosting and client integrations. +ms.date: 04/30/2025 +uid: database/azure-sql-entity-framework-integration +--- + +# .NET Aspire Azure SQL Entity Framework Core integration + +[!INCLUDE [includes-hosting-and-client](../includes/includes-hosting-and-client.md)] + +[Azure SQL](https://azure.microsoft.com/products/azure-sql) is a family of relational database management systems that run in the Azure cloud. The database systems are Platform-as-a-Service (PaaS) products that enable database administrators to implement highly scalable and available databases without maintaining complex infrastructures themselves. The .NET Aspire Azure SQL Server Hosting integration provides methods to create a new Azure Database server and databases from code in your .NET Aspire app host project. In a consuming project, you can use the .NET Aspire SQL Server Entity Framework Core client integration as you would for any other SQL Server instance. + +## Hosting integration + +[!INCLUDE [azure-sql-hosting](includes/azure-sql-hosting.md)] + +## Client integration + +[!INCLUDE [sql-server-ef-client](includes/sql-server-ef-client.md)] + +## See also + +- [Azure SQL Database](/azure/azure-sql/database) +- [.NET Aspire database containers sample](/samples/dotnet/aspire-samples/aspire-database-containers/) +- [.NET Aspire integrations](../fundamentals/integrations-overview.md) +- [.NET Aspire GitHub repo](https://github.com/dotnet/aspire) +- [Azure SQL & SQL Server Aspire Samples](https://github.com/Azure-Samples/azure-sql-db-aspire) diff --git a/docs/database/azure-sql-integration.md b/docs/database/azure-sql-integration.md new file mode 100644 index 0000000000..7b7e0a41f0 --- /dev/null +++ b/docs/database/azure-sql-integration.md @@ -0,0 +1,28 @@ +--- +title: .NET Aspire Azure SQL integration +description: Learn how to use the .NET Aspire Azure SQL integration, which includes both hosting and client integrations. +ms.date: 04/30/2025 +uid: database/azure-sql-integration +--- + +# .NET Aspire Azure SQL integration + +[!INCLUDE [includes-hosting-and-client](../includes/includes-hosting-and-client.md)] + +[Azure SQL](https://azure.microsoft.com/products/azure-sql) is a family of relational database management systems that run in the Azure cloud. The database systems are Platform-as-a-Service (PaaS) products that enable database administrators to implement highly scalable and available databases without maintaining complex infrastructures themselves. The .NET Aspire Azure SQL Server Hosting integration provides methods to create a new Azure Database server and databases from code in your .NET Aspire app host project. In a consuming project, you can use the .NET Aspire SQL Server client integration as you would for any other SQL Server instance. + +## Hosting integration + +[!INCLUDE [azure-sql-hosting](includes/azure-sql-hosting.md)] + +## Client integration + +[!INCLUDE [sql-server-client](includes/sql-server-client.md)] + +## See also + +- [Azure SQL Database](/azure/azure-sql/database) +- [.NET Aspire database containers sample](/samples/dotnet/aspire-samples/aspire-database-containers/) +- [.NET Aspire integrations](../fundamentals/integrations-overview.md) +- [.NET Aspire GitHub repo](https://github.com/dotnet/aspire) +- [Azure SQL & SQL Server Aspire Samples](https://github.com/Azure-Samples/azure-sql-db-aspire) diff --git a/docs/database/includes/azure-sql-hosting.md b/docs/database/includes/azure-sql-hosting.md new file mode 100644 index 0000000000..23652b4ae7 --- /dev/null +++ b/docs/database/includes/azure-sql-hosting.md @@ -0,0 +1,96 @@ +--- +ms.topic: include +--- + +The Azure SQL hosting integration models the Azure SQL server as the type and the database as the type. To access these types and APIs, add the [📦 Aspire.Hosting.Azure.Sql](https://www.nuget.org/packages/Aspire.Hosting.Azure.Sql) NuGet package in the [app host](xref:dotnet/aspire/app-host) project. + +### [.NET CLI](#tab/dotnet-cli) + +```dotnetcli +dotnet add package Aspire.Hosting.Azure.Sql +``` + +### [PackageReference](#tab/package-reference) + +```xml + +``` + +--- + +For more information, see [dotnet add package](/dotnet/core/tools/dotnet-add-package) or [Manage package dependencies in .NET applications](/dotnet/core/tools/dependencies). + +The Azure SQL hosting integration takes a dependency on the [📦 Aspire.Hosting.SqlServer](https://www.nuget.org/packages/Aspire.Hosting.SqlServer/) NuGet package, extending it to support Azure. Everything that you can do with the [.NET Aspire SQL Server integration](../sql-server-integration.md) and [.NET Aspire SQL Server Entity Framework Core integration](../sql-server-entity-framework-integration.md) you can also do with this integration. + +### Add Azure SQL server resource and database resource + +In your app host project, call to add and return an Azure SQL server resource builder. Chain a call to the returned resource builder to , to add an Azure SQL database resource: + +```csharp +var azureSql = builder.AddAzureSqlServer("azuresql") + .AddDatabase("database"); + +var myService = builder.AddProject() + .WithReference(azureSql); +``` + +The preceding call to `AddAzureSqlServer` configures the Azure SQL server resource to be deployed as an [Azure SQL Database server](/azure/azure-sql/database/sql-database-paas-overview). + +> [!IMPORTANT] +> By default, `AddAzureSqlServer` configures [Microsoft Entra ID](/azure/azure-sql/database/authentication-aad-overview) authentication. This requires changes to applications that need to connect to these resources. For more information, see [Client integration](#client-integration). + +> [!TIP] +> When you call , it implicitly calls — which adds support for generating Azure resources dynamically during app startup. The app must configure the appropriate subscription and location. For more information, see [Local provisioning: Configuration](../../azure/local-provisioning.md#configuration). + +### Connect to an existing Azure SQL server + +You might have an existing Azure SQL database that you want to connect to. Instead of representing a new Azure SQL server resource, you can add a connection string to the app host. To add a connection to an existing Azure SQL server, call the method: + +```csharp +var builder = DistributedApplication.CreateBuilder(args); + +var azureSql = builder.AddConnectionString("database"); + +builder.AddProject("web") + .WithReference(azureSql); + +// After adding all resources, run the app... +``` + +[!INCLUDE [connection-strings-alert](../../includes/connection-strings-alert.md)] + +The connection string is configured in the app host's configuration, typically under [User Secrets](/aspnet/core/security/app-secrets), under the `ConnectionStrings` section. The app host injects this connection string as an environment variable into all dependent resources, for example: + +```json +{ + "ConnectionStrings": { + "database": "Server=tcp:.database.windows.net,1433;Initial Catalog=;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;User ID=;" + } +} +``` + +The dependent resource can access the injected connection string by calling the method, and passing the connection name as the parameter, in this case `"database"`. The `GetConnectionString` API is shorthand for `IConfiguration.GetSection("ConnectionStrings")[name]`. + +### Run Azure SQL server resource as a container + +The Azure SQL Server hosting integration supports running the Azure SQL server as a local container. This is beneficial for situations where you want to run the Azure SQL server locally for development and testing purposes, avoiding the need to provision an Azure resource or connect to an existing Azure SQL server. + +To run the Azure SQL server as a container, call the method: + +```csharp +var builder = DistributedApplication.CreateBuilder(args); + +var azureSql = builder.AddAzureSqlServer("azuresql") + .RunAsContainer(); + +var azureSqlData = postgres.AddDatabase("database"); + +var exampleProject = builder.AddProject() + .WithReference(azureSqlData); +``` + +The preceding code configures an Azure SQL Database resource to run locally in a container. + +> [!TIP] +> The `RunAsContainer` method is useful for local development and testing. The API exposes an optional delegate that enables you to customize the underlying configuration. For example, you can add a data volume or data bind mount. For more information, see the [.NET Aspire SQL Server hosting integration](../sql-server-integration.md#add-sql-server-resource-with-data-volume) section. diff --git a/docs/database/includes/sql-server-client.md b/docs/database/includes/sql-server-client.md new file mode 100644 index 0000000000..5d34fbb74d --- /dev/null +++ b/docs/database/includes/sql-server-client.md @@ -0,0 +1,166 @@ +--- +ms.topic: include +--- + +To get started with the .NET Aspire SQL Server client integration, install the [📦 Aspire.Microsoft.Data.SqlClient](https://www.nuget.org/packages/Aspire.Microsoft.Data.SqlClient) NuGet package in the client-consuming project, that is, the project for the application that uses the SQL Server client. The SQL Server client integration registers a instance that you can use to interact with SQL Server. + +### [.NET CLI](#tab/dotnet-cli) + +```dotnetcli +dotnet add package Aspire.Microsoft.Data.SqlClient +``` + +### [PackageReference](#tab/package-reference) + +```xml + +``` + +--- + +### Add SQL Server client + +In the _:::no-loc text="Program.cs":::_ file of your client-consuming project, call the extension method on any to register a `SqlConnection` for use via the dependency injection container. The method takes a connection name parameter. + +```csharp +builder.AddSqlServerClient(connectionName: "database"); +``` + +> [!TIP] +> The `connectionName` parameter must match the name used when adding the SQL Server database resource in the app host project. In other words, when you call `AddDatabase` and provide a name of `database` that same name should be used when calling `AddSqlServerClient`. For more information, see [Add SQL Server resource and database resource](../sql-server-integration.md#add-sql-server-resource-and-database-resource). + +You can then retrieve the instance using dependency injection. For example, to retrieve the connection from an example service: + +```csharp +public class ExampleService(SqlConnection connection) +{ + // Use connection... +} +``` + +For more information on dependency injection, see [.NET dependency injection](/dotnet/core/extensions/dependency-injection). + +### Add keyed SQL Server client + +There might be situations where you want to register multiple `SqlConnection` instances with different connection names. To register keyed SQL Server clients, call the method: + +```csharp +builder.AddKeyedSqlServerClient(name: "mainDb"); +builder.AddKeyedSqlServerClient(name: "loggingDb"); +``` + +> [!IMPORTANT] +> When using keyed services, it's expected that your SQL Server resource configured two named databases, one for the `mainDb` and one for the `loggingDb`. + +Then you can retrieve the `SqlConnection` instances using dependency injection. For example, to retrieve the connection from an example service: + +```csharp +public class ExampleService( + [FromKeyedServices("mainDb")] SqlConnection mainDbConnection, + [FromKeyedServices("loggingDb")] SqlConnection loggingDbConnection) +{ + // Use connections... +} +``` + +For more information on keyed services, see [.NET dependency injection: Keyed services](/dotnet/core/extensions/dependency-injection#keyed-services). + +### Configuration + +The .NET Aspire SQL Server integration provides multiple options to configure the connection based on the requirements and conventions of your project. + +#### Use a connection string + +When using a connection string from the `ConnectionStrings` configuration section, you can provide the name of the connection string when calling the method: + +```csharp +builder.AddSqlServerClient(connectionName: "sql"); +``` + +Then the connection string is retrieved from the `ConnectionStrings` configuration section: + +```json +{ + "ConnectionStrings": { + "database": "Data Source=myserver;Initial Catalog=master" + } +} +``` + +For more information on how to format this connection string, see the [ConnectionString](/dotnet/api/system.data.sqlclient.sqlconnection.connectionstring#remarks). + +#### Use configuration providers + +The .NET Aspire SQL Server integration supports . It loads the from configuration by using the `Aspire:Microsoft:Data:SqlClient` key. The following snippet is an example of a _:::no-loc text="appsettings.json":::_ file that configures some of the options: + +```json +{ + "Aspire": { + "Microsoft": { + "Data": { + "SqlClient": { + "ConnectionString": "YOUR_CONNECTIONSTRING", + "DisableHealthChecks": false, + "DisableMetrics": true + } + } + } + } +} +``` + +For the complete SQL Server client integration JSON schema, see [Aspire.Microsoft.Data.SqlClient/ConfigurationSchema.json](https://github.com/dotnet/aspire/blob/v8.2.2/src/Components/Aspire.Microsoft.Data.SqlClient/ConfigurationSchema.json). + +#### Use inline delegates + +Also you can pass the `Action configureSettings` delegate to set up some or all the options inline, for example to disable health checks from code: + +```csharp +builder.AddSqlServerClient( + "database", + static settings => settings.DisableHealthChecks = true); +``` + +### Client integration health checks + +By default, .NET Aspire integrations enable [health checks](../../fundamentals/health-checks.md) for all services. For more information, see [.NET Aspire integrations overview](../../fundamentals/integrations-overview.md). + +The .NET Aspire SQL Server integration: + +- Adds the health check when is `false`, which attempts to connect to the SQL Server. +- Integrates with the `/health` HTTP endpoint, which specifies all registered health checks must pass for app to be considered ready to accept traffic. + +[!INCLUDE [integration-observability-and-telemetry](../../includes/integration-observability-and-telemetry.md)] + +#### Logging + +The .NET Aspire SQL Server integration currently doesn't enable logging by default due to limitations of the . + +#### Tracing + +The .NET Aspire SQL Server integration emits the following tracing activities using OpenTelemetry: + +- `OpenTelemetry.Instrumentation.SqlClient` + +#### Metrics + +The .NET Aspire SQL Server integration will emit the following metrics using OpenTelemetry: + +- Microsoft.Data.SqlClient.EventSource + - `active-hard-connections` + - `hard-connects` + - `hard-disconnects` + - `active-soft-connects` + - `soft-connects` + - `soft-disconnects` + - `number-of-non-pooled-connections` + - `number-of-pooled-connections` + - `number-of-active-connection-pool-groups` + - `number-of-inactive-connection-pool-groups` + - `number-of-active-connection-pools` + - `number-of-inactive-connection-pools` + - `number-of-active-connections` + - `number-of-free-connections` + - `number-of-stasis-connections` + - `number-of-reclaimed-connections` diff --git a/docs/database/includes/sql-server-ef-client.md b/docs/database/includes/sql-server-ef-client.md new file mode 100644 index 0000000000..49d0b522d5 --- /dev/null +++ b/docs/database/includes/sql-server-ef-client.md @@ -0,0 +1,229 @@ +--- +ms.topic: include +--- + +To get started with the .NET Aspire SQL Server Entity Framework Core integration, install the [📦 Aspire.Microsoft.EntityFrameworkCore.SqlServer](https://www.nuget.org/packages/Aspire.Microsoft.EntityFrameworkCore.SqlServer) NuGet package in the client-consuming project, that is, the project for the application that uses the SQL Server Entity Framework Core client. + +### [.NET CLI](#tab/dotnet-cli) + +```dotnetcli +dotnet add package Aspire.Microsoft.EntityFrameworkCore.SqlServer +``` + +### [PackageReference](#tab/package-reference) + +```xml + +``` + +--- + +For more information, see [dotnet add package](/dotnet/core/tools/dotnet-add-package) or [Manage package dependencies in .NET applications](/dotnet/core/tools/dependencies). + +### Add SQL Server database context + +In the :::no-loc text="Program.cs"::: file of your client-consuming project, call the extension method on any to register a for use via the dependency injection container. The method takes a connection name parameter. + +```csharp +builder.AddSqlServerDbContext(connectionName: "database"); +``` + +> [!TIP] +> The `connectionName` parameter must match the name used when adding the SQL Server database resource in the app host project. In other words, when you call `AddDatabase` and provide a name of `database` that same name should be used when calling `AddSqlServerDbContext`. For more information, see [Add SQL Server resource and database resource](../sql-server-integration.md#add-sql-server-resource-and-database-resource). + +To retrieve `ExampleDbContext` object from a service: + +```csharp +public class ExampleService(ExampleDbContext context) +{ + // Use context... +} +``` + +For more information on dependency injection, see [.NET dependency injection](/dotnet/core/extensions/dependency-injection). + +### Enrich a SQL Server database context + +You may prefer to use the standard Entity Framework method to obtain a database context and add it to the dependency injection container: + +```csharp +builder.Services.AddDbContext(options => + options.UseSqlServer(builder.Configuration.GetConnectionString("database") + ?? throw new InvalidOperationException("Connection string 'database' not found."))); +``` + +> [!NOTE] +> The connection string name that you pass to the method must match the name used when adding the SQL server resource in the app host project. For more information, see [Add SQL Server resource and database resource](../sql-server-integration.md#add-sql-server-resource-and-database-resource). + +You have more flexibility when you create the database context in this way, for example: + +- You can reuse existing configuration code for the database context without rewriting it for .NET Aspire. +- You can use Entity Framework Core interceptors to modify database operations. +- You can choose not to use Entity Framework Core context pooling, which may perform better in some circumstances. + +If you use this method, you can enhance the database context with .NET Aspire-style retries, health checks, logging, and telemetry features by calling the method: + +```csharp +builder.EnrichSqlServerDbContext( + configureSettings: settings => + { + settings.DisableRetry = false; + settings.CommandTimeout = 30; // seconds + }); +``` + +The `settings` parameter is an instance of the class. + +### Configuration + +The .NET Aspire SQL Server Entity Framework Core integration provides multiple configuration approaches and options to meet the requirements and conventions of your project. + +#### Use connection string + +When using a connection string from the `ConnectionStrings` configuration section, you provide the name of the connection string when calling `builder.AddSqlServerDbContext()`: + +```csharp +builder.AddSqlServerDbContext("sql"); +``` + +The connection string is retrieved from the `ConnectionStrings` configuration section: + +```json +{ + "ConnectionStrings": { + "sql": "Data Source=myserver;Initial Catalog=master" + } +} +``` + +The `EnrichSqlServerDbContext` won't make use of the `ConnectionStrings` configuration section since it expects a `DbContext` to be registered at the point it's called. + +For more information, see the [ConnectionString](/dotnet/api/system.data.sqlclient.sqlconnection.connectionstring#remarks). + +#### Use configuration providers + +The .NET Aspire SQL Server Entity Framework Core integration supports . It loads the from configuration files such as _:::no-loc text="appsettings.json":::_ by using the `Aspire:Microsoft:EntityFrameworkCore:SqlServer` key. If you have set up your configurations in the `Aspire:Microsoft:EntityFrameworkCore:SqlServer` section you can just call the method without passing any parameter. + +The following is an example of an _:::no-loc text="appsettings.json":::_ file that configures some of the available options: + +```json +{ + "Aspire": { + "Microsoft": { + "EntityFrameworkCore": { + "SqlServer": { + "ConnectionString": "YOUR_CONNECTIONSTRING", + "DbContextPooling": true, + "DisableHealthChecks": true, + "DisableTracing": true, + "DisableMetrics": false + } + } + } + } +} +``` + +#### Use inline configurations + +You can also pass the `Action` delegate to set up some or all the options inline, for example to turn off the metrics: + +```csharp +builder.AddSqlServerDbContext( + "sql", + static settings => + settings.DisableMetrics = true); +``` + +#### Configure multiple DbContext connections + +If you want to register more than one `DbContext` with different configuration, you can use `$"Aspire.Microsoft.EntityFrameworkCore.SqlServer:{typeof(TContext).Name}"` configuration section name. The json configuration would look like: + +```json +{ + "Aspire": { + "Microsoft": { + "EntityFrameworkCore": { + "SqlServer": { + "ConnectionString": "YOUR_CONNECTIONSTRING", + "DbContextPooling": true, + "DisableHealthChecks": true, + "DisableTracing": true, + "DisableMetrics": false, + "AnotherDbContext": { + "ConnectionString": "AnotherDbContext_CONNECTIONSTRING", + "DisableTracing": false + } + } + } + } + } +} +``` + +Then calling the `AddSqlServerDbContext` method with `AnotherDbContext` type parameter would load the settings from `Aspire:Microsoft:EntityFrameworkCore:SqlServer:AnotherDbContext` section. + +```csharp +builder.AddSqlServerDbContext("another-sql"); +``` + +#### Configuration options + +Here are the configurable options with corresponding default values: + +| Name | Description | +|-----------------------|----------------------------------------------------------------------------------------------------------------------| +| `ConnectionString` | The connection string of the SQL Server database to connect to. | +| `DbContextPooling` | A boolean value that indicates whether the db context will be pooled or explicitly created every time it's requested | +| `MaxRetryCount` | The maximum number of retry attempts. Default value is 6, set it to 0 to disable the retry mechanism. | +| `DisableHealthChecks` | A boolean value that indicates whether the database health check is disabled or not. | +| `DisableTracing` | A boolean value that indicates whether the OpenTelemetry tracing is disabled or not. | +| `DisableMetrics` | A boolean value that indicates whether the OpenTelemetry metrics are disabled or not. | +| `Timeout` | The time in seconds to wait for the command to execute. | + +[!INCLUDE [client-integration-health-checks](../../includes/client-integration-health-checks.md)] + +By default, the .NET Aspire Sql Server Entity Framework Core integration handles the following: + +- Adds the [`DbContextHealthCheck`](https://github.com/Xabaril/AspNetCore.Diagnostics.HealthChecks/blob/master/src/HealthChecks.NpgSql/NpgSqlHealthCheck.cs), which calls EF Core's method. The name of the health check is the name of the `TContext` type. +- Integrates with the `/health` HTTP endpoint, which specifies all registered health checks must pass for app to be considered ready to accept traffic + +[!INCLUDE [integration-observability-and-telemetry](../../includes/integration-observability-and-telemetry.md)] + +#### Logging + +The .NET Aspire SQL Server Entity Framework Core integration uses the following Log categories: + +- `Microsoft.EntityFrameworkCore.ChangeTracking` +- `Microsoft.EntityFrameworkCore.Database.Command` +- `Microsoft.EntityFrameworkCore.Database.Connection` +- `Microsoft.EntityFrameworkCore.Database.Transaction` +- `Microsoft.EntityFrameworkCore.Infrastructure` +- `Microsoft.EntityFrameworkCore.Migrations` +- `Microsoft.EntityFrameworkCore.Model` +- `Microsoft.EntityFrameworkCore.Model.Validation` +- `Microsoft.EntityFrameworkCore.Query` +- `Microsoft.EntityFrameworkCore.Update` + +#### Tracing + +The .NET Aspire SQL Server Entity Framework Core integration will emit the following Tracing activities using OpenTelemetry: + +- "OpenTelemetry.Instrumentation.EntityFrameworkCore" + +#### Metrics + +The .NET Aspire SQL Server Entity Framework Core integration will emit the following metrics using OpenTelemetry: + +- Microsoft.EntityFrameworkCore: + - `ec_Microsoft_EntityFrameworkCore_active_db_contexts` + - `ec_Microsoft_EntityFrameworkCore_total_queries` + - `ec_Microsoft_EntityFrameworkCore_queries_per_second` + - `ec_Microsoft_EntityFrameworkCore_total_save_changes` + - `ec_Microsoft_EntityFrameworkCore_save_changes_per_second` + - `ec_Microsoft_EntityFrameworkCore_compiled_query_cache_hit_rate` + - `ec_Microsoft_Entity_total_execution_strategy_operation_failures` + - `ec_Microsoft_E_execution_strategy_operation_failures_per_second` + - `ec_Microsoft_EntityFramew_total_optimistic_concurrency_failures` + - `ec_Microsoft_EntityF_optimistic_concurrency_failures_per_second` diff --git a/docs/database/sql-server-entity-framework-integration.md b/docs/database/sql-server-entity-framework-integration.md index 865593502a..9673c736c8 100644 --- a/docs/database/sql-server-entity-framework-integration.md +++ b/docs/database/sql-server-entity-framework-integration.md @@ -23,231 +23,7 @@ The hosting integration relies on the [📦 AspNetCore.HealthChecks.SqlServer](h ## Client integration -To get started with the .NET Aspire SQL Server Entity Framework Core integration, install the [📦 Aspire.Microsoft.EntityFrameworkCore.SqlServer](https://www.nuget.org/packages/Aspire.Microsoft.EntityFrameworkCore.SqlServer) NuGet package in the client-consuming project, that is, the project for the application that uses the SQL Server Entity Framework Core client. - -### [.NET CLI](#tab/dotnet-cli) - -```dotnetcli -dotnet add package Aspire.Microsoft.EntityFrameworkCore.SqlServer -``` - -### [PackageReference](#tab/package-reference) - -```xml - -``` - ---- - -For more information, see [dotnet add package](/dotnet/core/tools/dotnet-add-package) or [Manage package dependencies in .NET applications](/dotnet/core/tools/dependencies). - -### Add SQL Server database context - -In the :::no-loc text="Program.cs"::: file of your client-consuming project, call the extension method on any to register a for use via the dependency injection container. The method takes a connection name parameter. - -```csharp -builder.AddSqlServerDbContext(connectionName: "database"); -``` - -> [!TIP] -> The `connectionName` parameter must match the name used when adding the SQL Server database resource in the app host project. In other words, when you call `AddDatabase` and provide a name of `database` that same name should be used when calling `AddSqlServerDbContext`. For more information, see [Add SQL Server resource and database resource](#add-sql-server-resource-and-database-resource). - -To retrieve `ExampleDbContext` object from a service: - -```csharp -public class ExampleService(ExampleDbContext context) -{ - // Use context... -} -``` - -For more information on dependency injection, see [.NET dependency injection](/dotnet/core/extensions/dependency-injection). - -### Enrich a SQL Server database context - -You may prefer to use the standard Entity Framework method to obtain a database context and add it to the dependency injection container: - -```csharp -builder.Services.AddDbContext(options => - options.UseSqlServer(builder.Configuration.GetConnectionString("database") - ?? throw new InvalidOperationException("Connection string 'database' not found."))); -``` - -> [!NOTE] -> The connection string name that you pass to the method must match the name used when adding the SQL server resource in the app host project. For more information, see [Add SQL Server resource and database resource](#add-sql-server-resource-and-database-resource). - -You have more flexibility when you create the database context in this way, for example: - -- You can reuse existing configuration code for the database context without rewriting it for .NET Aspire. -- You can use Entity Framework Core interceptors to modify database operations. -- You can choose not to use Entity Framework Core context pooling, which may perform better in some circumstances. - -If you use this method, you can enhance the database context with .NET Aspire-style retries, health checks, logging, and telemetry features by calling the method: - -```csharp -builder.EnrichSqlServerDbContext( - configureSettings: settings => - { - settings.DisableRetry = false; - settings.CommandTimeout = 30; // seconds - }); -``` - -The `settings` parameter is an instance of the class. - -### Configuration - -The .NET Aspire SQL Server Entity Framework Core integration provides multiple configuration approaches and options to meet the requirements and conventions of your project. - -#### Use connection string - -When using a connection string from the `ConnectionStrings` configuration section, you provide the name of the connection string when calling `builder.AddSqlServerDbContext()`: - -```csharp -builder.AddSqlServerDbContext("sql"); -``` - -The connection string is retrieved from the `ConnectionStrings` configuration section: - -```json -{ - "ConnectionStrings": { - "sql": "Data Source=myserver;Initial Catalog=master" - } -} -``` - -The `EnrichSqlServerDbContext` won't make use of the `ConnectionStrings` configuration section since it expects a `DbContext` to be registered at the point it's called. - -For more information, see the [ConnectionString](/dotnet/api/system.data.sqlclient.sqlconnection.connectionstring#remarks). - -#### Use configuration providers - -The .NET Aspire SQL Server Entity Framework Core integration supports . It loads the from configuration files such as _:::no-loc text="appsettings.json":::_ by using the `Aspire:Microsoft:EntityFrameworkCore:SqlServer` key. If you have set up your configurations in the `Aspire:Microsoft:EntityFrameworkCore:SqlServer` section you can just call the method without passing any parameter. - -The following is an example of an _:::no-loc text="appsettings.json":::_ file that configures some of the available options: - -```json -{ - "Aspire": { - "Microsoft": { - "EntityFrameworkCore": { - "SqlServer": { - "ConnectionString": "YOUR_CONNECTIONSTRING", - "DbContextPooling": true, - "DisableHealthChecks": true, - "DisableTracing": true, - "DisableMetrics": false - } - } - } - } -} -``` - -#### Use inline configurations - -You can also pass the `Action` delegate to set up some or all the options inline, for example to turn off the metrics: - -```csharp -builder.AddSqlServerDbContext( - "sql", - static settings => - settings.DisableMetrics = true); -``` - -#### Configure multiple DbContext connections - -If you want to register more than one `DbContext` with different configuration, you can use `$"Aspire.Microsoft.EntityFrameworkCore.SqlServer:{typeof(TContext).Name}"` configuration section name. The json configuration would look like: - -```json -{ - "Aspire": { - "Microsoft": { - "EntityFrameworkCore": { - "SqlServer": { - "ConnectionString": "YOUR_CONNECTIONSTRING", - "DbContextPooling": true, - "DisableHealthChecks": true, - "DisableTracing": true, - "DisableMetrics": false, - "AnotherDbContext": { - "ConnectionString": "AnotherDbContext_CONNECTIONSTRING", - "DisableTracing": false - } - } - } - } - } -} -``` - -Then calling the `AddSqlServerDbContext` method with `AnotherDbContext` type parameter would load the settings from `Aspire:Microsoft:EntityFrameworkCore:SqlServer:AnotherDbContext` section. - -```csharp -builder.AddSqlServerDbContext("another-sql"); -``` - -#### Configuration options - -Here are the configurable options with corresponding default values: - -| Name | Description | -|-----------------------|----------------------------------------------------------------------------------------------------------------------| -| `ConnectionString` | The connection string of the SQL Server database to connect to. | -| `DbContextPooling` | A boolean value that indicates whether the db context will be pooled or explicitly created every time it's requested | -| `MaxRetryCount` | The maximum number of retry attempts. Default value is 6, set it to 0 to disable the retry mechanism. | -| `DisableHealthChecks` | A boolean value that indicates whether the database health check is disabled or not. | -| `DisableTracing` | A boolean value that indicates whether the OpenTelemetry tracing is disabled or not. | -| `DisableMetrics` | A boolean value that indicates whether the OpenTelemetry metrics are disabled or not. | -| `Timeout` | The time in seconds to wait for the command to execute. | - -[!INCLUDE [client-integration-health-checks](../includes/client-integration-health-checks.md)] - -By default, the .NET Aspire Sql Server Entity Framework Core integration handles the following: - -- Adds the [`DbContextHealthCheck`](https://github.com/Xabaril/AspNetCore.Diagnostics.HealthChecks/blob/master/src/HealthChecks.NpgSql/NpgSqlHealthCheck.cs), which calls EF Core's method. The name of the health check is the name of the `TContext` type. -- Integrates with the `/health` HTTP endpoint, which specifies all registered health checks must pass for app to be considered ready to accept traffic - -[!INCLUDE [integration-observability-and-telemetry](../includes/integration-observability-and-telemetry.md)] - -#### Logging - -The .NET Aspire SQL Server Entity Framework Core integration uses the following Log categories: - -- `Microsoft.EntityFrameworkCore.ChangeTracking` -- `Microsoft.EntityFrameworkCore.Database.Command` -- `Microsoft.EntityFrameworkCore.Database.Connection` -- `Microsoft.EntityFrameworkCore.Database.Transaction` -- `Microsoft.EntityFrameworkCore.Infrastructure` -- `Microsoft.EntityFrameworkCore.Migrations` -- `Microsoft.EntityFrameworkCore.Model` -- `Microsoft.EntityFrameworkCore.Model.Validation` -- `Microsoft.EntityFrameworkCore.Query` -- `Microsoft.EntityFrameworkCore.Update` - -#### Tracing - -The .NET Aspire SQL Server Entity Framework Core integration will emit the following Tracing activities using OpenTelemetry: - -- "OpenTelemetry.Instrumentation.EntityFrameworkCore" - -#### Metrics - -The .NET Aspire SQL Server Entity Framework Core integration will emit the following metrics using OpenTelemetry: - -- Microsoft.EntityFrameworkCore: - - `ec_Microsoft_EntityFrameworkCore_active_db_contexts` - - `ec_Microsoft_EntityFrameworkCore_total_queries` - - `ec_Microsoft_EntityFrameworkCore_queries_per_second` - - `ec_Microsoft_EntityFrameworkCore_total_save_changes` - - `ec_Microsoft_EntityFrameworkCore_save_changes_per_second` - - `ec_Microsoft_EntityFrameworkCore_compiled_query_cache_hit_rate` - - `ec_Microsoft_Entity_total_execution_strategy_operation_failures` - - `ec_Microsoft_E_execution_strategy_operation_failures_per_second` - - `ec_Microsoft_EntityFramew_total_optimistic_concurrency_failures` - - `ec_Microsoft_EntityF_optimistic_concurrency_failures_per_second` +[!INCLUDE [sql-server-ef-client](includes/sql-server-ef-client.md)] ## See also diff --git a/docs/database/sql-server-integration.md b/docs/database/sql-server-integration.md index 1f651ecbba..d4134dc8bc 100644 --- a/docs/database/sql-server-integration.md +++ b/docs/database/sql-server-integration.md @@ -23,168 +23,7 @@ The hosting integration relies on the [📦 AspNetCore.HealthChecks.SqlServer](h ## Client integration -To get started with the .NET Aspire SQL Server client integration, install the [📦 Aspire.Microsoft.Data.SqlClient](https://www.nuget.org/packages/Aspire.Microsoft.Data.SqlClient) NuGet package in the client-consuming project, that is, the project for the application that uses the SQL Server client. The SQL Server client integration registers a instance that you can use to interact with SQL Server. - -### [.NET CLI](#tab/dotnet-cli) - -```dotnetcli -dotnet add package Aspire.Microsoft.Data.SqlClient -``` - -### [PackageReference](#tab/package-reference) - -```xml - -``` - ---- - -### Add SQL Server client - -In the _:::no-loc text="Program.cs":::_ file of your client-consuming project, call the extension method on any to register a `SqlConnection` for use via the dependency injection container. The method takes a connection name parameter. - -```csharp -builder.AddSqlServerClient(connectionName: "database"); -``` - -> [!TIP] -> The `connectionName` parameter must match the name used when adding the SQL Server database resource in the app host project. In other words, when you call `AddDatabase` and provide a name of `database` that same name should be used when calling `AddSqlServerClient`. For more information, see [Add SQL Server resource and database resource](#add-sql-server-resource-and-database-resource). - -You can then retrieve the instance using dependency injection. For example, to retrieve the connection from an example service: - -```csharp -public class ExampleService(SqlConnection connection) -{ - // Use connection... -} -``` - -For more information on dependency injection, see [.NET dependency injection](/dotnet/core/extensions/dependency-injection). - -### Add keyed SQL Server client - -There might be situations where you want to register multiple `SqlConnection` instances with different connection names. To register keyed SQL Server clients, call the method: - -```csharp -builder.AddKeyedSqlServerClient(name: "mainDb"); -builder.AddKeyedSqlServerClient(name: "loggingDb"); -``` - -> [!IMPORTANT] -> When using keyed services, it's expected that your SQL Server resource configured two named databases, one for the `mainDb` and one for the `loggingDb`. - -Then you can retrieve the `SqlConnection` instances using dependency injection. For example, to retrieve the connection from an example service: - -```csharp -public class ExampleService( - [FromKeyedServices("mainDb")] SqlConnection mainDbConnection, - [FromKeyedServices("loggingDb")] SqlConnection loggingDbConnection) -{ - // Use connections... -} -``` - -For more information on keyed services, see [.NET dependency injection: Keyed services](/dotnet/core/extensions/dependency-injection#keyed-services). - -### Configuration - -The .NET Aspire SQL Server integration provides multiple options to configure the connection based on the requirements and conventions of your project. - -#### Use a connection string - -When using a connection string from the `ConnectionStrings` configuration section, you can provide the name of the connection string when calling the method: - -```csharp -builder.AddSqlServerClient(connectionName: "sql"); -``` - -Then the connection string is retrieved from the `ConnectionStrings` configuration section: - -```json -{ - "ConnectionStrings": { - "database": "Data Source=myserver;Initial Catalog=master" - } -} -``` - -For more information on how to format this connection string, see the [ConnectionString](/dotnet/api/system.data.sqlclient.sqlconnection.connectionstring#remarks). - -#### Use configuration providers - -The .NET Aspire SQL Server integration supports . It loads the from configuration by using the `Aspire:Microsoft:Data:SqlClient` key. The following snippet is an example of a _:::no-loc text="appsettings.json":::_ file that configures some of the options: - -```json -{ - "Aspire": { - "Microsoft": { - "Data": { - "SqlClient": { - "ConnectionString": "YOUR_CONNECTIONSTRING", - "DisableHealthChecks": false, - "DisableMetrics": true - } - } - } - } -} -``` - -For the complete SQL Server client integration JSON schema, see [Aspire.Microsoft.Data.SqlClient/ConfigurationSchema.json](https://github.com/dotnet/aspire/blob/v8.2.2/src/Components/Aspire.Microsoft.Data.SqlClient/ConfigurationSchema.json). - -#### Use inline delegates - -Also you can pass the `Action configureSettings` delegate to set up some or all the options inline, for example to disable health checks from code: - -```csharp -builder.AddSqlServerClient( - "database", - static settings => settings.DisableHealthChecks = true); -``` - -### Client integration health checks - -By default, .NET Aspire integrations enable [health checks](../fundamentals/health-checks.md) for all services. For more information, see [.NET Aspire integrations overview](../fundamentals/integrations-overview.md). - -The .NET Aspire SQL Server integration: - -- Adds the health check when is `false`, which attempts to connect to the SQL Server. -- Integrates with the `/health` HTTP endpoint, which specifies all registered health checks must pass for app to be considered ready to accept traffic. - -[!INCLUDE [integration-observability-and-telemetry](../includes/integration-observability-and-telemetry.md)] - -#### Logging - -The .NET Aspire SQL Server integration currently doesn't enable logging by default due to limitations of the . - -#### Tracing - -The .NET Aspire SQL Server integration emits the following tracing activities using OpenTelemetry: - -- `OpenTelemetry.Instrumentation.SqlClient` - -#### Metrics - -The .NET Aspire SQL Server integration will emit the following metrics using OpenTelemetry: - -- Microsoft.Data.SqlClient.EventSource - - `active-hard-connections` - - `hard-connects` - - `hard-disconnects` - - `active-soft-connects` - - `soft-connects` - - `soft-disconnects` - - `number-of-non-pooled-connections` - - `number-of-pooled-connections` - - `number-of-active-connection-pool-groups` - - `number-of-inactive-connection-pool-groups` - - `number-of-active-connection-pools` - - `number-of-inactive-connection-pools` - - `number-of-active-connections` - - `number-of-free-connections` - - `number-of-stasis-connections` - - `number-of-reclaimed-connections` +[!INCLUDE [sql-server-client](includes/sql-server-client.md)] ## See also diff --git a/docs/toc.yml b/docs/toc.yml index 7e937b2485..23e20c2298 100644 --- a/docs/toc.yml +++ b/docs/toc.yml @@ -190,6 +190,9 @@ items: - name: Azure Service Bus displayName: service bus,messaging href: messaging/azure-service-bus-integration.md + - name: Azure SQL Database + displayName: azure sql database,database + href: database/azure-sql-integration.md - name: Azure Storage items: - name: Azure Blob Storage @@ -233,6 +236,9 @@ items: - name: Azure PostgreSQL displayName: postgresql,ef core href: database/azure-postgresql-entity-framework-integration.md + - name: Azure SQL Database + displayName: azure sql database,database,ef core + href: database/azure-sql-entity-framework-integration.md - name: MySQL Pomelo displayName: mysql pomelo,ef core href: database/mysql-entity-framework-integration.md