.NET Aspire SQL Server Entity Framework Core 集成

包含:托管集成已包含 - Client 集成已包含Client 集成

SQL Server 是由Microsoft开发的关系数据库管理系统。 通过.NET AspireSQL ServerEntity Framework Core集成,可以连接到现有SQL Server实例或从.NETmcr.microsoft.com/mssql/server容器映像创建新实例。

托管集成

托管集成 SQL Server 将服务器建模为 SqlServerServerResource 类型和数据库作为 SqlServerDatabaseResource 类型。 若要访问这些类型和 API,请在📦项目中添加Aspire.Hosting.SqlServer NuGet 包。

dotnet add package Aspire.Hosting.SqlServer

有关详细信息,请参阅 dotnet 添加包管理 .NET 应用程序中的包依赖性

添加 SQL Server 资源和数据库资源

在应用主机项目中,调用 AddSqlServer 添加并返回 SQL Server 资源生成器。 将对返回资源生成器的调用链接到 AddDatabase,以便添加 SQL Server 数据库资源。

var builder = DistributedApplication.CreateBuilder(args);

var sql = builder.AddSqlServer("sql")
                 .WithLifetime(ContainerLifetime.Persistent);

var db = sql.AddDatabase("database");

builder.AddProject<Projects.ExampleProject>("exampleproject")
       .WithReference(db)
       .WaitFor(db);

// After adding all resources, run the app...

builder.Build().Run();

注释

SQL Server 容器启动速度较慢,因此最好使用 持久性 生命周期,以避免不必要的重启。 有关详细信息,请参阅 容器资源生存期

当 .NET.NET Aspire 向应用主机添加容器镜像时,正如上例中的 mcr.microsoft.com/mssql/server 镜像所示,它会在您的本地计算机上创建一个新的 SQL Server 实例。 对 SQL Server 资源生成器(sql 变量)的引用用于添加数据库。 数据库命名为 database,然后将该数据库添加到 ExampleProject

将数据库资源添加到应用模型时,如果数据库尚不存在,则会创建该数据库。 数据库的创建依赖于 应用主机事件 API,具体而言 ResourceReadyEvent。 换句话说,当sql资源准备就绪时,将引发事件并创建数据库资源。

SQL Server 资源包括默认凭据,其中usernamesa,并且使用 password 方法生成了随机的 CreateDefaultPasswordParameter

应用主机运行时,密码存储在应用主机的机密存储中。 它已添加到 Parameters 部分,例如:

{
  "Parameters:sql-password": "<THE_GENERATED_PASSWORD>"
}

参数的名称是 sql-password,但实际上只是将资源名称格式化为带有 -password 后缀的形式。 有关详细信息,请参阅 ASP.NET Core 中应用机密在开发阶段的安全存储,以及 SQL Server 中添加带参数的资源。

WithReference 方法在 ExampleProject 中配置一个名为 database的连接。

小窍门

如果想要连接到现有 SQL Server,请改为调用 AddConnectionString。 有关详细信息,请参阅 引用现有资源

使用数据库脚本添加 SQL Server 资源

默认情况下,当您添加SqlServerDatabaseResource时,它依赖于以下SQL脚本来创建数据库:

IF
(
    NOT EXISTS
    (
        SELECT 1
        FROM sys.databases
        WHERE name = @DatabaseName
    )
)
CREATE DATABASE [<QUOTED_DATABASE_NAME>];

若要更改默认脚本,请在数据库资源生成器上链式调用 WithCreationScript 方法:

var builder = DistributedApplication.CreateBuilder(args);

var sql = builder.AddSqlServer("sql")
                 .WithLifetime(ContainerLifetime.Persistent);

var databaseName = "app-db";
var creationScript = $$"""
    IF DB_ID('{{databaseName}}') IS NULL
        CREATE DATABASE [{{databaseName}}];
    GO

    -- Use the database
    USE [{{databaseName}}];
    GO

    -- Create the todos table
    CREATE TABLE todos (
        id INT PRIMARY KEY IDENTITY(1,1),        -- Unique ID for each todo
        title VARCHAR(255) NOT NULL,             -- Short description of the task
        description TEXT,                        -- Optional detailed description
        is_completed BIT DEFAULT 0,              -- Completion status
        due_date DATE,                           -- Optional due date
        created_at DATETIME DEFAULT GETDATE()    -- Creation timestamp
    );
    GO

    """;

var db = sql.AddDatabase(databaseName)
            .WithCreationScript(creationScript);

builder.AddProject<Projects.AspireApp_ExampleProject>("exampleproject")
       .WithReference(db)
       .WaitFor(db);

// After adding all resources, run the app...

builder.Build().Run();

以上示例创建一个名为app_db的数据库,其中包含一个todos表。 在创建数据库资源时将执行该 SQL 脚本。 脚本作为字符串传递给WithCreationScript方法,然后在SQL Server资源的上下文中执行。

添加具有数据容量的 SQL Server 资源

若要将数据卷添加到 SQL Server 资源,请在 WithDataVolume 资源上调用 SQL Server 方法:

var builder = DistributedApplication.CreateBuilder(args);

var sql = builder.AddSqlServer("sql")
                 .WithDataVolume();

var db = sql.AddDatabase("database");

builder.AddProject<Projects.AspireApp_ExampleProject>("exampleproject")
       .WithReference(db)
       .WaitFor(db);

// After adding all resources, run the app...

builder.Build().Run();

数据卷用于在容器的生命周期之外保留 SQL Server 数据。 数据卷装载在 /var/opt/mssql 容器中的 SQL Server 路径上,当未提供 name 参数时,则会随机生成名称。 有关数据量的详细信息,以及它们为何优于 绑定装载的详细原因,请参阅 Docker 文档:数据量

警告

密码存储在数据卷中。 当使用数据卷时,如果更改了密码,则在删除该卷之前,它将无法正常工作。

添加具有数据绑定挂载的 SQL Server 资源

若要将数据绑定挂载添加到 SQL Server 资源,请调用 WithDataBindMount 方法。

var builder = DistributedApplication.CreateBuilder(args);

var sql = builder.AddSqlServer("sql")
                 .WithDataBindMount(source: @"C:\SqlServer\Data");

var db = sql.AddDatabase("database");

builder.AddProject<Projects.AspireApp_ExampleProject>("exampleproject")
       .WithReference(db)
       .WaitFor(db);

// After adding all resources, run the app...

builder.Build().Run();

重要

相比,绑定 装载的数据功能有限,而 提供更好的性能、可移植性和安全性,因此它们更适用于生产环境。 但是,绑定装载允许直接访问和修改主机系统上的文件,非常适合在需要实时更改的情况下进行开发和测试。

数据绑定挂载依赖于主机文件系统,以便在容器重启时持久化 SQL Server 数据。 数据绑定装载被安装在 Windows 上的 C:\SqlServer\Data 路径上(或者在 /SqlServer/Data上的 Unix 路径上),位于 SQL Server 容器中的主机设备上。 有关数据挂载绑定的详细信息,请参阅 Docker 文档:挂载绑定

添加带有参数的 SQL Server 资源

如果要显式提供容器映像使用的密码,可以将这些凭据作为参数提供。 请考虑以下替代示例:

var builder = DistributedApplication.CreateBuilder(args);

var password = builder.AddParameter("password", secret: true);

var sql = builder.AddSqlServer("sql", password);
var db = sql.AddDatabase("database");

builder.AddProject<Projects.AspireApp_ExampleProject>("exampleproject")
       .WithReference(db)
       .WaitFor(db);

// After adding all resources, run the app...

builder.Build().Run();

有关提供参数的详细信息,请参阅 外部参数

连接至数据库资源

运行 .NET.NET Aspire 应用主机时,可以从外部工具(如 SQL Server Management Studio(SSMS)MSSQL 等外部工具访问服务器的数据库资源 Visual Studio Code。 数据库资源的连接字符串在依赖资源环境变量中可用,并使用 .NET.NET Aspire 仪表板进行访问:资源详细信息 窗格。 环境变量被命名为 ConnectionStrings__{name},其中 {name} 是数据库资源的名称,在本示例中为 database。 使用连接字符串从外部工具连接到数据库资源。 假设你有一个名为 todos 的数据库,其中包含单个 dbo.Todos 表。

若要从 SQL Server Management Studio 连接到数据库资源,请执行以下步骤:

  1. 打开 SSMS。

  2. 在“连接到 Server”对话框中,选择 “其他连接参数” 选项卡。

  3. 将连接字符串粘贴到“附加连接参数”字段中,然后选择“连接

    SQL Server Management Studio:连接到Server 对话框。

  4. 如果已连接,可以在 对象资源管理器中看到数据库资源:

    SQL Server Management Studio:连接到数据库。

有关详细信息,请参阅 SQL Server Management Studio:连接到服务器

主办集成健康检查

SQL Server 托管集成会自动为 SQL Server 资源添加运行状况检查。 运行状况检查会验证 SQL Server 是否正在运行,并确保可以成功建立与其的连接。

托管集成依赖于 📦 AspNetCore.HealthChecks.SqlServer NuGet 包。

Client 集成

若要开始使用.NET AspireSQL ServerEntity Framework Core集成,请在使用📦Aspire客户端的应用程序项目中安装 NuGet 包。

dotnet add package Aspire.Microsoft.EntityFrameworkCore.SqlServer

有关详细信息,请参阅 dotnet 添加包管理 .NET 应用程序中的包依赖性

添加 SQL Server 数据库上下文

在您的客户端消费项目中的 Program.cs 文件中,对任何 AddSqlServerDbContext 调用 IHostApplicationBuilder 扩展方法,以注册 DbContext,以便通过依赖注入容器进行使用。 该方法采用连接名称参数。

builder.AddSqlServerDbContext<ExampleDbContext>(connectionName: "database");

小窍门

connectionName 参数必须与在应用主机项目中添加 SQL Server 数据库资源时使用的名称匹配。 换句话说,当你调用 AddDatabase 并提供 database 的名称时,应该在调用 AddSqlServerDbContext时使用相同的名称。 有关详细信息,请参阅 添加 SQL Server 资源和数据库资源

从服务检索 ExampleDbContext 对象:

public class ExampleService(ExampleDbContext context)
{
    // Use context...
}

有关依赖项注入的详细信息,请参阅 .NET 依赖项注入

充实 SQL Server 数据库上下文

你可能更喜欢使用标准 Entity Framework 方法获取数据库上下文并将其添加到依赖项注入容器:

builder.Services.AddDbContext<ExampleDbContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("database")
        ?? throw new InvalidOperationException("Connection string 'database' not found.")));

注释

传递给该方法的 GetConnectionString 连接字符串名称必须与在应用主机项目中添加 SQL Server 资源时使用的名称匹配。 有关详细信息,请参阅 添加 SQL Server 资源和数据库资源

以这种方式创建数据库上下文时具有更大的灵活性,例如:

  • 可以重复使用数据库上下文的现有配置代码,而无需为 .NET.NET Aspire重写它。
  • 可以使用 Entity Framework Core 拦截器来修改数据库操作。
  • 可以选择不使用 Entity Framework Core 上下文池,在某些情况下性能可能更好。

如果使用此方法,通过调用 .NET 方法,可以为数据库上下文添加 .NET AspireEnrichSqlServerDbContext 样式的重试、运行状况检查、日志记录和遥测功能。

builder.EnrichSqlServerDbContext<ExampleDbContext>(
    configureSettings: settings =>
    {
        settings.DisableRetry = false;
        settings.CommandTimeout = 30; // seconds
    });

settings 参数是 MicrosoftEntityFrameworkCoreSqlServerSettings 类的实例。

配置

.NET Aspire SQL Server Entity Framework Core 集成提供了多种配置方法和选项,以满足项目的要求和约定。

使用连接字符串

使用 ConnectionStrings 配置部分中的连接字符串时,在调用 builder.AddSqlServerDbContext<TContext>()时提供连接字符串的名称:

builder.AddSqlServerDbContext<ExampleDbContext>("sql");

连接字符串从 ConnectionStrings 配置部分中检索而来。

{
  "ConnectionStrings": {
    "sql": "Data Source=myserver;Initial Catalog=master"
  }
}

EnrichSqlServerDbContext 不会使用 ConnectionStrings 配置部分,因为它预期在调用前已注册 DbContext

有关详细信息,请参阅 ConnectionString

使用配置提供器

.NET Aspire SQL Server Entity Framework Core 集成支持 Microsoft.Extensions.Configuration。 它通过使用 MicrosoftEntityFrameworkCoreSqlServerSettings 键从配置文件(例如 appsettings.json)中加载 Aspire:Microsoft:EntityFrameworkCore:SqlServer。 如果在 Aspire:Microsoft:EntityFrameworkCore:SqlServer 节中设置了配置,只需调用该方法即可不传递任何参数。

下面是配置某些可用选项的文件示例 appsettings.json

{
  "Aspire": {
    "Microsoft": {
      "EntityFrameworkCore": {
        "SqlServer": {
          "ConnectionString": "YOUR_CONNECTIONSTRING",
          "DbContextPooling": true,
          "DisableHealthChecks": true,
          "DisableTracing": true,
          "DisableMetrics": false
        }
      }
    }
  }
}

使用内联配置

还可以传递 Action<MicrosoftEntityFrameworkCoreSqlServerSettings> 委托来设置部分或全部内联选项,例如关闭指标:

builder.AddSqlServerDbContext<YourDbContext>(
    "sql",
    static settings =>
        settings.DisableMetrics = true);

配置多个 DbContext 连接

如果您想为多个 DbContext 注册不同的配置,可以使用 $"Aspire.Microsoft.EntityFrameworkCore.SqlServer:{typeof(TContext).Name}" 配置段名称。 json 配置如下所示:

{
  "Aspire": {
    "Microsoft": {
      "EntityFrameworkCore": {
          "SqlServer": {
            "ConnectionString": "YOUR_CONNECTIONSTRING",
            "DbContextPooling": true,
            "DisableHealthChecks": true,
            "DisableTracing": true,
            "DisableMetrics": false,
          "AnotherDbContext": {
            "ConnectionString": "AnotherDbContext_CONNECTIONSTRING",
            "DisableTracing": false
          }
        }
      }
    }
  }
}

然后,使用 AddSqlServerDbContext 类型参数调用 AnotherDbContext 方法将从 Aspire:Microsoft:EntityFrameworkCore:SqlServer:AnotherDbContext 节加载设置。

builder.AddSqlServerDbContext<AnotherDbContext>("another-sql");

配置选项

下面是具有相应默认值的可配置选项:

名字 DESCRIPTION
ConnectionString 要连接到 SQL Server 数据库的连接字符串。
DbContextPooling 一个布尔值,指示数据库上下文每次被请求时是否会被池化或显式创建。
MaxRetryCount 重试次数上限。 默认值为 6,将其设置为 0 以禁用重试机制。
DisableHealthChecks 一个布尔值,该值指示是否禁用数据库运行状况检查。
DisableTracing 一个布尔值,用于指示 OpenTelemetry 跟踪是否被禁用。
DisableMetrics 一个布尔值,该值指示是否禁用 OpenTelemetry 指标。
Timeout 等待命令执行的时间(以秒为单位)。

Client 集成健康检查

默认情况下,.NET.NET Aspire客户端集成 为所有服务启用 健康检查。 同样,许多托管集成 .NET.NET Aspire 也启用健康检查端点。 有关详细信息,请参见:

默认情况下, .NET Aspire Sql ServerEntity Framework Core 集成将处理以下内容:

  • 添加 DbContextHealthCheck,并调用 EF Core的 CanConnectAsync 方法。 健康检查的名称是 TContext 类型的名称。
  • /health HTTP 终结点集成,该终结点指定所有已注册的健康检查都必须通过,应用才会被视为准备好接受流量。

可观测性和遥测

.NET .NET Aspire 集成会自动设置日志记录、跟踪和指标等配置,这些配置有时称为 可观测性的基础支柱。 有关集成可观测性和遥测的详细信息,请参阅 .NET.NET Aspire 集成概述。 根据支持服务,某些集成可能仅支持其中一些功能。 例如,某些集成支持日志记录和跟踪,但不支持指标。 也可以使用 配置 部分中介绍的技术禁用遥测功能。

伐木业

.NET Aspire SQL Server Entity Framework Core 集成使用以下日志类别:

  • 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

追踪

.NET Aspire SQL Server Entity Framework Core 集成将使用 OpenTelemetry发出以下跟踪活动:

  • “OpenTelemetry.Instrumentation.EntityFrameworkCore”

指标

.NET Aspire SQL Server Entity Framework Core 集成将使用 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

另请参阅