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.EntityFramework Core 為例安裝它,因此請以同樣的方式安裝其他兩個。

選擇要安裝的內容, 然後單擊 「安裝」 按鈕。 版本選擇最新的穩定器。

對話框基本上沒有問題,單擊"確定"。

請安裝另外兩個。

我認為包如下所示。

從資料庫的表組態建立模型(程式)

如果要在實體框架核心中從資料庫中檢索或更新數據,請使用 您需要編寫一個程式,該程式通常基於表配置進行建模。 此模型也稱為實體。

創建模型時,代碼優先是一種從模型(程式)創建 資料庫表 的技術。 資料庫優先是一種從表創建模型( 程式) 的技術。 本節介紹如何使用 易於執行 的資料庫優先表自動程式設計。

順便說一下 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 | 如果按兩下"刪除",則會發生錯誤。 您可以像創建一樣創建它,因此請嘗試它。 範例代碼還包含上述三個過程。

從 Request Services 獲取資料庫上下文

在 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 | 如果按兩下"刪除",則會發生錯誤。 您可以像創建一樣創建它,因此請嘗試它。 範例代碼還包含上述三個過程。

從 Request Services 獲取資料庫上下文

在 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();
}