EntityFramework Core和Enums作为字符串的ASP.NET核心Razor页面三

这是一篇由多部分组成的文章的第三部分,演示了通过EntityFramework Core 2.1(EF)将C#enum映射string数据库表中的值。它解决了enum与应用程序实体的一对多和多对多关系中映射问题它在ASP.NET Core Razor Page应用程序的上下文中执行此操作。

EF是对象关系映射器(ORM)。在诸如此示例的应用程序中,有两个“世界”。一个是在C#中作为对象模型存在的对象世界。另一个是存在于关系数据库中的关系世界,如Microsoft SQL Server。这两个世界并不一致。ORM的功能EntityFramework就是这两个世界之间的桥梁,并促进它们之间的数据传输。

第一部分设置实体框架数据上下文和初始Customer的Razor页面

第二部分完成了Customers的CRUD功能

第三部分我们将创建ProjectProjectState实体和实施一个一对多的关系之间ProjectState,并Project如下S:

第四部分添加技能实体(Skill enumSkillTitleProjectSkill)并在Projects之间实现多对多关系Skills

代码

添加初始项目处理。

接下来,我们启用Customer项目处理。该应用程序使用Customer“网关”实体; 一切都是通过CustomerCustomera之间存在一对多的关系Projects因此,我们需要修改Customer类。

修改后的Customer.cs

隐藏   收缩    复制代码

using System.Collections.Generic;namespace QuantumWeb.Model
{    /// <summary>    /// Customer Class    /// </summary>    public class Customer
    {        #region Constructors
        /// <summary>        /// Parameter-less Constructor        /// </summary>        /// <remarks>        /// Required for scaffolding the UI        /// </remarks>        public Customer()
        {
        } // end public Customer()

        #endregion // Constructors
        /// <summary>        /// Customer Identifier, primary key        /// </summary>        public int CustomerId { get; set; }        /// <summary>        /// Customer Name        /// </summary>        public string CustomerName { get; set; }        /// <summary>        /// Primary Customer Contact        /// </summary>        public string CustomerContact { get; set; }        /// <summary>        /// Customer Contact Phone Number        /// </summary>        public string CustomerPhone { get; set; }        /// <summary>        /// Customer Contact Email Address        /// </summary>        public string CustomerEmail { get; set; }        #region Navigation Properties
        /// <summary>        /// List of Projects        /// </summary>        public List<Project> Projects { get; set; }        #endregion // Navigation Properties
    } // end public class Customer} // end namespace QuantumWeb.Model

我们添加了一个项目列表(上面加粗)。在这里,我们将某些属性标识为导航属性。这些属性引用其他类/实体,以便我们可以在处理中导航到它们。CustomerProjects列表中表示零或多个Projects。初始Project类定义如下。

初始Project.cs

隐藏   收缩    复制代码

namespace QuantumWeb.Model
{    /// <summary>    /// Project Class    /// </summary>    public class Project
    {        /// <summary>        /// Project Identifier, primary key        /// </summary>        public int ProjectId { get; set; }        /// <summary>        /// Project Name        /// </summary>        public string ProjectName { get; set; }        #region Navigation Properties
        /// <summary>        /// Customer Identifier        /// </summary>        public int CustomerId { get; set; }        /// <summary>        /// Customer        /// </summary>        /// <remarks>        /// Every Project has a Customer        /// </remarks>        public Customer Customer { get; set; }        /// <summary>        /// Project Status Code        /// </summary>        public ProjectState ProjectStateCode { get; set; }        /// <summary>        /// ProjectStateDescription Reference        /// </summary>        public ProjectStateDescription ProjectStateDescription { get; set; }        #endregion // Navigation Properties
    } // end public class Project} // end namespace QuantumApp.Model

除了定义初始Project类之外,我们还将ProjectState enumModel文件夹中定义它

ProjectState.cs

隐藏   复制代码

namespace QuantumWeb.Model
{   
    /// <summary>    /// Project State Enumeration    /// </summary>    public enum ProjectState
    {
        Prospect,
        UnderReview,
        StartScheduled,
        InProgress,
        Completed
    } // end public enum ProjectState} // end namespace QuantumWeb.Model

enum指定了Project工作流的状态

如前所述,我们对此应用程序有两个目标。

  1. 我们应该为Project将在UI中显示的每个状态定义简短描述,以帮助用户理解每个状态的含义。

  2. 每个enum值都作为a存储在数据库中string

为了满足这些要求ProjectState enum,我们定义了ProjectStateDescription类。

ProjectStateDescription.cs

隐藏   收缩    复制代码

using System.Collections.Generic;namespace QuantumWeb.Model
{    /// <summary>    /// Project State Description Class    /// </summary>    public class ProjectStateDescription
    {        /// <summary>        /// ProjectState Code        /// </summary>        public ProjectState ProjectStateCode { get; set; }        /// <summary>        /// State Description        /// </summary>        public string StateDescription { get; set; }        #region Navigation Properties
        /// <summary>        /// Projects Collection        /// </summary>        public List<Project> Projects { get; set; }        #endregion // Navigation Properties
    } // end public class ProjectStateDescription} // end namespace QuantumWeb.Model

ProjectStateProjects一个一对多的关系,通过导航属性启用。每个Project都有一个ProjectStateDesciption每个ProjectStateDescripton都有一个集合Projects

接下来,我们需要定义EF配置类,ProjectProjectStateDescriptionQuantumDbContext类中包含所有内容所有此活动都发生在Data文件夹中。

初始ProjectConfiguration.cs

隐藏   收缩    复制代码

using System;using Microsoft.EntityFrameworkCore;using Microsoft.EntityFrameworkCore.Metadata.Builders;using QuantumWeb.Model;namespace QuantumWeb.Data
{    public class ProjectConfiguration : IEntityTypeConfiguration<Project>
    {        public void Configure(EntityTypeBuilder<Project> builder)
        {
            builder.ToTable("Projects");
            builder.HasKey(p => p.ProjectId);
            builder.Property(p => p.ProjectId)
            .HasColumnType("int");
            builder.Property(p => p.ProjectName)
            .IsRequired()
            .HasColumnType("nvarchar(80)")
            .HasMaxLength(80);
            builder.Property(p => p.CustomerId)
            .HasColumnType("int")
            .IsRequired();
            builder.HasOne(p => p.Customer)
            .WithMany(c => c.Projects)
            .HasForeignKey(p => p.CustomerId)
            .IsRequired();
            builder.Property(p => p.ProjectStateCode)
            .HasColumnType("nvarchar(15)")
            .HasDefaultValue(ProjectState.Prospect)
            .HasConversion(
                p => p.ToString(),
                p => (ProjectState)Enum.Parse(typeof(ProjectState), p));
            builder.HasOne(p => p.ProjectStateDescription)
            .WithMany(pd => pd.Projects)
            .HasForeignKey(p => p.ProjectStateCode);
        } // end public void Configure(EntityTypeBuilder<Project> builder)

    } // end public class ProjectConfiguration : IEntityTypeConfiguration<Project>} // end namespace QuantumWeb.Data

看看下面提取的行:

隐藏   复制代码

builder.HasOne(p => p.Customer)
.WithMany(c => c.Projects)
.HasForeignKey(p => p.CustomerId)
.IsRequired();

对这些行的解释是,“每个Project都有一个Customer有许多Projects。每个都Project映射到Projects数据库中表与外键CustomerId,并且是必需的。因此,CustomerProject关系是一对多。

在一个一对多ProjectStateDescriptionProject关系被配置为通过:

隐藏   复制代码

builder.HasOne(p => p.ProjectStateDescription)
.WithMany(pd => pd.Projects)
.HasForeignKey(p => p.ProjectStateCode);

接下来,我们将了解处理enum数据库string配置的方式。

隐藏   复制代码

builder.Property(p => p.ProjectStateCode)
.HasColumnType("nvarchar(15)")
.HasDefaultValue(ProjectState.Prospect)
.HasConversion(
    p => p.ToString(),
    p => (ProjectState)Enum.Parse(typeof(ProjectState), p));

这些行首先nvarchar(15)Projects名为表中配置一个ProjectStateCode,其默认值取自ProjectState.Prospect接下来,定义ProjectState值和string之间的转换将值从移动ProjectState enumProjects表时,将使用该ToString()函数转换值转换另一种方式时,string表中值将被解析为一个enum值。始终使用相同的方案在数据库列中的enum值和string之间进行转换

ProjectStateDescriptionConfiguration类如下所示。

ProjectStateDescriptionConfiguration.cs

隐藏   收缩    复制代码

using System;using Microsoft.EntityFrameworkCore;using Microsoft.EntityFrameworkCore.Metadata.Builders;using QuantumWeb.Model;namespace QuantumWeb.Data
{    /// <summary>    /// ProjectState Description Configuration Class    /// </summary>    public class ProjectStateDescriptionConfiguration : 
                   IEntityTypeConfiguration<ProjectStateDescription>
    {        public void Configure(EntityTypeBuilder<ProjectStateDescription> builder)
        {
            builder.ToTable("ProjectStateDescriptions");
            builder.HasKey(p => p.ProjectStateCode);
            builder.Property(p => p.ProjectStateCode)
            .HasColumnType("nvarchar(15)")
            .HasConversion(
                p => p.ToString(),
                p => (ProjectState)Enum.Parse(typeof(ProjectState), p));
            builder.Property(p => p.StateDescription)
            .IsRequired()
            .HasColumnType("nvarchar(80)")
            .HasMaxLength(80);
        } // end public void Configure(EntityTypeBuilder<ProjectStateDescription> builder)

    } // end public class ProjectStateDescriptionConfiguration : 
      // IEntityTypeConfiguration<ProjectStateDescription>} // end namespace QuantumWeb.Data

现在,我们更新QuantumDbContext课程。

QuantumDbContext.cs的第二次更新

隐藏   收缩    复制代码

using Microsoft.EntityFrameworkCore;using QuantumWeb.Model;namespace QuantumWeb.Data
{    public class QuantumDbContext : DbContext
    {        public QuantumDbContext (DbContextOptions<QuantumDbContext> options)
            : base(options)
        {
        } // end public QuantumDbContext (DbContextOptions<QuantumDbContext> options)

        #region DbSets
        /// <summary>        /// Customer DbSet        /// </summary>        public DbSet<Customer> Customers { get; set; }        /// <summary>        /// Project DbSet        /// </summary>        public DbSet<Project> Projects { get; set; }        /// <summary>        /// ProjectStateDescription DbSet        /// </summary>        public DbSet<ProjectStateDescription> ProjectStateDescriptions { get; set; }        #endregion // DbSets
        /// <summary>        /// Data Model Creation Method        /// </summary>        /// <param name="modelBuilder">ModelBuilder instance</param>        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.ApplyConfiguration(new CustomerConfiguration());
            modelBuilder.ApplyConfiguration(new ProjectConfiguration());
            modelBuilder.ApplyConfiguration(new ProjectStateDescriptionConfiguration());
        } // end  protected override void OnModelCreating(ModelBuilder modelBuilder)

    } // end public class QuantumDbContext : DbContext} // end namespace QuantumWeb.Data

添加的行以粗体显示。现在为ProjectProjectState实体添加EF迁移

隐藏   复制代码

Add-Migration Added-Project-ProjectState

生成〜\ Migrations \ 20181021203503_Added-Project-ProjectState.cs

隐藏   收缩    复制代码

using Microsoft.EntityFrameworkCore.Metadata;using Microsoft.EntityFrameworkCore.Migrations;namespace QuantumWeb.Migrations
{    public partial class AddedProjectProjectState : Migration
    {        protected override void Up(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.CreateTable(
                name: "ProjectStateDescriptions",
                columns: table => new
                {
                    ProjectStateCode = 
                    table.Column<string>(type: "nvarchar(15)", nullable: false),
                    StateDescription = 
                    table.Column<string>(type: "nvarchar(80)", maxLength: 80, nullable: false)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_ProjectStateDescriptions", x => x.ProjectStateCode);
                });

            migrationBuilder.CreateTable(
                name: "Projects",
                columns: table => new
                {
                    ProjectId = table.Column<int>(type: "int", nullable: false)
                        .Annotation("SqlServer:ValueGenerationStrategy", 
                        SqlServerValueGenerationStrategy.IdentityColumn),
                    ProjectName = table.Column<string>(type: "nvarchar(80)", 
                                  maxLength: 80, nullable: false),
                    CustomerId = table.Column<int>(type: "int", nullable: false),
                    ProjectStateCode = table.Column<string>
                    (type: "nvarchar(15)", nullable: false, defaultValue: "Prospect")
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_Projects", x => x.ProjectId);
                    table.ForeignKey(
                        name: "FK_Projects_Customers_CustomerId",
                        column: x => x.CustomerId,
                        principalTable: "Customers",
                        principalColumn: "CustomerId",
                        onDelete: ReferentialAction.Cascade);
                    table.ForeignKey(
                        name: "FK_Projects_ProjectStateDescriptions_ProjectStateCode",
                        column: x => x.ProjectStateCode,
                        principalTable: "ProjectStateDescriptions",
                        principalColumn: "ProjectStateCode",
                        onDelete: ReferentialAction.Cascade);
                });

            migrationBuilder.CreateIndex(
                name: "IX_Projects_CustomerId",
                table: "Projects",
                column: "CustomerId");

            migrationBuilder.CreateIndex(
                name: "IX_Projects_ProjectStateCode",
                table: "Projects",
                column: "ProjectStateCode");
        }        protected override void Down(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.DropTable(
                name: "Projects");

            migrationBuilder.DropTable(
                name: "ProjectStateDescriptions");
        }
    }
}

UpdateDatabase命令之后,SQL Server Management Studio(SSMS)中的数据库图如下所示。

QuantumDbContext数据库图表CustomerProjectProjectState表格:

修改剃刀页ProjectProjectState

我们需要为项目的应用程序添加一些自定义客户剃刀页面。首先,我们需要添加一个指向Customer / Index页面的链接CustomerProjects

添加CustomerProjects 指向Pages \ Customers \ Index.cshtml的链接

隐藏   收缩    复制代码

@page
@model QuantumWeb.Pages.Customers.IndexModel

@{
    ViewData["Title"] = "Index";
}<h2>Index</h2><p>
    <a asp-page="Create">Create New</a>
    <!-- A link to the Pages/Customers/Create page to create a new Customer --></p><!-- An HTML table to display existing Customers --><table class="table">
    <thead>
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.Customer[0].CustomerName)            </th>
            <th>
                @Html.DisplayNameFor(model => model.Customer[0].CustomerContact)            </th>
            <th>
                @Html.DisplayNameFor(model => model.Customer[0].CustomerPhone)            </th>
            <th>
                @Html.DisplayNameFor(model => model.Customer[0].CustomerEmail)            </th>
            <th></th>
        </tr>
    </thead>
    <tbody>@foreach (var item in Model.Customer) {        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.CustomerName)            </td>
            <td>
                @Html.DisplayFor(modelItem => item.CustomerContact)            </td>
            <td>
                @Html.DisplayFor(modelItem => item.CustomerPhone)            </td>
            <td>
                @Html.DisplayFor(modelItem => item.CustomerEmail)            </td>
            <td>
                <a asp-page="./Edit" asp-route-id="@item.CustomerId">Edit</a> |                <!-- A link to the Pages/Customers/Edit page to edit an existing Customer -->
                <a asp-page="./Details" asp-route-id="@item.CustomerId">Details</a> |                <!--
                   A link to the Pages/Customers/Details page to display the details for an existing
                   Customer                -->
                <a asp-page="./CustomerProjects" asp-route-id="@item.CustomerId">Projects</a> |                <!--
                    A link to the Pages/Customers/CustomerProjects page to display & manage the
                    Projects for an existing Customer                -->
                <a asp-page="./Delete" asp-route-id="@item.CustomerId">Delete</a>
                <!-- A link to the Pages/Customers/Delete page to delete an existing Customer -->
            </td>
        </tr>}    </tbody></table>

我们将Customers如下构建几个自定义Razor页面。

为客户设计的定制脚手架Razor页面:

脚手架客户/客户项目剃刀页面:

单击“ 添加 ”将为CustomerProjects索引页面生成shell文件

生成~Pages \ Customers \ CustomerProjects.cshtml

隐藏   复制代码

@page
@model QuantumWeb.Pages.Customers.CustomerProjectsModel
@{
    ViewData["Title"] = "CustomerProjects";
}<h2>CustomerProjects</h2>
生成~Pages \ Customers \ CustomerProjects.cshtml.cs

隐藏   复制代码

using System;using System.Collections.Generic;using System.Linq;using System.Threading.Tasks;using Microsoft.AspNetCore.Mvc;using Microsoft.AspNetCore.Mvc.RazorPages;namespace QuantumWeb.Pages.Customers
{    public class CustomerProjectsModel : PageModel
    {        public void OnGet()
        {

        }
    }
}

我们将在每种情况下修改这些shell文件以满足我们的需求。CustomerProjects索引页面的修改文件是。

修改了~Pages \ Customers \ CustomerProjects.cshtml

隐藏   收缩    复制代码

@page "{id:int?}"
@model QuantumWeb.Pages.Customers.CustomerProjectsModel
@{
    ViewData["Title"] = "Customer Projects";
}<h2>Customer Projects</h2><div>
    <h4>Customer</h4>
    <hr />
    <dl class="dl-horizontal">
        <dt>
            @Html.DisplayNameFor(model => model.Customer.CustomerId)        </dt>
        <dd>
            @Html.DisplayFor(model => model.Customer.CustomerId)        </dd>
        <dt>
            @Html.DisplayNameFor(model => model.Customer.CustomerName)        </dt>
        <dd>
            @Html.DisplayFor(model => model.Customer.CustomerName)        </dd>
        <dt>
            @Html.DisplayNameFor(model => model.Customer.Projects)        </dt>
        <dd>
            <table class="table">
                <tr>
                    <th>Project ID</th>
                    <th>Project Name</th>
                    <th>Project State</th>
                    <th></th>
                </tr>
                @foreach (var item in Model.Customer.Projects)
                {                    <tr>
                       <td>
                           @Html.DisplayFor(modelItem => item.ProjectId)                       </td>
                        <td>
                            @Html.DisplayFor(modelItem => item.ProjectName)                        </td>
                        <td>
                            @Html.DisplayFor(modelItem => item.ProjectStateCode)                        </td>
                        <td>
                            <a asp-page="./CustomerProjectEdit"                                asp-route-id="@item.ProjectId">Edit</a> |                            <a asp-page="./CustomerProjectDelete"                                asp-route-id="@item.ProjectId">Delete</a>
                        </td>
                    </tr>
                }            </table>
        </dd>
    </dl></div><div>
    <a asp-page="CustomerProjectCreate" asp-route-id="@Model.Customer.CustomerId">        Create New Project</a> |    <a asp-page="./Index">Back to List</a></div>

“ {id:int?}”表示需要整数参数,id或者页面请求将返回HTTP 401(未找到页面)错误。在这种情况下,这是CustomerId目标的标识符(Customer另外,请注意引用该CustomerProjectCreate页面的链接

<a asp-page="CustomerProjectCreate"asp-route-id="@Model.Customer.CustomerId">创建新项目</a> |

这将把我们带到CustomerProjectCreate尚未创建页面,Project为引用创建一个新Customer

修改了~Pages \ Customers \ CustomerProjects.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 CustomerProjectsModel : PageModel
    {        private readonly QuantumDbContext _context;        public CustomerProjectsModel(QuantumDbContext context)
        {
            _context = context;
        } // end public CustomerProjectsModel(QuantumDbContext context)

        public Customer Customer { get; set; }        public async Task<IActionResult> OnGet(int? id)
        {            if (id == null)
            {                return NotFound();
            } // endif (id == null)

            Customer = await _context.Customers
                .Include(c => c.Projects)
                    .FirstOrDefaultAsync(c => c.CustomerId == id);            if (Customer == null)
            {                return NotFound();
            } // endif (Customer == null)

            return Page();
        } // end public async Task<IActionResult> OnGet(int? id)

    } // end public class CustomerProjectsModel : PageModel} // end namespace QuantumWeb.Pages.Customers

请注意,OnGet处理程序具有可为空的整数参数,id应该CustomerId如上所述。

QuantumWeb 应用客户页面:https // localhost:44306 /具有项目链接的客户。

Customer Projects页面:https // localhost:44306 / Customers / CustomerProjects / 1(无项目)

“ 创建新项目 ”链接将激活自定义CustomerProjectCreateRazor页面。我们现在支持这个页面。

脚手架客户/ CustomerProjectCreate Razor页面:

Initial~Pages \ Customers \ CustomerProjectCreate.cshtml.cs

隐藏   收缩    复制代码

using System.Threading.Tasks;using Microsoft.AspNetCore.Mvc;using Microsoft.AspNetCore.Mvc.RazorPages;using Microsoft.AspNetCore.Mvc.Rendering;using Microsoft.EntityFrameworkCore;using QuantumWeb.Data;using QuantumWeb.Model;namespace QuantumWeb.Pages.Customers
{    public class CustomerProjectCreateModel : PageModel
    {        private readonly QuantumDbContext _context;        public CustomerProjectCreateModel(QuantumDbContext context)
        {
            _context = context;
        } // end public CustomerProjectCreateModel(QuantumContext context)

        [BindProperty]        public Customer Customer { get; set; }        public async Task<IActionResult> OnGet(int? id)
        {            if (id == null)
            {                return NotFound();
            } // endif (id == null)

            Customer = await _context.Customers
                .Include(c => c.Projects)
                    .FirstOrDefaultAsync(c => c.CustomerId == id);            if (Customer == null)
            {                return NotFound();
            } // endif (Customer == null)

            ViewData["ProjectStateCode"] = new SelectList(_context.ProjectStateDescriptions,                "ProjectStateCode", "StateDescription", ProjectState.Prospect);            return Page();

        } // end public async Task<IActionResult> OnGet(int? id)

        [BindProperty]        public Project Project { get; set; }        public async Task<IActionResult> OnPostAsync()
        {            if (!ModelState.IsValid)
            {                return Page();
            } // endif (!ModelState.IsValid)

            Project.CustomerId = Customer.CustomerId;

            _context.Projects.Add(Project);            await _context.SaveChangesAsync();            return RedirectToPage("./CustomerProjects", new { id = Customer.CustomerId });
        } // end public async Task<IActionResult> OnPostAsync()

    } // end public class CustomerProjectCreateModel : PageModel} // end namespace QuantumWeb.Pages.Customers

请注意此代码中的这些行。

隐藏   复制代码

[BindProperty]public Customer Customer { get; set; }

[BindProperty]的结合Customer,使它们的值在浏览器和Web服务器之间保持实例的用户界面的元素。另请注意,此属性也适用于Project实例。

隐藏   复制代码

Customer = await _context.Customers
    .Include(c => c.Projects)
        .FirstOrDefaultAsync(c => c.CustomerId == id);

此语句对数据库执行查询,以检索Customer其主键值CustomerId与输入参数id,值及其关联Project记录(如果有)匹配的记录。该函数的功能.Include是在查询中包含相关记录。

隐藏   复制代码

ViewData["ProjectStateCode"] = new SelectList(_context.ProjectStateDescriptions,   "ProjectStateCode", "StateDescription", ProjectState.Prospect);

ViewData是一个未键入的键值字典,用于在CustomerProjectCreateModel类(在.cshtml.cs文件中)和.cshtml文件中的HTML 之间传递值这类似于将数据从ControllerMVC 传递到View,在使用中ViewData,数据仅在HTTP请求中持久存在。其成员由ProjectStateDescriptions数据库表中的查询填充在这种情况下,_context.ProjectStateDescriptionsIEnumerable<ProjectStateDescription>从查询返回的。ProjectStateCode是表中的主键,表示ViewData字典中的键StateDescription成为ViewData.字典中的关联值ViewData将用来填充<select>的元素CustomerProjectCreate.cshtml(见下文。)ProjectState.Prospect是从默认选择的值ProjectState enum<select>您可以ViewData在链接上阅读更多信息https://www.tektutorialshub.com/viewbag-viewdata-asp-net-core/

Initial ~Pages \ Customers \ CustomerProjectCreate.cshtml

隐藏   收缩    复制代码

@page
@model QuantumWeb.Pages.Customers.CustomerProjectCreateModel
@{
    ViewData["Title"] = "Create Customer Project";
}<h2>Create Customer Project</h2><hr /><dl class="dl-horizontal">
    <dt>
        @Html.DisplayNameFor(model => model.Customer.CustomerId)    </dt>
    <dd>
        @Html.DisplayFor(model => model.Customer.CustomerId)    </dd>
    <dt>
        @Html.DisplayNameFor(model => model.Customer.CustomerName)    </dt>
    <dd>
        @Html.DisplayFor(model => model.Customer.CustomerName)    </dd></dl><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="Project.ProjectName" class="control-label"></label>
                <input asp-for="Project.ProjectName" class="form-control">
            </div>
            <div class="form-group">
                <label asp-for="Project.ProjectStateCode" class="control-label"></label>
                <select asp-for="Project.ProjectStateCode" class="form-control"                   asp-items="ViewBag.ProjectStateCode">
                </select>
            </div>
            <div class="form-group">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </form>
    </div></div><div>
    <a asp-page="CustomerProjects" asp-route-id="@Model.Customer.CustomerId">
        Back to Customer Projects    </a></div>@section Scripts {
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

关键要素如下:

隐藏   复制代码

<input type="hidden" asp-for="Customer.CustomerId" />

这个隐藏<input>捕获目标,CustomerId以便在<form>发布时可用它来创建Project

隐藏   复制代码

<select asp-for="Project.ProjectStateCode" class="form-control"    asp-items="ViewBag.ProjectStateCode"></select>

<select>元素将显示为UI中的下拉列表,其中包含方法中ViewData填充的值CustomerProjectCreate.OnGet()

Initial ~Pages \ Customers \ CustomerProjectCreate.cshtml

这将显示最初显示Customers / CustomerProjectCreate页面。

CustomerProjectCreate 包含数据的页面:

点击“ Create”后,我们会看到:

客户Projects页面添加Project

接下来的两个数字显示Projects了两者之后的其他内容Customers

客户项目页面包含Mirarex Oil&Gas的2个项目:

客户项目页面包含3个聚烯烃加工项目

我们现在可以添加另一个页面来编辑Customer项目CustomerProjectEdit页面。

脚手架客户/ CustomerProjectEdit Razor Page

Initial~Pages \ Customers \ CustomerProjectEdit.cshtml.cs

隐藏   收缩    复制代码

using System.Threading.Tasks;using Microsoft.AspNetCore.Mvc;using Microsoft.AspNetCore.Mvc.RazorPages;using Microsoft.AspNetCore.Mvc.Rendering;using Microsoft.EntityFrameworkCore;using QuantumWeb.Data;using QuantumWeb.Model;namespace QuantumApp.Pages.Customers
{    public class CustomerProjectEditModel : PageModel
    {        private readonly QuantumDbContext _context;        public CustomerProjectEditModel(QuantumDbContext context)
        {
            _context = context;
        } // end public CustomerProjectEditModel(QuantumDbContext context)

        [BindProperty]        public Customer Customer { get; set; }
        [BindProperty]        public Project Project { get; set; }        public async Task<IActionResult> OnGet(int? id)
        {            if (id == null)
            {                return NotFound();
            } // endif (id == null)

            Project = await _context.Projects
                .Include(p => p.Customer)
                    .FirstOrDefaultAsync(p => p.ProjectId == id);            if (Project == null)
            {                return NotFound();
            } // endif (Project == null)

            Customer = Project.Customer;

            ViewData["ProjectStateCode"] = new SelectList(_context.ProjectStateDescriptions,                "ProjectStateCode", "StateDescription", ProjectState.Prospect);            return Page();
        } // end public async Task<IActionResult> OnGet(int? id)

        public async Task<IActionResult> OnPostAsync(int? id)
        {            if (!ModelState.IsValid)
            {                return Page();
            } // endif (!ModelState.IsValid)

            var projectToUpdate = await _context.Projects.FindAsync(id);            if (projectToUpdate == null)
            {                return NotFound();
            } // endif (projectToUpdate == null)

            projectToUpdate.CustomerId = Customer.CustomerId;            if (await TryUpdateModelAsync<Project>(
                projectToUpdate,                "project",
                p => p.ProjectName, p => p.ProjectStateCode))
            {                await _context.SaveChangesAsync();                return RedirectToPage("./CustomerProjects", new { id = Customer.CustomerId });
            }            return Page();
        } // end public async Task<IActionResult> OnPostAsync(int? id)

    } // end public class CustomerProjectEditModel : PageModel} // end namespace QuantumApp.Pages.Customers

该代码具有相同的器物作为CustomerProjectCreate相对于页面.IncludeViewData

Initial~Pages \ Customers \ CustomerProjectEdit.cshtml

隐藏   收缩    复制代码

@page "{id:int?}"
@model QuantumWeb.Pages.Customers.CustomerProjectEditModel
@{
    ViewData["Title"] = "Edit Customer Project";
}<h2>Edit Customer Project</h2><hr /><dl class="dl-horizontal">
    <dt>
        @Html.DisplayNameFor(model => model.Customer.CustomerId)    </dt>
    <dd>
        @Html.DisplayFor(model => model.Customer.CustomerId)    </dd>
    <dt>
        @Html.DisplayNameFor(model => model.Customer.CustomerName)    </dt>
    <dd>
        @Html.DisplayFor(model => model.Customer.CustomerName)    </dd></dl><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="Project.ProjectName" class="control-label"></label>
                <input asp-for="Project.ProjectName" class="form-control">
            </div>
            <div class="form-group">
                <label asp-for="Project.ProjectStateCode" class="control-label"></label>
                <select asp-for="Project.ProjectStateCode" class="form-control"                    asp-items="ViewBag.ProjectStateCode">
                </select>
            </div>
            <div class="form-group">
                <input type="submit" value="Save" class="btn btn-default" />
            </div>
        </form>
    </div></div><div>
    <a asp-page="CustomerProjects" asp-route-id="@Model.Customer.CustomerId">
        Back to Customer Projects    </a></div>@section Scripts {
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

此页面具有与页面相同的元素CustomerProjectCreate,关于隐藏<input>CustomerId<select>

Customer Projects 有关Mirarex Oil&Gas的2个项目的页面 - 用于编辑:

Zolar Pipeline Mirarex Oil&Gas的客户项目编辑页面:

客户项目页面,包含Mirarex石油和天然气的2个项目 - 项目编辑:

此部分的最终功能通过CustomerProjectDelete页面删除项目

脚手架客户/ CustomerProjectDelete Razor页面:

Initial~Pages \ Customers \ CustomerProjectDelete.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 CustomerProjectDeleteModel : PageModel
    {        private readonly QuantumDbContext _context;        public CustomerProjectDeleteModel(QuantumDbContext context)
        {
            _context = context;
        } // end public CustomerProjectDeleteModel(QuantumContext context)

        [BindProperty]        public Customer Customer { get; set; }
        [BindProperty]        public Project Project { get; set; }        public async Task<IActionResult> OnGetAsync(int? id)
        {            if (id == null)
            {                return NotFound();
            } // endif (id == null)

            Project = await _context.Projects
                .Include(p => p.Customer)
                    .FirstOrDefaultAsync(p => p.ProjectId == id);            if (Project == null)
            {                return NotFound();
            } // endif (Project == null)

            Customer = Project.Customer;            return Page();
        } // end public async Task<IActionResult> OnGet(int? id)

        public async Task<IActionResult> OnPostAsync(int? id)
        {            if (id == null)
            {                return NotFound();
            } // endif (id == null)

            Project = await _context.Projects
                .Include(p => p.Customer)
                .FirstOrDefaultAsync(p => p.ProjectId == id);            if (Project != null)
            {
                _context.Projects.Remove(Project);                await _context.SaveChangesAsync();
            } // endif (Project != null)

            return RedirectToPage("./CustomerProjects", new { id = Project.Customer.CustomerId });
        } // end public async Task<IActionResult> OnPostAsync(int? id)

    } // end public class CustomerProjectDeleteModel : PageModel} // end namespace QuantumWeb.Pages.Customer
Initial~Pages \ Customers \ CustomerProjectDelete.cshtml

隐藏   收缩    复制代码

@page "{id:int?}"
@model QuantumWeb.Pages.Customers.CustomerProjectDeleteModel
@{
    ViewData["Title"] = "Delete Customer Project";
}<h2>Delete Customer Project</h2><h3>Are you sure you want to delete this?</h3><div>
    <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.Project.ProjectId)        </dt>
        <dd>
            @Html.DisplayFor(model => model.Project.ProjectId)        </dd>
        <dt>
            @Html.DisplayNameFor(model => model.Project.ProjectName)        </dt>
        <dd>
            @Html.DisplayFor(model => model.Project.ProjectName)        </dd>
        <dt>
            @Html.DisplayNameFor(model => model.Project.ProjectStateCode)        </dt>
        <dd>
            @Html.DisplayFor(model => model.Project.ProjectStateCode)        </dd>
    </dl>

    <form method="post">
        <input type="hidden" asp-for="Project.ProjectId" />
        <a asp-page="CustomerProjects" asp-route-id="@Model.Customer.CustomerId">
            Back to Customer Projects        </a> |        <input type="submit" value="Delete" class="btn btn-default" />
    </form></div>

为Mirarex Oil&Gas提供3个项目的客户项目页面:

删除客户项目页面 - 删除Ouachita页岩:

客户项目页面包含Mirarex Oil&Gas的2个项目:

此时,我们可以总结下表中的测试数据:

客户,项目,项目所在

顾客ID顾客姓名专案编号项目名ProjectStateCodeStateDescription
1Mirarex Oil&Gas,LLC1Zolar管道UnderReview项目正在审查和谈判中
1Mirarex Oil&Gas,LLC2Nelar Ranch气体压裂展望预期或转介项目
2聚烯烃加工公司3吉布森港工厂扩建展望预期或转介项目
2聚烯烃加工公司4杰克逊工厂控制系统升级展望预期或转介项目
2聚烯烃加工公司Eutaw工厂关闭和维护展望预期或转介项目

摘要

我们已经实现了ProjectStateProject一个一对多的关系,创建ASP.NET页面剃刀来管理它。


合作伙伴

网站备案:豫ICP备15023476号-1 唯特科技