ASP.NET Core 中使用实体框架 Core 访问数据库

页面创建日期 :

环境

Visual Studio
  • Visual Studio 2019
ASP.NET Core
  • 3.1 (MVC, Razor 页面)
SQL Server
  • 2019 Express

入门

此提示 ASP.NET 使用实体框架 Core 的过程,该过程遵循核心技术。

创建数据库、使用实体框架核心等不是此提示的主要内容,因此没有详细的说明。 它们 ASP.NET 核心之外以相同的方式使用。

这一次,我在另一台服务器上安装了 SQL Server,并通过 SQL Server 身份验证进行连接。 与在本地安装期间使用的 Windows 身份验证不同,只有连接字符串,并且程序没有区别。

创建数据库表

此提示使用 SQL Server。 在本地环境或任何服务器上安装 SQL Server。

如果没有要测试的数据库,请创建一个数据库。

如果要使用 SQL 创建 SQL,请根据您的环境更改 SQL Server 版本路径和数据库名称,如下所示:

USE [master]
GO

CREATE DATABASE [TestDatabase]
  CONTAINMENT = NONE
  ON  PRIMARY 
( NAME = N'TestDatabase', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL15.SQLEXPRESS\MSSQL\DATA\TestDatabase.mdf' , SIZE = 8192KB , MAXSIZE = UNLIMITED, FILEGROWTH = 65536KB )
  LOG ON 
( NAME = N'TestDatabase_log', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL15.SQLEXPRESS\MSSQL\DATA\TestDatabase_log.ldf' , SIZE = 8192KB , MAXSIZE = 2048GB , FILEGROWTH = 65536KB )
  WITH CATALOG_COLLATION = DATABASE_DEFAULT
GO

创建用于测试的表。 设置主键以进行更新或删除。

在 SQL 中创建时:

USE [TestDatabase]
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[User](
  [ID] [int] NOT NULL,
  [Name] [nvarchar](20) NOT NULL,
  [Password] [nvarchar](20) NOT NULL,
  [Age] [int] NULL,
  [Email] [nvarchar](200) NULL,
  [Birthday] [date] NULL,
  [UpdateDateTime] [datetime2](7) NULL,
  CONSTRAINT [PK_User] PRIMARY KEY CLUSTERED 
(
  [ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO

添加记录以进行查看。

在 SQL 中添加时:

USE [TestDatabase]
GO
INSERT [dbo].[User] ([ID], [Name], [Password], [Age], [Email], [Birthday], [UpdateDateTime]) VALUES (1, N'氏名1', N'aaaa', 20, N'aaaa@example.com', CAST(N'2020-04-01' AS Date), CAST(N'2021-03-14T00:00:00.0000000' AS DateTime2))
GO
INSERT [dbo].[User] ([ID], [Name], [Password], [Age], [Email], [Birthday], [UpdateDateTime]) VALUES (2, N'氏名2', N'bbbb', 30, N'bbbb@example.com', CAST(N'2010-04-01' AS Date), CAST(N'2021-03-14T00:00:00.0000000' AS DateTime2))
GO

ASP.NET 核心使用实体框架

此项目在 MVC 和 Razor 页面上都很常见。

实体框架核心的软件包安装

创建项目后,首先从 NuGet 获取包,以便可以使用实体框架核心。 此处以 MVC 为例,但 Razor 页的操作相同。

从项目中 右键单击 "依赖项 ",然后选择"管理 NuGet 包"。

选项卡中选择 "浏览",然后在搜索 字段中输入 EntityFrameworkCore。 然后,该列表显示与实体框架核心相关的包。

这一次,我们将使用 SQL Server,因此我们将安装以下包:

  • Microsoft.EntityFrameworkCore
  • Microsoft.EntityFrameworkCore.Tools
  • Microsoft.EntityFrameworkCore.SqlServer

我们将 以 Microsoft.EntityFrameworkCore 为例安装它,因此请以同样的方式安装其他两个。

选择要安装的内容, 然后单击 "安装"按钮。 版本选择最新的稳定器。

对话框基本上没有问题,单击"确定"。

请安装另外两个。

我认为包如下所示。

从数据库的表配置创建模型(程序)

如果要在实体框架核心中从数据库中检索或更新数据,请使用 您需要编写一个程序,该程序通常基于表配置进行建模。 此模型也称为实体。

创建模型时,代码优先是一种从模型(程序)创建 数据库表 的技术。 数据库优先是一种从表创建模型( 程序) 的技术。 本节介绍如何使用 易于执行 的数据库优先表自动编程。

顺便说一下 ASP.NET 这些步骤与核心无关,因此您可以在控制台或桌面应用中以类似的方式创建这些步骤。

首先,生成项目一次,以确保没有错误。 如果出现错误,则无法创建模型。 如果您已经验证了没有错误,则不需要生成它。

从 Visual Studio 打开包 管理器控制台。 如果没有,请从菜单中的"工具"、"NuGet 包管理器"和"包管理器控制台"中打开它。

将显示一个窗口,如下所示,因此确保右上角的"默认项目"是要为其创建模型的项目。 (如果您有多个项目,您需要小心)

在输入字段中输入以下文本。 参数因环境而异,因此请根据以下说明及时更改参数。 (尤其是 ****** 的部位)

Scaffold-DbContext -Provider Microsoft.EntityFrameworkCore.SqlServer -Connection "Data Source=********\SQLEXPRESS;Database=TestDatabase;user id=********;password=**********" -f -OutputDir "Models\Database" -Context "TestDatabaseDbContext" -UseDatabaseNames -DataAnnotations

每个名称的 -Provider 头部有连字符,如参数名称,后跟参数值。

参数 说明 参数示例
Provider 在 SQL Server Microsoft.EntityFrameworkCore.SqlServer 中是固定的。 Microsoft.EntityFrameworkCore.SqlServer
Connection 用于连接到数据库的连接字符串。 由于连接字符串在其他应用中也很常见,因此请根据连接字符串的表示法描述要指定的内容。 它可用于 Windows 和 SQL Server 身份验证。 顺便说一下,它仅用于创建模型,因此您不必担心此连接字符串在应用发布后的安全性。 如果密码包含符号,请注意转义。 "Data Source=ServerName\SQLEXPRESS;Database=TestDatabase;user id=UserName;password=**********"
f 强制覆盖程序,即使该程序已存在。 <无>
OutputDir 要打印代码的文件夹路径。 相对于项目文件夹的路径 Models\Database
Context 使用实体框架时的上下文类名称 TestDatabaseDbContext
UseDatabaseNames 如果指定,数据库的表名称将按原样成为类名称。 如果未指定,则根据规则调整实体类名称的大小写和复数。 <无>
DataAnnotations 如果指定,列类型将自动将 DataAnnotation 属性附加到每个属性。 如果要根据数据库类型自动执行输入检查,这有点方便。 <无>

按 Enter 运行时,将自动生成代码,如下所示:

User 表的模型代码如下所示:

[Table("User")]
public partial class User
{
  [Key]
  public int ID { get; set; }
  [Required]
  [StringLength(20)]
  public string Name { get; set; }
  [Required]
  [StringLength(20)]
  public string Password { get; set; }
  public int? Age { get; set; }
  [StringLength(200)]
  public string Email { get; set; }
  [Column(TypeName = "date")]
  public DateTime? Birthday { get; set; }
  public DateTime? UpdateDateTime { get; set; }
}

顺便说一下,警告是因为它在生成的上下文类代码中按原样列出连接字符串。 请确保在 OnConfiguring 生成代码后删除此上下文类的方法。

注册连接字符串

这是 ASP.NET Core 的特定过程。 (您可以自定义它,以用于其他 .NET Core 应用 ASP.NET 默认情况下,它可用于核心)

在包管理器控制台中指定的连接字符串仅用于生成模型。

appsettings.json中提供了作为 Web 应用连接到数据库的连接字符串。 如果要更改每次生成或发布时连接到的数据库目标,请使用appsettings。 也可以使用 Development.json等进行分支。

此外,由于此连接字符串用作操作,因此请采取措施,如连接用户专用用户,同时考虑安全性等。

如果设置为 appsettings.json,请创建根节中的 ConnectionStrings 节(确切地称为对象,而不是节)。 在其中创建一组键和值。 密钥的名称并不重要,但稍后使用。 该值是连接字符串。

{
  // 

  "ConnectionStrings": {
    "TestDatabaseDbContext": "Data Source=ServerName\\SQLEXPRESS;Database=TestDatabase;user id=UserName;password=********"
  }
}

使实体框架 Core 可供程序使用

这是 ASP.NET Core 的特定过程。 (您可以自定义它,以用于其他 .NET Core 应用 ASP.NET 默认情况下,它可用于核心)

ASP.NET 核心与控制台和桌面应用不同,每个实例都有一个生存期。 例如,"从 Web 服务启动到停止"或"从收到请求到返回响应"。 ASP.NET,默认情况下,实体框架 Core 可以放置在 Core ServiceLifetime.Scoped 中。 如果没有特殊原因,可以保持原样。

若要允许程序访问数据库上下文,请将其添加到 Startup.ConfigureServices 中,如下所示:

// 追加 (自前のクラスなので名前空間は適時合わせてください)
using DatabaseEntityFrameworkCoreMvc.Models.Database;

// 追加
using Microsoft.EntityFrameworkCore;

public class Startup
{
  // 省略

  // このメソッドはランタイムによって呼び出されます。 このメソッドを使用して、コンテナーにサービスを追加します。
  public void ConfigureServices(IServiceCollection services)
  {
    // 省略

    // 追加
    services.AddDbContext<TestDatabaseDbContext>(
      options => options.UseSqlServer(Configuration.GetConnectionString("TestDatabaseDbContext")));
  }

  // 省略

services.AddDbContext<TestDatabaseDbContext> 方法的类型参数指定创建的上下文类。

options.UseSqlServer 方法指示使用 SQL Server。

Configuration.GetConnectionString("TestDatabaseDbContext") 指定在 appsettings.json 中注册的密钥名称。

ASP.NET Core MVC 中的示例

ASP.NET Core MVC 中使用实体框架 Core 的方法有很多种。

使用 DI(依赖项插入)添加到控制器

通过.cs services.AddDbContext Startup TestDatabaseDbContext 方法注册 可以插入到控制器中。

DI 的一 HomeController 个示例是 构造函数作为 ILogger<HomeController> logger 参数。 这是 DI 添加的内容。 也可以 TestDatabaseDbContext 以同样的方式插入 。

如果要 HomeController 将现有 添加到 : 当然,您可以将其添加到其他控制器。

using DatabaseEntityFrameworkCoreMvc.Models.Database;  // 追加

// 省略

public class HomeController : Controller
{
  private readonly ILogger<HomeController> _logger;
  
  // 追加
  private readonly TestDatabaseDbContext _dbContext;
  
  public HomeController(ILogger<HomeController> logger, TestDatabaseDbContext dbContext)  // 追加
  {
    _logger = logger;
    _dbContext = dbContext;  // 追加
  }
  
  // 省略
}

然后,通过在每个操作中使用收到的上下文的实例来访问数据库。

使用示例

以下代码处理用户列表和新注册。 前面都是 ASP.NET Core、实体框架 Core 中的代码,因此省略了详细说明。

实体框架核心生成的模型可用作操作的模型。 您可以单独创建模型,并包装实体框架核心模型。

此外,当用户的请求结束时,上下文将自动销毁。

HomeController.cs

public class HomeController : Controller
{
  private readonly TestDatabaseDbContext _dbContext;

  // 省略

  // ここから追加

  /// <summary>
  /// ユーザー一覧表示アクション。
  /// </summary>
  public IActionResult List()
  {
    // データベースから User 一覧を取得する
    var users = _dbContext.Users.ToList();
    
    // ビューに渡す
    return View(users);
  }
  
  /// <summary>
  /// ユーザー一新規登録画面。
  /// </summary>
  public IActionResult Create()
  {
    return View();
  }
  
  /// <summary>
  /// ユーザー新規登録処理。
  /// </summary>
  [HttpPost]
  public IActionResult Create(User user)
  {
    // エラーがある場合は登録画面に戻る
    if (ModelState.IsValid == false) View(user);
    
    // 更新日時設定
    user.UpdateDateTime = DateTime.Now;

    // 登録リストにユーザー追加
    _dbContext.Users.Add(user);

    // 登録を確定する
    _dbContext.SaveChanges();
    
    // 一覧画面に遷移
    return RedirectToAction(nameof(List));
  }

  // ここまで追加

  // 省略
}

由于手动创建屏幕很麻烦,因此使用基架自动生成列表屏幕。

自动 Views/Home/List.cshtml 生成如下所示:

@model IEnumerable<DatabaseEntityFrameworkCoreMvc.Models.Database.User>

@{
  ViewData["Title"] = "List";
  Layout = "~/Views/Shared/_Layout.cshtml";
}

<h1>List</h1>

<p>
  <a asp-action="Create">Create New</a>
</p>
<table class="table">
  <thead>
    <tr>
      <th>
        @Html.DisplayNameFor(model => model.ID)
      </th>
      <th>
        @Html.DisplayNameFor(model => model.Name)
      </th>
      <th>
        @Html.DisplayNameFor(model => model.Password)
      </th>
      <th>
        @Html.DisplayNameFor(model => model.Age)
      </th>
      <th>
        @Html.DisplayNameFor(model => model.Email)
      </th>
      <th>
        @Html.DisplayNameFor(model => model.Birthday)
      </th>
      <th>
        @Html.DisplayNameFor(model => model.UpdateDateTime)
      </th>
      <th></th>
    </tr>
  </thead>
  <tbody>
@foreach (var item in Model) {
    <tr>
      <td>
        @Html.DisplayFor(modelItem => item.ID)
      </td>
      <td>
        @Html.DisplayFor(modelItem => item.Name)
      </td>
      <td>
        @Html.DisplayFor(modelItem => item.Password)
      </td>
      <td>
        @Html.DisplayFor(modelItem => item.Age)
      </td>
      <td>
        @Html.DisplayFor(modelItem => item.Email)
      </td>
      <td>
        @Html.DisplayFor(modelItem => item.Birthday)
      </td>
      <td>
        @Html.DisplayFor(modelItem => item.UpdateDateTime)
      </td>
      <td>
        @Html.ActionLink("Edit", "Edit", new { /* id=item.PrimaryKey */ }) |
        @Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ }) |
        @Html.ActionLink("Delete", "Delete", new { /* id=item.PrimaryKey */ })
      </td>
    </tr>
}
  </tbody>
</table>

Index.cshtml 将屏幕转换链接添加到列表中。

<!-- 省略 -->

<ul>
  <li><a asp-action="List">List</a></li>
</ul>

用户注册屏幕也会自动生成。

自动 Views/Home/Create.cshtml 生成如下所示: 因为它是,它很难使用,所以它纠正了一点。

@model DatabaseEntityFrameworkCoreMvc.Models.Database.User

@{
  ViewData["Title"] = "Create";
  Layout = "~/Views/Shared/_Layout.cshtml";
}

<h1>Create</h1>

<h4>User</h4>
<hr />
<div class="row">
  <div class="col-md-4">
    <form asp-action="Create">
      <div asp-validation-summary="ModelOnly" class="text-danger"></div>
      <div class="form-group">
        <label asp-for="ID" class="control-label"></label>
        <input asp-for="ID" class="form-control" />
        <span asp-validation-for="ID" class="text-danger"></span>
      </div>
      <div class="form-group">
        <label asp-for="Name" class="control-label"></label>
        <input asp-for="Name" class="form-control" />
        <span asp-validation-for="Name" class="text-danger"></span>
      </div>
      <div class="form-group">
        <label asp-for="Password" class="control-label"></label>
        <input asp-for="Password" class="form-control" type="password" /> <!-- type="password" 追加 -->
        <span asp-validation-for="Password" class="text-danger"></span>
      </div>
      <div class="form-group">
        <label asp-for="Age" class="control-label"></label>
        <input asp-for="Age" class="form-control" />
        <span asp-validation-for="Age" class="text-danger"></span>
      </div>
      <div class="form-group">
        <label asp-for="Email" class="control-label"></label>
        <input asp-for="Email" class="form-control" />
        <span asp-validation-for="Email" class="text-danger"></span>
      </div>
      <div class="form-group">
        <label asp-for="Birthday" class="control-label"></label>
        <input asp-for="Birthday" class="form-control" type="date" /> <!-- type="date" 追加 -->
        <span asp-validation-for="Birthday" class="text-danger"></span>
      </div>
      @* 更新日時は入力しないのでコメントアウト *@
      @*
      <div class="form-group">
        <label asp-for="UpdateDateTime" class="control-label"></label>
        <input asp-for="UpdateDateTime" class="form-control "/>
        <span asp-validation-for="UpdateDateTime" class="text-danger"></span>
      </div>
      *@
      <div class="form-group">
        <input type="submit" value="Create" class="btn btn-primary" />
      </div>
    </form>
  </div>
</div>

<div>
    <a asp-action="List">Back to List</a>  <!-- List に遷移するように変更 -->
</div>

@section Scripts {
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

运行它并检查它。 顺便说一下,由于没有安全措施,如密码注册,在操作时,请遵循 ASP.NET Core 和数据库注册技术。

当然,它反映在数据库中。

由于此提示不创建编辑或删除过程,因此列表右侧的"编辑| Details | 如果单击"删除",则会发生错误。 您可以像创建一样创建它,因此请尝试它。 示例代码还包含上述三个过程。

从 RequestServices 获取数据库上下文

在 DI 中添加到控制器构造函数时,这有点麻烦,因为必须添加所有必要的控制器。 另一种方法是 RequestServices 从 中获取它。

它不包括在示例代码中,但可以按如下方式获取:

/// <summary>
/// ユーザー一覧表示アクション。
/// </summary>
public IActionResult List()
{
  // RequestServices からデータベースコンテキストを取得する
  var dbContext = (TestDatabaseDbContext)HttpContext.RequestServices.GetService(typeof(TestDatabaseDbContext));
  
  // データベースから User 一覧を取得する
  var users = dbContext.Users.ToList();
  
  // ビューに渡す
  return View(users);
}

直接创建数据库上下文

该技术也用于控制台和桌面应用。 这可以毫无问题地使用。 不建议这样做,因为在具有大量并发访问的 Web 应用程序中,事务范围很容易变得模糊不清。 特别是,更新系统可能无法回滚到请求单位。

以这种方式访问数据库时, DbContext 将使用派生 的技术。

首先 Startup Configuration ,修改 static 它,以便 可以处理 在 中。

public class Startup
{
  public Startup(IConfiguration configuration)
  {
    Configuration = configuration;
    ConfigurationStatic = configuration;  // 追加
  }
  
  public IConfiguration Configuration { get; }
  public static IConfiguration ConfigurationStatic { get; private set; }  // 追加

  // 省略
}

TestDatabaseDbContext 创建派生 TestDatabaseDbContextEx 的类,并设置 appsettings.json 的连接字符串。 如果可以设置连接字符串,则可以执行其他操作,例如通过构造函数传递连接字符串。

using Microsoft.Extensions.Configuration;
using Microsoft.EntityFrameworkCore;

namespace DatabaseEntityFrameworkCoreMvc.Models.Database
{
  public partial class TestDatabaseDbContextEx : TestDatabaseDbContext
  {
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
      if (!optionsBuilder.IsConfigured)
      {
        optionsBuilder.UseSqlServer(Startup.ConfigurationStatic.GetConnectionString("TestDatabaseDbContext"));
      }
    }
  }
}

如果要访问数据库,请生成和使用派生类的实例。

/// <summary>
/// ユーザー一覧表示アクション。
/// </summary>
public IActionResult List()
{
  // 派生クラスのデータベースコンテキストのインスタンスを生成する
  using var dbContext = new TestDatabaseDbContextEx();
  
  // データベースから User 一覧を取得する
  var users = dbContext.Users.ToList();
  
  // ビューに渡す
  return View(users);
}

ASP.NET Core Razor 页面上的示例

ASP.NET 在 Core Razor 页面上使用实体框架 Core 的方法有很多种。

使用 DI(依赖项插入)添加到页面模型

通过.cs services.AddDbContext Startup TestDatabaseDbContext 方法注册 可以插入到页面模型中。

DI 的一 IndexModel 个示例是 构造函数作为 ILogger<IndexModel> logger 参数。 这是 DI 添加的内容。 也可以 TestDatabaseDbContext 以同样的方式插入 。

如果要 IndexModel 将现有 添加到 : 当然,它也可以添加到其他页面模型中。

using DatabaseEntityFrameworkCoreMvc.Models.Database;  // 追加

// 省略

public class IndexModel : PageModel
{
  private readonly ILogger<IndexModel> _logger;
  
  // 追加
  private readonly TestDatabaseDbContext _dbContext;
  
  public IndexModel(ILogger<IndexModel> logger, TestDatabaseDbContext dbContext)  // 追加
  {
    _logger = logger;
    _dbContext = dbContext;  // 追加
  }
  
  // 省略
}

然后,通过在每个操作中使用收到的上下文的实例来访问数据库。

使用示例

以下代码处理用户列表和新注册。 两 ASP.NET Core 和实体框架 Core 中的代码,因此省略了详细说明。 此外,当用户的请求结束时,上下文将自动销毁。

为列表屏幕创建页面模型。

将 List.cshtml.cs 如下所示:

using System.Collections.Generic;
using System.Linq;
using DatabaseEntityFrameworkCoreRazor.Models.Database;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace DatabaseEntityFrameworkCoreRazor.Pages
{
  public class ListModel : PageModel
  {
    private readonly TestDatabaseDbContext _dbContext;
    
    /// <summary>
    /// 一覧に表示するためのユーザー一覧を格納します。
    /// </summary>
    public List<User> Users { get; set; }
    
    /// <summary>
    /// DI で TestDatabaseDbContext を受け取ります。
    /// </summary>
    /// <param name="dbContext"></param>
    public ListModel(TestDatabaseDbContext dbContext)
    {
      _dbContext = dbContext;
    }
    
    /// <summary>
    /// ページにアクセスされたときに呼ばれます。
    /// </summary>
    public void OnGet()
    {
      // データベースからユーザー一覧を取得します。
      Users = _dbContext.Users.ToList();
    }
  }
}

创建 List.cshtml, 如下所示:

@page
@model DatabaseEntityFrameworkCoreRazor.Pages.ListModel
@{
}

<h1>List</h1>

<p>
  <a asp-page="Create">Create New</a>
</p>
<table class="table">
  <thead>
    <tr>
      <th>
        @Html.DisplayNameFor(model => model.Users[0].ID)
      </th>
      <th>
        @Html.DisplayNameFor(model => model.Users[0].Name)
      </th>
      <th>
        @Html.DisplayNameFor(model => model.Users[0].Password)
      </th>
      <th>
        @Html.DisplayNameFor(model => model.Users[0].Age)
      </th>
      <th>
        @Html.DisplayNameFor(model => model.Users[0].Email)
      </th>
      <th>
        @Html.DisplayNameFor(model => model.Users[0].Birthday)
      </th>
      <th>
        @Html.DisplayNameFor(model => model.Users[0].UpdateDateTime)
      </th>
      <th></th>
    </tr>
  </thead>
  <tbody>
    @foreach (var item in Model.Users)
    {
      <tr>
        <td>
          @Html.DisplayFor(modelItem => item.ID)
        </td>
        <td>
          @Html.DisplayFor(modelItem => item.Name)
        </td>
        <td>
          @Html.DisplayFor(modelItem => item.Password)
        </td>
        <td>
          @Html.DisplayFor(modelItem => item.Age)
        </td>
        <td>
          @Html.DisplayFor(modelItem => item.Email)
        </td>
        <td>
          @Html.DisplayFor(modelItem => item.Birthday)
        </td>
        <td>
          @Html.DisplayFor(modelItem => item.UpdateDateTime)
        </td>
        <td>
          <a asp-page="./Edit" asp-route-id="@item.ID">Edit</a> |
          <a asp-page="./Details" asp-route-id="@item.ID">Details</a> |
          <a asp-page="./Delete" asp-route-id="@item.ID">Delete</a>
        </td>
      </tr>
    }
  </tbody>
</table>

Index.cshtml 中添加,以便 可以转到 List 页。

<!-- 追加 -->
<ul>
  <li><a asp-page="List">List</a></li>
</ul>

创建用户注册屏幕。

在 Create.cshtml .cs 代码,如下所示:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using DatabaseEntityFrameworkCoreRazor.Models.Database;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace DatabaseEntityFrameworkCoreRazor.Pages
{
  public class CreateModel : PageModel
  {
    private readonly TestDatabaseDbContext _dbContext;

    /// <summary>
    /// 登録するユーザー情報を格納します。
    /// </summary>
    [BindProperty]
    public User UserInfo { get; set; }

    /// <summary>
    /// DI で TestDatabaseDbContext を受け取ります。
    /// </summary>
    /// <param name="dbContext"></param>
    public CreateModel(TestDatabaseDbContext dbContext)
    {
      _dbContext = dbContext;
    }

    /// <summary>
    /// ページにアクセスされたときに呼ばれます。
    /// </summary>
    public void OnGet()
    {
      // 画面表示時は何もしません。
    }

    /// <summary>
    /// POST が送信されたときに呼ばれる。
    /// </summary>
    public IActionResult OnPost()
    {
      // エラーがある場合は登録画面に戻る
      if (ModelState.IsValid == false) return Page();

      // 更新日時設定
      UserInfo.UpdateDateTime = DateTime.Now;

      // 登録リストにユーザー追加
      _dbContext.Users.Add(UserInfo);

      // 登録を確定する
      _dbContext.SaveChanges();

      // 一覧画面に遷移
      return RedirectToPage("List");
    }
  }
}

创建 Create.cshtml, 如下所示:

@page
@model DatabaseEntityFrameworkCoreRazor.Pages.CreateModel
@{
}

<h1>Create</h1>

<h4>User</h4>
<hr />
<div class="row">
  <div class="col-md-4">
    <form asp-action="Create">
      <div asp-validation-summary="ModelOnly" class="text-danger"></div>
      <div class="form-group">
        <label asp-for="UserInfo.ID" class="control-label"></label>
        <input asp-for="UserInfo.ID" class="form-control" />
        <span asp-validation-for="UserInfo.ID" class="text-danger"></span>
      </div>
      <div class="form-group">
        <label asp-for="UserInfo.Name" class="control-label"></label>
        <input asp-for="UserInfo.Name" class="form-control" />
        <span asp-validation-for="UserInfo.Name" class="text-danger"></span>
      </div>
      <div class="form-group">
        <label asp-for="UserInfo.Password" class="control-label"></label>
        <input asp-for="UserInfo.Password" class="form-control" type="password" />
        <span asp-validation-for="UserInfo.Password" class="text-danger"></span>
      </div>
      <div class="form-group">
        <label asp-for="UserInfo.Age" class="control-label"></label>
        <input asp-for="UserInfo.Age" class="form-control" />
        <span asp-validation-for="UserInfo.Age" class="text-danger"></span>
      </div>
      <div class="form-group">
        <label asp-for="UserInfo.Email" class="control-label"></label>
        <input asp-for="UserInfo.Email" class="form-control" />
        <span asp-validation-for="UserInfo.Email" class="text-danger"></span>
      </div>
      <div class="form-group">
        <label asp-for="UserInfo.Birthday" class="control-label"></label>
        <input asp-for="UserInfo.Birthday" class="form-control" type="date" />
        <span asp-validation-for="UserInfo.Birthday" class="text-danger"></span>
      </div>
      @*
        <div class="form-group">
          <label asp-for="UpdateDateTime" class="control-label"></label>
          <input asp-for="UpdateDateTime" class="form-control" />
          <span asp-validation-for="UpdateDateTime" class="text-danger"></span>
        </div>
      *@
      <div class="form-group">
        <input type="submit" value="Create" class="btn btn-primary" />
      </div>
    </form>
  </div>
</div>

<div>
  <a asp-page="List">Back to List</a>
</div>

运行它并检查它。 顺便说一下,由于没有安全措施,如密码注册,在操作时,请遵循 ASP.NET Core 和数据库注册技术。

当然,它反映在数据库中。

由于您尚未创建编辑或删除过程,因此列表右侧的"编辑| Details | 如果单击"删除",则会发生错误。 您可以像创建一样创建它,因此请尝试它。 示例代码还包含上述三个过程。

从 RequestServices 获取数据库上下文

在 DI 中添加到页面模型的构造函数时,这有点麻烦,因为必须添加所有必要的页面模型。 另一种方法是 RequestServices 从 中获取它。

它不包括在示例代码中,但可以按如下方式获取:

/// <summary>
/// ページにアクセスされたときに呼ばれます。
/// </summary>
public void OnGet()
{
  // RequestServices からデータベースコンテキストを取得する
  var dbContext = (TestDatabaseDbContext)HttpContext.RequestServices.GetService(typeof(TestDatabaseDbContext));
  
  // データベースからユーザー一覧を取得します。
  Users = dbContext.Users.ToList();
}

直接创建数据库上下文

该技术也用于控制台和桌面应用。 这可以毫无问题地使用。 不建议这样做,因为在具有大量并发访问的 Web 应用程序中,事务范围很容易变得模糊不清。 特别是,更新系统可能无法回滚到请求单位。

以这种方式访问数据库时, DbContext 将使用派生 的技术。

首先 Startup Configuration ,修改 static 它,以便 可以处理 在 中。

public class Startup
{
  public Startup(IConfiguration configuration)
  {
    Configuration = configuration;
    ConfigurationStatic = configuration;  // 追加
  }
  
  public IConfiguration Configuration { get; }
  public static IConfiguration ConfigurationStatic { get; private set; }  // 追加

  // 省略
}

TestDatabaseDbContext 创建派生 TestDatabaseDbContextEx 的类,并设置 appsettings.json 的连接字符串。 如果可以设置连接字符串,则可以执行其他操作,例如通过构造函数传递连接字符串。

using Microsoft.Extensions.Configuration;
using Microsoft.EntityFrameworkCore;

namespace DatabaseEntityFrameworkCoreRazor.Models.Database
{
  public partial class TestDatabaseDbContextEx : TestDatabaseDbContext
  {
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
      if (!optionsBuilder.IsConfigured)
      {
        optionsBuilder.UseSqlServer(Startup.ConfigurationStatic.GetConnectionString("TestDatabaseDbContext"));
      }
    }
  }
}

如果要访问数据库,请生成和使用派生类的实例。

/// <summary>
/// ページにアクセスされたときに呼ばれます。
/// </summary>
public void OnGet()
{
  // 派生クラスのデータベースコンテキストのインスタンスを生成する
  using var dbContext = new TestDatabaseDbContextEx();
    
  // データベースからユーザー一覧を取得します。
  Users = dbContext.Users.ToList();
}