ASP.NET Core Razor Pages 使用 EntityFramework Core 和枚举字符串 - 第二部分





5.00/5 (4投票s)
完成初始 CRUD 页面
引言
这是多部分文章的第二部分,演示了如何通过 EntityFramework Core 2.1 (EF) 将 C# enum 值映射到数据库表中的 string 值。它在 ASP.NET Core Razor Page 应用程序的上下文中,解决了 enum 值与应用程序实体之间的一对多和多对多关系映射问题。
EF 是一个对象关系映射器 (ORM)。在这样的应用程序中,存在两个“世界”。一个是以 C# 对象模型形式存在的对象世界。另一个是存在于关系数据库(如 Microsoft SQL Server)中的关系世界。这两个世界并不一致。ORM(如 EntityFramework)的功能是连接这两个世界,并促进它们之间的数据传输。
第一部分:我们创建了初始对象模型、Entity Framework 数据上下文和数据库,并显示了第一个 Customers Razor Page。这是所有已定义 Customers 的 Customer 的读取功能 (CRUD)。
在第二部分中,我们将完成并测试 Customer CRUD Razor Pages。
- 实现并测试 Customer 创建 Razor Page,Customers\Create.cshtml。这是 CustomerCRUD 的Create功能。
- 在 Customers\Details.cshtml Razor Page 中,实现 Customer详情的显示,这是通过其CustomerId属性标识的单个Customer的Read功能的实现。
- 在 Customers\Edit.cshtml Razor Page 中,实现 Customer属性的编辑,这是CustomerCRUD 的Update功能。
- 最后,在 Customers\Delete.cshtml Razor Page 中实现 CustomerCRUD 的Delete功能。
在第三部分,我们将 创建 Project 和 ProjectState 实体,并实现 ProjectState 和 Projects 之间的一对多关系。
在第四部分,我们将 添加 Skill 实体 (Skill enum, SkillTitle 和 ProjectSkill),并实现 Projects 和 Skills 之间的多对多关系。
Using the Code
完成 Customers CRUD
此时,我们已经完成了对 Customers 表的基本读取。现在,我们将完成剩余的 Customer CRUD 功能。
Customer 创建
Pages\Customers\Create 文件处理在数据库中创建 Customer 记录。
生成的 Pages\Customers\Create.cshtml
@page
@model QuantumWeb.Pages.Customers.CreateModel
@{
    ViewData["Title"] = "Create";
}
<h2>Create</h2>
<h4>Customer</h4>
<hr />
<div class="row">
    <div class="col-md-4">
        <form method="post">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="form-group">
                <label asp-for="Customer.CustomerName" class="control-label"></label>
                <input asp-for="Customer.CustomerName" class="form-control" />
                <span asp-validation-for="Customer.CustomerName" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Customer.CustomerContact" class="control-label"></label>
                <input asp-for="Customer.CustomerContact" class="form-control" />
                <span asp-validation-for="Customer.CustomerContact" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Customer.CustomerPhone" class="control-label"></label>
                <input asp-for="Customer.CustomerPhone" class="form-control" />
                <span asp-validation-for="Customer.CustomerPhone" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Customer.CustomerEmail" class="control-label"></label>
                <input asp-for="Customer.CustomerEmail" class="form-control" />
                <span asp-validation-for="Customer.CustomerEmail" class="text-danger"></span>
            </div>
            <div class="form-group">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </form>
    </div>
</div>
<div>
    <a asp-page="Index">Back to List</a>
</div>
@section Scripts {
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
此文件包含一个 <form> 元素,用于将用户输入 POST 到服务器。
修改后的 Pages\Customers\Create.cshtml.cs
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using QuantumWeb.Data;
using QuantumWeb.Model;
namespace QuantumWeb.Pages.Customers
{
    public class CreateModel : PageModel
    {
        private readonly QuantumDbContext _context;
        public CreateModel(QuantumDbContext context)
        {
            _context = context;
        } // end public CreateModel(QuantumDbContext context)
        public IActionResult OnGet()
        {
            return Page();
        } // end public IActionResult OnGet()
        [BindProperty]
        public Customer Customer { get; set; }
        public async Task<IActionResult> OnPostAsync()
        {
            if (!ModelState.IsValid)
            {
                return Page();
            }
            _context.Customer.Add(Customer);
            await _context.SaveChangesAsync();
            return RedirectToPage("./Index");
        } // end public async Task<IActionResult> OnPostAsync()
    } // end public class CreateModel : PageModel
} // end namespace QuantumWeb.Pages.Customers
可以通过点击 Customers 页上的“Create New”链接来访问 Customers/Create 页面。
QuantumWeb 应用程序 Customers 页面:https//: 44306/Customers

在 **Customer Create** 页面输入第一个 Customer 的数据,然后点击“Create”。
QuantumWeb 应用程序 Customers 页面:https//: 44306/Customers/Create

QuantumWeb 应用程序 Customers 页面:https//: 44306/Customers (包含第 1 个 Customer)

添加另外两个 Customers 后,我们显示 Customer 页面。
QuantumWeb 应用程序 Customers 页面:https//: 44306/Customers - 3 个 Customers

通过点击 customer "Polyolefin Processing, Inc." 的“Details”链接,我们可以显示其详情。接下来是 Customers\Details.cshtml 和 Customers\Details.cshtml.cs 文件的列表。
显示 Customer 详情
生成的 Pages\Customers\Details.cshtml
@page
@model QuantumWeb.Pages.Customers.DetailsModel
@{
    ViewData["Title"] = "Details";
}
<h2>Details</h2>
<div>
    <h4>Customer</h4>
    <hr />
    <dl class="dl-horizontal">
        <dt>
            @Html.DisplayNameFor(model => model.Customer.CustomerName)
        </dt>
        <dd>
            @Html.DisplayFor(model => model.Customer.CustomerName)
        </dd>
        <dt>
            @Html.DisplayNameFor(model => model.Customer.CustomerContact)
        </dt>
        <dd>
            @Html.DisplayFor(model => model.Customer.CustomerContact)
        </dd>
        <dt>
            @Html.DisplayNameFor(model => model.Customer.CustomerPhone)
        </dt>
        <dd>
            @Html.DisplayFor(model => model.Customer.CustomerPhone)
        </dd>
        <dt>
            @Html.DisplayNameFor(model => model.Customer.CustomerEmail)
        </dt>
        <dd>
            @Html.DisplayFor(model => model.Customer.CustomerEmail)
        </dd>
    </dl>
</div>
<div>
    <a asp-page="./Edit" asp-route-id="@Model.Customer.CustomerId">Edit</a> |
    <a asp-page="./Index">Back to List</a>
</div>
修改后的 Pages\Customers\Details.cshtml.cs
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using QuantumWeb.Data;
using QuantumWeb.Model;
namespace QuantumWeb.Pages.Customers
{
    public class DetailsModel : PageModel
    {
        private readonly QuantumDbContext _context;
        public DetailsModel(QuantumDbContext context)
        {
            _context = context;
        } // end public DetailsModel(QuantumDbContext context)
        public Customer Customer { get; set; }
        public async Task<IActionResult> OnGetAsync(int? id)
        {
            if (id == null)
            {
                return NotFound();
            } // end if (id == null)
            Customer = await _context.Customer.FirstOrDefaultAsync(m => m.CustomerId == id);
            if (Customer == null)
            {
                return NotFound();
            } // endif (Customer == null)
            return Page();
        } // end public async Task<IActionResult> OnGetAsync(int? id)
    } // end public class DetailsModel : PageModel
} // end namespace QuantumWeb.Pages.Customers
QuantumWeb 应用程序 Customer Details 页面:https//: 44306/Customers/Details?id=2

QuantumWeb 应用程序 Customers 页面:https//: 44306/Customers - 3 个 Customers

通过点击 customer "Pascagoula Petrochemicals" 的“Edit”链接,我们可以编辑该客户的记录。接下来是 Customers\Edit.cshtml 和 Customers\Edit.cshtml.cs 文件的列表。
编辑 Customer 信息
生成的 Pages\Customers\Edit.cshtml
@page
@model QuantumWeb.Pages.Customers.EditModel
@{
    ViewData["Title"] = "Edit";
}
<h2>Edit</h2>
<h4>Customer</h4>
<hr />
<div class="row">
    <div class="col-md-4">
        <form method="post">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <input type="hidden" asp-for="Customer.CustomerId" />
            <div class="form-group">
                <label asp-for="Customer.CustomerName" class="control-label"></label>
                <input asp-for="Customer.CustomerName" class="form-control" />
                <span asp-validation-for="Customer.CustomerName" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Customer.CustomerContact" class="control-label"></label>
                <input asp-for="Customer.CustomerContact" class="form-control" />
                <span asp-validation-for="Customer.CustomerContact" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Customer.CustomerPhone" class="control-label"></label>
                <input asp-for="Customer.CustomerPhone" class="form-control" />
                <span asp-validation-for="Customer.CustomerPhone" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Customer.CustomerEmail" class="control-label"></label>
                <input asp-for="Customer.CustomerEmail" class="form-control" />
                <span asp-validation-for="Customer.CustomerEmail" class="text-danger"></span>
            </div>
            <div class="form-group">
                <input type="submit" value="Save" class="btn btn-default" />
            </div>
        </form>
    </div>
</div>
<div>
    <a asp-page="./Index">Back to List</a>
</div>
@section Scripts {
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
修改后的 Pages\Customers\Edit.cshtml.cs
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using QuantumWeb.Data;
using QuantumWeb.Model;
namespace QuantumWeb.Pages.Customers
{
    public class EditModel : PageModel
    {
        private readonly QuantumDbContext _context;
        public EditModel(QuantumDbContext context)
        {
            _context = context;
        } // end public EditModel(QuantumDbContext context)
        [BindProperty]
        public Customer Customer { get; set; }
        public async Task<IActionResult> OnGetAsync(int? id)
        {
            if (id == null)
            {
                return NotFound();
            } // endif (id == null)
            Customer = await _context.Customer.FirstOrDefaultAsync(m => m.CustomerId == id);
            if (Customer == null)
            {
                return NotFound();
            } // endif (Customer == null)
            return Page();
        } // end public async Task<IActionResult> OnGetAsync(int? id)
        public async Task<IActionResult> OnPostAsync()
        {
            if (!ModelState.IsValid)
            {
                return Page();
            } // endif (!ModelState.IsValid)
            _context.Attach(Customer).State = EntityState.Modified;
            try
            {
                await _context.SaveChangesAsync();
            } // end try
            catch (DbUpdateConcurrencyException)
            {
                if (!CustomerExists(Customer.CustomerId))
                {
                    return NotFound();
                }
                else
                {
                    throw;
                } // endif (!CustomerExists(Customer.CustomerId))
            } // end catch (DbUpdateConcurrencyException)
            return RedirectToPage("./Index");
        } // end public async Task<IActionResult> OnPostAsync()
        private bool CustomerExists(int id)
        {
            return _context.Customer.Any(e => e.CustomerId == id);
        } // end private bool CustomerExists(int id)
    } // end public class EditModel : PageModel
} // end namespace QuantumWeb.Pages.Customers
QuantumWeb 应用程序 Customer Edit 页面:https//: 44306/Customers/Edit?id=3

我们更改所选 Customer 的值并保存更改。
QuantumWeb 应用程序 Customers 页面:https//: 44306/Customers - 修改后的 Customer

我们看到已编辑的值。现在,通过点击 Customer 的“Delete”链接,我们删除一个 Customer。接下来是 Customers\Delete.cshtml 和 Customers\Delete.cshtml.cs 文件的列表。
删除 Customer 记录
生成的 Pages\Customers\Delete.cshtml
@page
@model QuantumWeb.Pages.Customers.DeleteModel
@{
    ViewData["Title"] = "Delete";
}
<h2>Delete</h2>
<h3>Are you sure you want to delete this?</h3>
<div>
    <h4>Customer</h4>
    <hr />
    <dl class="dl-horizontal">
        <dt>
            @Html.DisplayNameFor(model => model.Customer.CustomerName)
        </dt>
        <dd>
            @Html.DisplayFor(model => model.Customer.CustomerName)
        </dd>
        <dt>
            @Html.DisplayNameFor(model => model.Customer.CustomerContact)
        </dt>
        <dd>
            @Html.DisplayFor(model => model.Customer.CustomerContact)
        </dd>
        <dt>
            @Html.DisplayNameFor(model => model.Customer.CustomerPhone)
        </dt>
        <dd>
            @Html.DisplayFor(model => model.Customer.CustomerPhone)
        </dd>
        <dt>
            @Html.DisplayNameFor(model => model.Customer.CustomerEmail)
        </dt>
        <dd>
            @Html.DisplayFor(model => model.Customer.CustomerEmail)
        </dd>
    </dl>
   
    <form method="post">
        <input type="hidden" asp-for="Customer.CustomerId" />
        <input type="submit" value="Delete" class="btn btn-default" /> |
        <a asp-page="./Index">Back to List</a>
    </form>
</div>
修改后的 Pages\Customers\Delete.cshtml.cs
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using QuantumWeb.Data;
using QuantumWeb.Model;
namespace QuantumWeb.Pages.Customers
{
    public class DeleteModel : PageModel
    {
        private readonly QuantumDbContext _context;
        public DeleteModel(QuantumDbContext context)
        {
            _context = context;
        } // end public DeleteModel(QuantumDbContext context)
        [BindProperty]
        public Customer Customer { get; set; }
        public async Task<IActionResult> OnGetAsync(int? id)
        {
            if (id == null)
            {
                return NotFound();
            } // endif (id == null)
            Customer = await _context.Customer.FirstOrDefaultAsync(m => m.CustomerId == id);
            if (Customer == null)
            {
                return NotFound();
            } // endif (Customer == null)
            return Page();
        } // end public async Task<IActionResult> OnGetAsync(int? id)
        public async Task<IActionResult> OnPostAsync(int? id)
        {
            if (id == null)
            {
                return NotFound();
            } // endif (id == null)
            Customer = await _context.Customer.FindAsync(id);
            if (Customer != null)
            {
                _context.Customer.Remove(Customer);
                await _context.SaveChangesAsync();
            } // endif (Customer != null)
            return RedirectToPage("./Index");
        } // end public async Task<IActionResult> OnPostAsync(int? id)
    } // end public class DeleteModel : PageModel
} // end namespace QuantumWeb.Pages.Customers
QuantumWeb 应用程序 Customer Delete 页面:https//: 44306/Customers/Delete?id=3

我们显示客户 "Pascagoula Petrochemicals, Ltd" 的详情,并提供通过点击“Delete”按钮来删除它的选项。
QuantumWeb 应用程序 Customers 页面:https//: 44306/Customers - 2 个 Customers

摘要
我们已经实现了 Customer CRUD ASP.NET Razor Pages。
关注点
在这篇第三部分的文章中,我们将定义 Project 和 ProjectState 实体 (Project, ProjectState 和 ProjectStateDescription),并实现 ProjectStates 和 Projects 之间的一对多关系。


