教程:使用 .NET Aspire 和 Entity Framework Core 将 ASP.NET Core 应用连接到 SQL Server

在本教程中,你将创建一个 ASP.NET Core 应用,该应用使用 .NET AspireEntity Framework CoreSQL Server 集成连接到 SQL Server 来读取和写入支持票证数据。 Entity Framework Core 是一种轻型、可扩展的开源对象关系映射器,使 .NET 开发人员能够使用 .NET 对象处理数据库。 你将了解如何:

  • 创建一个基本 .NET 应用,该应用设置为使用 .NET Aspire 集成
  • 添加 .NET Aspire 集成以连接到 SQL Server
  • 配置和使用 .NET.NET Aspire 组件功能,用于从数据库读取和写入

先决条件

若要使用 .NET.NET Aspire,需要在本地安装以下各项:

有关详细信息,请参阅 .NET.NET Aspire 设置和工具,以及 .NET.NET Aspire SDK

创建示例解决方案

  1. 在 Visual Studio顶部,转到 文件>新建>项目
  2. 在对话框窗口中,搜索 Blazor 并选择 Blazor Web 应用。 选择 然后选择
  3. 配置新项目 界面上:
    • 输入 AspireSQLEFCore项目名称
    • 将 rest 的值保留为默认值,然后选择 下一步
  4. 其他信息 界面上:
    • 确保已选择 .NET 9.0
    • 确保 交互式呈现模式 设置为 None
    • 选中 登记至 .NET.NET Aspire 编排 选项,然后选择“创建”。

Visual Studio 创建了新的 ASP.NET Core 解决方案,该方案设计为使用 .NET Aspire。 该解决方案由以下项目组成:

  • AspireSQLEFCore:依赖于服务默认值的 Blazor 项目。
  • AspireSQLEFCore.AppHost:一个业务流程协调程序项目,旨在连接和配置应用的不同项目和服务。 协调器应设置为启动项目。
  • AspireSQLEFCore.ServiceDefaults:用于保存可在解决方案中的项目中重复使用的配置的共享类库。

创建数据库模型和上下文类

若要表示用户提交的支持请求,请在 AspireSQLEFCore 项目的根目录中添加以下 SupportTicket 模型类。

using System.ComponentModel.DataAnnotations;

namespace AspireSQLEFCore;

public sealed class SupportTicket
{
    public int Id { get; set; }
    [Required]
    public string Title { get; set; } = string.Empty;
    [Required]
    public string Description { get; set; } = string.Empty;
}

AspireSQLEFCore 项目的根目录中添加以下 TicketDbContext 数据上下文类。 该类继承 System.Data.Entity.DbContext 来处理 Entity Framework 并表示数据库。

using Microsoft.EntityFrameworkCore;
using System.Reflection.Metadata;

namespace AspireSQLEFCore;

public class TicketContext(DbContextOptions options) : DbContext(options)
{
    public DbSet<SupportTicket> Tickets => Set<SupportTicket>();
}

将 .NET Aspire 集成添加到 Blazor 应用

.NET AspireEntity Framework Core Sql Server 库包 添加到 AspireSQLEFCore 项目中:

dotnet add package Aspire.Microsoft.EntityFrameworkCore.SqlServer

AspireSQLEFCore 项目现已设置为使用 .NET.NET Aspire 集成。 下面是更新的 AspireSQLEFCore.csproj 文件:

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>net9.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Aspire.Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.0" />
  </ItemGroup>

  <ItemGroup>
    <ProjectReference Include="..\AspireSQLEFCore.ServiceDefaults\AspireSQLEFCore.ServiceDefaults.csproj" />
  </ItemGroup>

</Project>

配置 .NET.NET Aspire 集成

AspireSQLEFCore 项目的 Program.cs 文件中,在创建 builder 后,但在调用 AddServiceDefaults之前添加对 AddSqlServerDbContext 扩展方法的调用。 有关详细信息,请参阅 .NET.NET Aspire 服务默认值。 提供连接字符串的名称作为参数。

using AspireSQLEFCore;
using AspireSQLEFCore.Components;

var builder = WebApplication.CreateBuilder(args);
builder.AddSqlServerDbContext<TicketContext>("sqldata");

builder.AddServiceDefaults();

// Add services to the container.
builder.Services.AddRazorComponents().AddInteractiveServerComponents();

var app = builder.Build();

app.MapDefaultEndpoints();

此方法完成以下任务:

  • 向 DI 容器注册 TicketContext,以便连接到容器化 Azure SQL 数据库。
  • 自动启用相应的运行状况检查、日志记录和遥测。

创建数据库

在本地开发时,需要在 SQL Server 容器中创建数据库。 使用以下代码更新 Program.cs 文件:

using AspireSQLEFCore;
using AspireSQLEFCore.Components;

var builder = WebApplication.CreateBuilder(args);
builder.AddSqlServerDbContext<TicketContext>("sqldata");

builder.AddServiceDefaults();

// Add services to the container.
builder.Services.AddRazorComponents().AddInteractiveServerComponents();

var app = builder.Build();

app.MapDefaultEndpoints();

if (app.Environment.IsDevelopment())
{
    using (var scope = app.Services.CreateScope())
    {
        var context = scope.ServiceProvider.GetRequiredService<TicketContext>();
        context.Database.EnsureCreated();
    }
}
else
{
    app.UseExceptionHandler("/Error", createScopeForErrors: true);
    // The default HSTS value is 30 days.
    // You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

前面的代码:

  • 检查应用是否在开发环境中运行。
  • 如果是,它将从 DI 容器检索 TicketContext 服务,并调用 Database.EnsureCreated() 以创建数据库(如果尚不存在)。

注意

请注意,EnsureCreated() 不适用于生产环境,它仅创建上下文中定义的数据库。 它不应用任何迁移。 有关 .NET Aspire中 Entity Framework Core 迁移的详细信息,请参阅 在 .NET Aspire中应用 Entity Framework Core 迁移。

创建表单

应用需要一个表单,使用户能够提交支持票证信息并将条目保存到数据库。

使用以下 Razor 标记创建基本表单,替换 AspireSQLEFCore/Components/Pages 目录中 Home.razor 文件的内容:

@page "/"
@inject TicketContext context

<div class="row">
    <div class="col-md-6">
        <div>
            <h1 class="display-4">Request Support</h1>
        </div>
        <EditForm Model="@Ticket" FormName="Tickets" method="post"
                  OnValidSubmit="@HandleValidSubmit" class="mb-4">
            <DataAnnotationsValidator />
            <div class="mb-4">
                <label>Issue Title</label>
                <InputText class="form-control" @bind-Value="@Ticket.Title" />
                <ValidationMessage For="() => Ticket.Title" />
            </div>
            <div class="mb-4">
                <label>Issue Description</label>
                <InputText class="form-control" @bind-Value="@Ticket.Description" />
                <ValidationMessage For="() => Ticket.Description" />
            </div>
            <button class="btn btn-primary" type="submit">Submit</button>
            <button class="btn btn-danger mx-2" type="reset" @onclick=@ClearForm>Clear</button>
        </EditForm>

        <table class="table table-striped">
            @foreach (var ticket in Tickets)
            {
                <tr>
                    <td>@ticket.Id</td>
                    <td>@ticket.Title</td>
                    <td>@ticket.Description</td>
                </tr>
            }
        </table>
    </div>
</div>

@code {
    [SupplyParameterFromForm(FormName = "Tickets")]
    private SupportTicket Ticket { get; set; } = new();

    private List<SupportTicket> Tickets = [];

    private void ClearForm() => Ticket = new();

    protected override async Task OnInitializedAsync()
    {
        Tickets = await context.Tickets.ToListAsync();
    }

    private async Task HandleValidSubmit()
    {
        context.Tickets.Add(Ticket);

        await context.SaveChangesAsync();

        Tickets = await context.Tickets.ToListAsync();

        ClearForm();
    }
}

有关在 Blazor中创建表单的详细信息,请参阅 ASP.NET CoreBlazor 窗体概述

配置 AppHost

AspireSQLEFCore.AppHost 项目是您应用的协调器。 它负责连接和配置应用的不同项目和服务。 协调器应设置为启动项目。

.NET Aspire 托管的 Sql Server NuGet 包添加到你的 AspireStorage.AppHost 项目中:

dotnet add package Aspire.Hosting.SqlServer

AspireSQLEFCore.AppHost 项目中 Program.cs 文件的内容替换为以下代码:

var builder = DistributedApplication.CreateBuilder(args);

var sql = builder.AddSqlServer("sql")
                 .AddDatabase("sqldata");

builder.AddProject<Projects.AspireSQLEFCore>("aspiresql")
       .WithReference(sql)
       .WaitFor(sql);

builder.Build().Run();

前面的代码将 SQL Server 容器资源添加到应用,并配置与名为 sqldata的数据库的连接。 之前配置的 Entity Framework 类会在迁移和连接到数据库时自动使用此连接。

在本地运行和测试应用

示例应用现已准备好进行测试。 通过完成以下步骤,验证提交的表单数据是否持久保存到数据库:

  1. 选择 Visual Studio 顶部的运行按钮(或 F5),在浏览器中启动 .NET.NET Aspire 项目仪表板。

  2. 在项目页面中,在 AspireSQLEFCore 行中,单击 终结点 列中的链接以打开应用程序的界面。

    显示 .NET.NET Aspire 支持应用程序的主页的屏幕截图。

  3. TitleDescription 窗体字段中输入示例数据。

  4. 选择 提交 按钮,表单提交支持票证进行处理 — (然后选择 清除 以清除表单)。

  5. 在页面重新加载时,提交的数据将显示在页面底部的表中。

另请参阅