zoukankan      html  css  js  c++  java
  • 使用EntityFramework Core和Enums作为字符串的ASP.NET Core 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功能

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

    • 添加Project,ProjectState和ProjectStateDescription实体。
    • 添加EF迁移以在数据库中创建和配置Projects和ProjectStateDescriptions表。
    • 演示enum对象模型实体中的string值与Projects和ProjectStateDescriptions数据库表中的值之间的转换。
    • 搭建,实现和测试包含ProjectState功能的ProjectCRUD页面,如CustomerProjects.cshtmlCustomerProjectCreate.cshtmlCustomerProjectDetails.cshtmlCustomerProjectDelete.cshtml Razor页面。

    使用代码

    添加初始项目处理。

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

    修改后的Customer.cs

    1.  
      using System.Collections.Generic;
    2.  
       
    3.  
      namespace QuantumWeb.Model
    4.  
      {
    5.  
      /// <summary>
    6.  
      /// Customer Class
    7.  
      /// </summary>
    8.  
      public class Customer
    9.  
      {
    10.  
      #region Constructors
    11.  
       
    12.  
      /// <summary>
    13.  
      /// Parameter-less Constructor
    14.  
      /// </summary>
    15.  
      /// <remarks>
    16.  
      /// Required for scaffolding the UI
    17.  
      /// </remarks>
    18.  
      public Customer()
    19.  
      {
    20.  
      } // end public Customer()
    21.  
       
    22.  
      #endregion // Constructors
    23.  
       
    24.  
      /// <summary>
    25.  
      /// Customer Identifier, primary key
    26.  
      /// </summary>
    27.  
      public int CustomerId { get; set; }
    28.  
      /// <summary>
    29.  
      /// Customer Name
    30.  
      /// </summary>
    31.  
      public string CustomerName { get; set; }
    32.  
      /// <summary>
    33.  
      /// Primary Customer Contact
    34.  
      /// </summary>
    35.  
      public string CustomerContact { get; set; }
    36.  
      /// <summary>
    37.  
      /// Customer Contact Phone Number
    38.  
      /// </summary>
    39.  
      public string CustomerPhone { get; set; }
    40.  
      /// <summary>
    41.  
      /// Customer Contact Email Address
    42.  
      /// </summary>
    43.  
      public string CustomerEmail { get; set; }
    44.  
       
    45.  
      #region Navigation Properties
    46.  
       
    47.  
      /// <summary>
    48.  
      /// List of Projects
    49.  
      /// </summary>
    50.  
      public List<Project> Projects { get; set; }
    51.  
       
    52.  
      #endregion // Navigation Properties
    53.  
       
    54.  
      } // end public class Customer
    55.  
       
    56.  
      } // end namespace QuantumWeb.Model

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

    初始Project.cs

    1.  
      namespace QuantumWeb.Model
    2.  
      {
    3.  
      /// <summary>
    4.  
      /// Project Class
    5.  
      /// </summary>
    6.  
      public class Project
    7.  
      {
    8.  
      /// <summary>
    9.  
      /// Project Identifier, primary key
    10.  
      /// </summary>
    11.  
      public int ProjectId { get; set; }
    12.  
      /// <summary>
    13.  
      /// Project Name
    14.  
      /// </summary>
    15.  
      public string ProjectName { get; set; }
    16.  
       
    17.  
      #region Navigation Properties
    18.  
       
    19.  
      /// <summary>
    20.  
      /// Customer Identifier
    21.  
      /// </summary>
    22.  
      public int CustomerId { get; set; }
    23.  
       
    24.  
      /// <summary>
    25.  
      /// Customer
    26.  
      /// </summary>
    27.  
      /// <remarks>
    28.  
      /// Every Project has a Customer
    29.  
      /// </remarks>
    30.  
      public Customer Customer { get; set; }
    31.  
       
    32.  
      /// <summary>
    33.  
      /// Project Status Code
    34.  
      /// </summary>
    35.  
      public ProjectState ProjectStateCode { get; set; }
    36.  
       
    37.  
      /// <summary>
    38.  
      /// ProjectStateDescription Reference
    39.  
      /// </summary>
    40.  
      public ProjectStateDescription ProjectStateDescription { get; set; }
    41.  
       
    42.  
      #endregion // Navigation Properties
    43.  
       
    44.  
      } // end public class Project
    45.  
       
    46.  
      } // end namespace QuantumApp.Model

    除了定义初始化Project类之外,我们还将在Model文件夹中定义ProjectState enum。

    ProjectState.cs

    1.  
      namespace QuantumWeb.Model
    2.  
      {
    3.  
      /// <summary>
    4.  
      /// Project State Enumeration
    5.  
      /// </summary>
    6.  
      public enum ProjectState
    7.  
      {
    8.  
      Prospect,
    9.  
      UnderReview,
    10.  
      StartScheduled,
    11.  
      InProgress,
    12.  
      Completed
    13.  
      } // end public enum ProjectState
    14.  
       
    15.  
      } // end namespace QuantumWeb.Model

    这个enum指定了Project工作流的状态。

    • Prospect。这涉及一个有前景的Project。这个Project可能是通过推荐或其他营销工作提出的。尚未进行任何研究,且规格尚不清楚。
    • UnderReview。在这种状态下,Project制定了要求,初始预算和进度表。没有承诺Quantum或者Customer。
    • StartScheduled。已经指定了工作开始的日期,并且正在准备开始工作。
    • InProgress。实际工作已经开始但尚未完成。
    • Completed。项目工作完成。

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

    1. 我们应该为Project将在UI中显示的每个状态定义简短描述,以帮助用户理解每个状态的含义。
    2. 每个enum值都作为string类型存储在数据库中。

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

    ProjectStateDescription.cs

    1.  
      using System.Collections.Generic;
    2.  
       
    3.  
      namespace QuantumWeb.Model
    4.  
      {
    5.  
      /// <summary>
    6.  
      /// Project State Description Class
    7.  
      /// </summary>
    8.  
      public class ProjectStateDescription
    9.  
      {
    10.  
      /// <summary>
    11.  
      /// ProjectState Code
    12.  
      /// </summary>
    13.  
      public ProjectState ProjectStateCode { get; set; }
    14.  
       
    15.  
      /// <summary>
    16.  
      /// State Description
    17.  
      /// </summary>
    18.  
      public string StateDescription { get; set; }
    19.  
       
    20.  
      #region Navigation Properties
    21.  
       
    22.  
      /// <summary>
    23.  
      /// Projects Collection
    24.  
      /// </summary>
    25.  
      public List<Project> Projects { get; set; }
    26.  
       
    27.  
      #endregion // Navigation Properties
    28.  
       
    29.  
      } // end public class ProjectStateDescription
    30.  
       
    31.  
      } // end namespace QuantumWeb.Model

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

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

    初始ProjectConfiguration.cs

    1.  
      using System;
    2.  
      using Microsoft.EntityFrameworkCore;
    3.  
      using Microsoft.EntityFrameworkCore.Metadata.Builders;
    4.  
      using QuantumWeb.Model;
    5.  
       
    6.  
      namespace QuantumWeb.Data
    7.  
      {
    8.  
      public class ProjectConfiguration : IEntityTypeConfiguration<Project>
    9.  
      {
    10.  
      public void Configure(EntityTypeBuilder<Project> builder)
    11.  
      {
    12.  
      builder.ToTable("Projects");
    13.  
      builder.HasKey(p => p.ProjectId);
    14.  
      builder.Property(p => p.ProjectId)
    15.  
      .HasColumnType("int");
    16.  
      builder.Property(p => p.ProjectName)
    17.  
      .IsRequired()
    18.  
      .HasColumnType("nvarchar(80)")
    19.  
      .HasMaxLength(80);
    20.  
      builder.Property(p => p.CustomerId)
    21.  
      .HasColumnType("int")
    22.  
      .IsRequired();
    23.  
      builder.HasOne(p => p.Customer)
    24.  
      .WithMany(c => c.Projects)
    25.  
      .HasForeignKey(p => p.CustomerId)
    26.  
      .IsRequired();
    27.  
      builder.Property(p => p.ProjectStateCode)
    28.  
      .HasColumnType("nvarchar(15)")
    29.  
      .HasDefaultValue(ProjectState.Prospect)
    30.  
      .HasConversion(
    31.  
      p => p.ToString(),
    32.  
      p => (ProjectState)Enum.Parse(typeof(ProjectState), p));
    33.  
      builder.HasOne(p => p.ProjectStateDescription)
    34.  
      .WithMany(pd => pd.Projects)
    35.  
      .HasForeignKey(p => p.ProjectStateCode);
    36.  
      } // end public void Configure(EntityTypeBuilder<Project> builder)
    37.  
       
    38.  
      } // end public class ProjectConfiguration : IEntityTypeConfiguration<Project>
    39.  
       
    40.  
      } // end namespace QuantumWeb.Data

    看看下面提取的行:

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

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

    在一对多ProjectStateDescription- Project关系被配置为:

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

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

    1.  
      builder.Property(p => p.ProjectStateCode)
    2.  
      .HasColumnType("nvarchar(15)")
    3.  
      .HasDefaultValue(ProjectState.Prospect)
    4.  
      .HasConversion(
    5.  
      p => p.ToString(),
    6.  
      p => (ProjectState)Enum.Parse(typeof(ProjectState), p));

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

    ProjectStateDescriptionConfiguration类如下所示。

    ProjectStateDescriptionConfiguration.cs

    1.  
      using System;
    2.  
      using Microsoft.EntityFrameworkCore;
    3.  
      using Microsoft.EntityFrameworkCore.Metadata.Builders;
    4.  
      using QuantumWeb.Model;
    5.  
       
    6.  
      namespace QuantumWeb.Data
    7.  
      {
    8.  
      /// <summary>
    9.  
      /// ProjectState Description Configuration Class
    10.  
      /// </summary>
    11.  
      public class ProjectStateDescriptionConfiguration :
    12.  
      IEntityTypeConfiguration<ProjectStateDescription>
    13.  
      {
    14.  
       
    15.  
      public void Configure(EntityTypeBuilder<ProjectStateDescription> builder)
    16.  
      {
    17.  
      builder.ToTable("ProjectStateDescriptions");
    18.  
      builder.HasKey(p => p.ProjectStateCode);
    19.  
      builder.Property(p => p.ProjectStateCode)
    20.  
      .HasColumnType("nvarchar(15)")
    21.  
      .HasConversion(
    22.  
      p => p.ToString(),
    23.  
      p => (ProjectState)Enum.Parse(typeof(ProjectState), p));
    24.  
      builder.Property(p => p.StateDescription)
    25.  
      .IsRequired()
    26.  
      .HasColumnType("nvarchar(80)")
    27.  
      .HasMaxLength(80);
    28.  
      } // end public void Configure(EntityTypeBuilder<ProjectStateDescription> builder)
    29.  
       
    30.  
      } // end public class ProjectStateDescriptionConfiguration :
    31.  
      // IEntityTypeConfiguration<ProjectStateDescription>
    32.  
       
    33.  
      } // end namespace QuantumWeb.Data

    现在,我们更新QuantumDbContext类。

    然后更新QuantumDbContext.cs

    1.  
      using Microsoft.EntityFrameworkCore;
    2.  
      using QuantumWeb.Model;
    3.  
       
    4.  
      namespace QuantumWeb.Data
    5.  
      {
    6.  
      public class QuantumDbContext : DbContext
    7.  
      {
    8.  
      public QuantumDbContext (DbContextOptions<QuantumDbContext> options)
    9.  
      : base(options)
    10.  
      {
    11.  
      } // end public QuantumDbContext (DbContextOptions<QuantumDbContext> options)
    12.  
       
    13.  
      #region DbSets
    14.  
       
    15.  
      /// <summary>
    16.  
      /// Customer DbSet
    17.  
      /// </summary>
    18.  
      public DbSet<Customer> Customers { get; set; }
    19.  
       
    20.  
      /// <summary>
    21.  
      /// Project DbSet
    22.  
      /// </summary>
    23.  
      public DbSet<Project> Projects { get; set; }
    24.  
       
    25.  
      /// <summary>
    26.  
      /// ProjectStateDescription DbSet
    27.  
      /// </summary>
    28.  
      public DbSet<ProjectStateDescription> ProjectStateDescriptions { get; set; }
    29.  
       
    30.  
      #endregion // DbSets
    31.  
       
    32.  
      /// <summary>
    33.  
      /// Data Model Creation Method
    34.  
      /// </summary>
    35.  
      /// <param name="modelBuilder">ModelBuilder instance</param>
    36.  
      protected override void OnModelCreating(ModelBuilder modelBuilder)
    37.  
      {
    38.  
      modelBuilder.ApplyConfiguration(new CustomerConfiguration());
    39.  
      modelBuilder.ApplyConfiguration(new ProjectConfiguration());
    40.  
      modelBuilder.ApplyConfiguration(new ProjectStateDescriptionConfiguration());
    41.  
      } // end protected override void OnModelCreating(ModelBuilder modelBuilder)
    42.  
       
    43.  
      } // end public class QuantumDbContext : DbContext
    44.  
       
    45.  
      } // end namespace QuantumWeb.Data

    现在为Project和ProjectState实体添加EF迁移。(译者注:同样需要调整appsettings.json中数据库连接字符串,建议删除Migrations文件夹后在执行下面的命令,同时提醒,在执行下面命令后需要命令update-database更新到数据库)

    Add-Migration Added-Project-ProjectState

    生成 ~Migrations20181021203503_Added-Project-ProjectState.cs:

    1.  
      using Microsoft.EntityFrameworkCore.Metadata;
    2.  
      using Microsoft.EntityFrameworkCore.Migrations;
    3.  
       
    4.  
      namespace QuantumWeb.Migrations
    5.  
      {
    6.  
      public partial class AddedProjectProjectState : Migration
    7.  
      {
    8.  
      protected override void Up(MigrationBuilder migrationBuilder)
    9.  
      {
    10.  
      migrationBuilder.CreateTable(
    11.  
      name: "ProjectStateDescriptions",
    12.  
      columns: table => new
    13.  
      {
    14.  
      ProjectStateCode =
    15.  
      table.Column<string>(type: "nvarchar(15)", nullable: false),
    16.  
      StateDescription =
    17.  
      table.Column<string>(type: "nvarchar(80)", maxLength: 80, nullable: false)
    18.  
      },
    19.  
      constraints: table =>
    20.  
      {
    21.  
      table.PrimaryKey("PK_ProjectStateDescriptions", x => x.ProjectStateCode);
    22.  
      });
    23.  
       
    24.  
      migrationBuilder.CreateTable(
    25.  
      name: "Projects",
    26.  
      columns: table => new
    27.  
      {
    28.  
      ProjectId = table.Column<int>(type: "int", nullable: false)
    29.  
      .Annotation("SqlServer:ValueGenerationStrategy",
    30.  
      SqlServerValueGenerationStrategy.IdentityColumn),
    31.  
      ProjectName = table.Column<string>(type: "nvarchar(80)",
    32.  
      maxLength: 80, nullable: false),
    33.  
      CustomerId = table.Column<int>(type: "int", nullable: false),
    34.  
      ProjectStateCode = table.Column<string>
    35.  
      (type: "nvarchar(15)", nullable: false, defaultValue: "Prospect")
    36.  
      },
    37.  
      constraints: table =>
    38.  
      {
    39.  
      table.PrimaryKey("PK_Projects", x => x.ProjectId);
    40.  
      table.ForeignKey(
    41.  
      name: "FK_Projects_Customers_CustomerId",
    42.  
      column: x => x.CustomerId,
    43.  
      principalTable: "Customers",
    44.  
      principalColumn: "CustomerId",
    45.  
      onDelete: ReferentialAction.Cascade);
    46.  
      table.ForeignKey(
    47.  
      name: "FK_Projects_ProjectStateDescriptions_ProjectStateCode",
    48.  
      column: x => x.ProjectStateCode,
    49.  
      principalTable: "ProjectStateDescriptions",
    50.  
      principalColumn: "ProjectStateCode",
    51.  
      onDelete: ReferentialAction.Cascade);
    52.  
      });
    53.  
       
    54.  
      migrationBuilder.CreateIndex(
    55.  
      name: "IX_Projects_CustomerId",
    56.  
      table: "Projects",
    57.  
      column: "CustomerId");
    58.  
       
    59.  
      migrationBuilder.CreateIndex(
    60.  
      name: "IX_Projects_ProjectStateCode",
    61.  
      table: "Projects",
    62.  
      column: "ProjectStateCode");
    63.  
      }
    64.  
       
    65.  
      protected override void Down(MigrationBuilder migrationBuilder)
    66.  
      {
    67.  
      migrationBuilder.DropTable(
    68.  
      name: "Projects");
    69.  
       
    70.  
      migrationBuilder.DropTable(
    71.  
      name: "ProjectStateDescriptions");
    72.  
      }
    73.  
      }
    74.  
      }

    在Update- Database命令之后,SQL Server Management Studio(SSMS)中的数据库关系图如下所示。

    使用Customer- Project- ProjectState表的QuantumDbContext数据库关系图:

    https://img-blog.csdnimg.cn/20181228195522488

    修改Project和ProjectState的Razor 页。

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

    添加CustomerProjects 链接指向PagesCustomersIndex.cshtml:

    1.  
      @page
    2.  
      @model QuantumWeb.Pages.Customers.IndexModel
    3.  
       
    4.  
      @{
    5.  
      ViewData["Title"] = "Index";
    6.  
      }
    7.  
       
    8.  
      <h2>Index</h2>
    9.  
       
    10.  
      <p>
    11.  
      <a asp-page="Create">Create New</a>
    12.  
      <!-- A link to the Pages/Customers/Create page to create a new Customer -->
    13.  
      </p>
    14.  
      <!-- An HTML table to display existing Customers -->
    15.  
      <table class="table">
    16.  
      <thead>
    17.  
      <tr>
    18.  
      <th>
    19.  
      @Html.DisplayNameFor(model => model.Customer[0].CustomerName)
    20.  
      </th>
    21.  
      <th>
    22.  
      @Html.DisplayNameFor(model => model.Customer[0].CustomerContact)
    23.  
      </th>
    24.  
      <th>
    25.  
      @Html.DisplayNameFor(model => model.Customer[0].CustomerPhone)
    26.  
      </th>
    27.  
      <th>
    28.  
      @Html.DisplayNameFor(model => model.Customer[0].CustomerEmail)
    29.  
      </th>
    30.  
      <th></th>
    31.  
      </tr>
    32.  
      </thead>
    33.  
      <tbody>
    34.  
      @foreach (var item in Model.Customer) {
    35.  
      <tr>
    36.  
      <td>
    37.  
      @Html.DisplayFor(modelItem => item.CustomerName)
    38.  
      </td>
    39.  
      <td>
    40.  
      @Html.DisplayFor(modelItem => item.CustomerContact)
    41.  
      </td>
    42.  
      <td>
    43.  
      @Html.DisplayFor(modelItem => item.CustomerPhone)
    44.  
      </td>
    45.  
      <td>
    46.  
      @Html.DisplayFor(modelItem => item.CustomerEmail)
    47.  
      </td>
    48.  
      <td>
    49.  
      <a asp-page="./Edit" asp-route-id="@item.CustomerId">Edit</a> |
    50.  
      <!-- A link to the Pages/Customers/Edit page to edit an existing Customer -->
    51.  
      <a asp-page="./Details" asp-route-id="@item.CustomerId">Details</a> |
    52.  
      <!--
    53.  
      A link to the Pages/Customers/Details page to display the details for an existing
    54.  
      Customer
    55.  
      -->
    56.  
      <a asp-page="./CustomerProjects" asp-route-id="@item.CustomerId">Projects</a> |
    57.  
      <!--
    58.  
      A link to the Pages/Customers/CustomerProjects page to display & manage the
    59.  
      Projects for an existing Customer
    60.  
      -->
    61.  
      <a asp-page="./Delete" asp-route-id="@item.CustomerId">Delete</a>
    62.  
      <!-- A link to the Pages/Customers/Delete page to delete an existing Customer -->
    63.  
      </td>
    64.  
      </tr>
    65.  
      }
    66.  
      </tbody>
    67.  
      </table>

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

    为客户设计的定制构建Razor页面:

    https://img-blog.csdnimg.cn/20181228195522543

    搭建Customers/CustomerProjects Razor 页面:

    https://img-blog.csdnimg.cn/20181228195522598

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

    生成~PagesCustomersCustomerProjects.cshtml

    1.  
      @page
    2.  
      @model QuantumWeb.Pages.Customers.CustomerProjectsModel
    3.  
      @{
    4.  
      ViewData["Title"] = "CustomerProjects";
    5.  
      }
    6.  
       
    7.  
      <h2>CustomerProjects</h2>

    生成~PagesCustomersCustomerProjects.cshtml.cs

    1.  
      using System;
    2.  
      using System.Collections.Generic;
    3.  
      using System.Linq;
    4.  
      using System.Threading.Tasks;
    5.  
      using Microsoft.AspNetCore.Mvc;
    6.  
      using Microsoft.AspNetCore.Mvc.RazorPages;
    7.  
       
    8.  
      namespace QuantumWeb.Pages.Customers
    9.  
      {
    10.  
      public class CustomerProjectsModel : PageModel
    11.  
      {
    12.  
      public void OnGet()
    13.  
      {
    14.  
       
    15.  
      }
    16.  
      }
    17.  
      }

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

    修改了~PagesCustomersCustomerProjects.cshtml

    1.  
      @page "{id:int?}"
    2.  
      @model QuantumWeb.Pages.Customers.CustomerProjectsModel
    3.  
      @{
    4.  
      ViewData["Title"] = "Customer Projects";
    5.  
      }
    6.  
       
    7.  
      <h2>Customer Projects</h2>
    8.  
       
    9.  
      <div>
    10.  
      <h4>Customer</h4>
    11.  
      <hr />
    12.  
      <dl class="dl-horizontal">
    13.  
      <dt>
    14.  
      @Html.DisplayNameFor(model => model.Customer.CustomerId)
    15.  
      </dt>
    16.  
      <dd>
    17.  
      @Html.DisplayFor(model => model.Customer.CustomerId)
    18.  
      </dd>
    19.  
      <dt>
    20.  
      @Html.DisplayNameFor(model => model.Customer.CustomerName)
    21.  
      </dt>
    22.  
      <dd>
    23.  
      @Html.DisplayFor(model => model.Customer.CustomerName)
    24.  
      </dd>
    25.  
      <dt>
    26.  
      @Html.DisplayNameFor(model => model.Customer.Projects)
    27.  
      </dt>
    28.  
      <dd>
    29.  
      <table class="table">
    30.  
      <tr>
    31.  
      <th>Project ID</th>
    32.  
      <th>Project Name</th>
    33.  
      <th>Project State</th>
    34.  
      <th></th>
    35.  
      </tr>
    36.  
      @foreach (var item in Model.Customer.Projects)
    37.  
      {
    38.  
      <tr>
    39.  
      <td>
    40.  
      @Html.DisplayFor(modelItem => item.ProjectId)
    41.  
      </td>
    42.  
      <td>
    43.  
      @Html.DisplayFor(modelItem => item.ProjectName)
    44.  
      </td>
    45.  
      <td>
    46.  
      @Html.DisplayFor(modelItem => item.ProjectStateCode)
    47.  
      </td>
    48.  
      <td>
    49.  
      <a asp-page="./CustomerProjectEdit"
    50.  
       
    51.  
      asp-route-id="@item.ProjectId">Edit</a> |
    52.  
      <a asp-page="./CustomerProjectDelete"
    53.  
       
    54.  
      asp-route-id="@item.ProjectId">Delete</a>
    55.  
      </td>
    56.  
      </tr>
    57.  
      }
    58.  
      </table>
    59.  
      </dd>
    60.  
      </dl>
    61.  
      </div>
    62.  
       
    63.  
      <div>
    64.  
      <a asp-page="CustomerProjectCreate" asp-route-id="@Model.Customer.CustomerId">
    65.  
      Create New Project</a> |
    66.  
      <a asp-page="./Index">Back to List</a>
    67.  
      </div>

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

    <a asp-page="CustomerProjectCreate" asp-route-id="@Model.Customer.CustomerId">Create New Project</a> |

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

    修改了~PagesCustomersCustomerProjects.cshtml.cs

    1.  
      using System.Threading.Tasks;
    2.  
      using Microsoft.AspNetCore.Mvc;
    3.  
      using Microsoft.AspNetCore.Mvc.RazorPages;
    4.  
      using Microsoft.EntityFrameworkCore;
    5.  
      using QuantumWeb.Data;
    6.  
      using QuantumWeb.Model;
    7.  
       
    8.  
      namespace QuantumWeb.Pages.Customers
    9.  
      {
    10.  
      public class CustomerProjectsModel : PageModel
    11.  
      {
    12.  
      private readonly QuantumDbContext _context;
    13.  
       
    14.  
      public CustomerProjectsModel(QuantumDbContext context)
    15.  
      {
    16.  
      _context = context;
    17.  
      } // end public CustomerProjectsModel(QuantumDbContext context)
    18.  
       
    19.  
      public Customer Customer { get; set; }
    20.  
       
    21.  
      public async Task<IActionResult> OnGet(int? id)
    22.  
      {
    23.  
      if (id == null)
    24.  
      {
    25.  
      return NotFound();
    26.  
      } // endif (id == null)
    27.  
       
    28.  
      Customer = await _context.Customers
    29.  
      .Include(c => c.Projects)
    30.  
      .FirstOrDefaultAsync(c => c.CustomerId == id);
    31.  
       
    32.  
      if (Customer == null)
    33.  
      {
    34.  
      return NotFound();
    35.  
      } // endif (Customer == null)
    36.  
       
    37.  
      return Page();
    38.  
      } // end public async Task<IActionResult> OnGet(int? id)
    39.  
       
    40.  
      } // end public class CustomerProjectsModel : PageModel
    41.  
       
    42.  
      } // end namespace QuantumWeb.Pages.Customers

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

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

    https://img-blog.csdnimg.cn/20181228195522645

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

    https://img-blog.csdnimg.cn/20181227224121669

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

    搭建Customers/CustomerProjectCreate Razor页面:

    https://img-blog.csdnimg.cn/2018122722531162

    Initial~PagesCustomersCustomerProjectCreate.cshtml.cs

    1.  
      using System.Threading.Tasks;
    2.  
      using Microsoft.AspNetCore.Mvc;
    3.  
      using Microsoft.AspNetCore.Mvc.RazorPages;
    4.  
      using Microsoft.AspNetCore.Mvc.Rendering;
    5.  
      using Microsoft.EntityFrameworkCore;
    6.  
      using QuantumWeb.Data;
    7.  
      using QuantumWeb.Model;
    8.  
       
    9.  
      namespace QuantumWeb.Pages.Customers
    10.  
      {
    11.  
      public class CustomerProjectCreateModel : PageModel
    12.  
      {
    13.  
      private readonly QuantumDbContext _context;
    14.  
       
    15.  
      public CustomerProjectCreateModel(QuantumDbContext context)
    16.  
      {
    17.  
      _context = context;
    18.  
      } // end public CustomerProjectCreateModel(QuantumContext context)
    19.  
       
    20.  
      [BindProperty]
    21.  
      public Customer Customer { get; set; }
    22.  
       
    23.  
      public async Task<IActionResult> OnGet(int? id)
    24.  
      {
    25.  
      if (id == null)
    26.  
      {
    27.  
      return NotFound();
    28.  
      } // endif (id == null)
    29.  
       
    30.  
      Customer = await _context.Customers
    31.  
      .Include(c => c.Projects)
    32.  
      .FirstOrDefaultAsync(c => c.CustomerId == id);
    33.  
       
    34.  
      if (Customer == null)
    35.  
      {
    36.  
      return NotFound();
    37.  
      } // endif (Customer == null)
    38.  
       
    39.  
      ViewData["ProjectStateCode"] = new SelectList(_context.ProjectStateDescriptions,
    40.  
      "ProjectStateCode", "StateDescription", ProjectState.Prospect);
    41.  
       
    42.  
      return Page();
    43.  
       
    44.  
      } // end public async Task<IActionResult> OnGet(int? id)
    45.  
       
    46.  
      [BindProperty]
    47.  
      public Project Project { get; set; }
    48.  
       
    49.  
      public async Task<IActionResult> OnPostAsync()
    50.  
      {
    51.  
      if (!ModelState.IsValid)
    52.  
      {
    53.  
      return Page();
    54.  
      } // endif (!ModelState.IsValid)
    55.  
       
    56.  
      Project.CustomerId = Customer.CustomerId;
    57.  
       
    58.  
      _context.Projects.Add(Project);
    59.  
      await _context.SaveChangesAsync();
    60.  
       
    61.  
      return RedirectToPage("./CustomerProjects", new { id = Customer.CustomerId });
    62.  
      } // end public async Task<IActionResult> OnPostAsync()
    63.  
       
    64.  
      } // end public class CustomerProjectCreateModel : PageModel
    65.  
       
    66.  
      } // end namespace QuantumWeb.Pages.Customers

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

    1.  
      [BindProperty]
    2.  
      public Customer Customer { get; set; }

    该[BindProperty]将Customer实例绑定到UI的元素,以便在浏览器和Web服务器之间保留它们的值。另请注意,此属性也适用于Project实例。

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

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

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

    ViewData是一个无类型的键值字典,用于在CustomerProjectCreateModel类(在.cshtml.cs文件中)和.cshtml文件中的HTML 之间传递值。这类似于MVC中将数据从Controller 传递到View,在使用ViewData中,数据仅在HTTP请求中持久存在。其成员由ProjectStateDescriptions数据库表中的查询填充。在这种情况下,_context.ProjectStateDescriptions是IEnumerable<ProjectStateDescription>从查询返回的。ProjectStateCode是表中的主键,表示ViewData字典中的键。StateDescription成为ViewData字典中的关联值。ViewData将用来填充在CustomerProjectCreate.cshtml(见下文)中的<select>元素。ProjectState.Prospect是为<select>从ProjectState enum中默认选择的值。您可以阅读更多ViewData信息在以下链接上 https://www.tektutorialshub.com/viewbag-viewdata-asp-net-core/。(译者注:需要在ProjectStateDescriptions数据库表中手动加入数据,具体可见下图展示的数据加,ProjectStateCode字段的值就是对应枚举中的值--定义在代码中的名称。如此值为Completed,StateDescription字段值为project is complete,以此类推)

    初始化~Pages CustomersCustomerProjectCreate.cshtml

    1.  
      @page
    2.  
      @model QuantumWeb.Pages.Customers.CustomerProjectCreateModel
    3.  
      @{
    4.  
      ViewData["Title"] = "Create Customer Project";
    5.  
      }
    6.  
       
    7.  
      <h2>Create Customer Project</h2>
    8.  
      <hr />
    9.  
      <dl class="dl-horizontal">
    10.  
      <dt>
    11.  
      @Html.DisplayNameFor(model => model.Customer.CustomerId)
    12.  
      </dt>
    13.  
      <dd>
    14.  
      @Html.DisplayFor(model => model.Customer.CustomerId)
    15.  
      </dd>
    16.  
      <dt>
    17.  
      @Html.DisplayNameFor(model => model.Customer.CustomerName)
    18.  
      </dt>
    19.  
      <dd>
    20.  
      @Html.DisplayFor(model => model.Customer.CustomerName)
    21.  
      </dd>
    22.  
      </dl>
    23.  
      <div class="row">
    24.  
      <div class="col-md-4">
    25.  
      <form method="post">
    26.  
      <div asp-validation-summary="ModelOnly" class="text-danger"></div>
    27.  
      <input type="hidden" asp-for="Customer.CustomerId" />
    28.  
      <div class="form-group">
    29.  
      <label asp-for="Project.ProjectName" class="control-label"></label>
    30.  
      <input asp-for="Project.ProjectName" class="form-control">
    31.  
      </div>
    32.  
      <div class="form-group">
    33.  
      <label asp-for="Project.ProjectStateCode" class="control-label"></label>
    34.  
      <select asp-for="Project.ProjectStateCode" class="form-control"
    35.  
       
    36.  
      asp-items="ViewBag.ProjectStateCode">
    37.  
      </select>
    38.  
      </div>
    39.  
      <div class="form-group">
    40.  
      <input type="submit" value="Create" class="btn btn-default" />
    41.  
      </div>
    42.  
      </form>
    43.  
      </div>
    44.  
      </div>
    45.  
       
    46.  
      <div>
    47.  
      <a asp-page="CustomerProjects" asp-route-id="@Model.Customer.CustomerId">
    48.  
      Back to Customer Projects
    49.  
      </a>
    50.  
      </div>
    51.  
       
    52.  
      @section Scripts {
    53.  
      @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
    54.  
      }

    关键要素如下:

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

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

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

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

    初始化 ~PagesCustomersCustomerProjectCreate.cshtml

    https://img-blog.csdnimg.cn/20181228195522684

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

    CustomerProjectCreate 包含数据的页面:

    https://img-blog.csdnimg.cn/20181228195522740

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

    客户Projects页面添加Project:

    https://img-blog.csdnimg.cn/20181228195522787

    接下来的两个图显示了为两个Customers添加其他Projects之后的情况。

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

    https://img-blog.csdnimg.cn/20181227224121714

    客户项目页面包含Polyolefin Processing, Inc.的3个项目

    https://img-blog.csdnimg.cn/20181228195522829

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

    搭建 Customers/CustomerProjectEdit Razor Page

    https://img-blog.csdnimg.cn/20181228195522869

    初始化~PagesCustomersCustomerProjectEdit.cshtml.cs

    1.  
      using System.Threading.Tasks;
    2.  
      using Microsoft.AspNetCore.Mvc;
    3.  
      using Microsoft.AspNetCore.Mvc.RazorPages;
    4.  
      using Microsoft.AspNetCore.Mvc.Rendering;
    5.  
      using Microsoft.EntityFrameworkCore;
    6.  
      using QuantumWeb.Data;
    7.  
      using QuantumWeb.Model;
    8.  
       
    9.  
      namespace QuantumApp.Pages.Customers
    10.  
      {
    11.  
      public class CustomerProjectEditModel : PageModel
    12.  
      {
    13.  
      private readonly QuantumDbContext _context;
    14.  
       
    15.  
      public CustomerProjectEditModel(QuantumDbContext context)
    16.  
      {
    17.  
      _context = context;
    18.  
      } // end public CustomerProjectEditModel(QuantumDbContext context)
    19.  
       
    20.  
      [BindProperty]
    21.  
      public Customer Customer { get; set; }
    22.  
      [BindProperty]
    23.  
      public Project Project { get; set; }
    24.  
       
    25.  
      public async Task<IActionResult> OnGet(int? id)
    26.  
      {
    27.  
      if (id == null)
    28.  
      {
    29.  
      return NotFound();
    30.  
      } // endif (id == null)
    31.  
       
    32.  
      Project = await _context.Projects
    33.  
      .Include(p => p.Customer)
    34.  
      .FirstOrDefaultAsync(p => p.ProjectId == id);
    35.  
       
    36.  
      if (Project == null)
    37.  
      {
    38.  
      return NotFound();
    39.  
      } // endif (Project == null)
    40.  
       
    41.  
      Customer = Project.Customer;
    42.  
       
    43.  
      ViewData["ProjectStateCode"] = new SelectList(_context.ProjectStateDescriptions,
    44.  
      "ProjectStateCode", "StateDescription", ProjectState.Prospect);
    45.  
       
    46.  
      return Page();
    47.  
      } // end public async Task<IActionResult> OnGet(int? id)
    48.  
       
    49.  
      public async Task<IActionResult> OnPostAsync(int? id)
    50.  
      {
    51.  
      if (!ModelState.IsValid)
    52.  
      {
    53.  
      return Page();
    54.  
      } // endif (!ModelState.IsValid)
    55.  
       
    56.  
      var projectToUpdate = await _context.Projects.FindAsync(id);
    57.  
       
    58.  
      if (projectToUpdate == null)
    59.  
      {
    60.  
      return NotFound();
    61.  
      } // endif (projectToUpdate == null)
    62.  
       
    63.  
      projectToUpdate.CustomerId = Customer.CustomerId;
    64.  
       
    65.  
      if (await TryUpdateModelAsync<Project>(
    66.  
      projectToUpdate,
    67.  
      "project",
    68.  
      p => p.ProjectName, p => p.ProjectStateCode))
    69.  
      {
    70.  
      await _context.SaveChangesAsync();
    71.  
      return RedirectToPage("./CustomerProjects", new { id = Customer.CustomerId });
    72.  
      }
    73.  
       
    74.  
      return Page();
    75.  
      } // end public async Task<IActionResult> OnPostAsync(int? id)
    76.  
       
    77.  
      } // end public class CustomerProjectEditModel : PageModel
    78.  
       
    79.  
      } // end namespace QuantumApp.Pages.Customers

    此代码与CustomerProjectCreate页面在.Include和ViewData方面具有相同的构件。

    初始化~PagesCustomersCustomerProjectEdit.cshtml

    1.  
      @page "{id:int?}"
    2.  
      @model QuantumWeb.Pages.Customers.CustomerProjectEditModel
    3.  
      @{
    4.  
      ViewData["Title"] = "Edit Customer Project";
    5.  
      }
    6.  
       
    7.  
      <h2>Edit Customer Project</h2>
    8.  
      <hr />
    9.  
      <dl class="dl-horizontal">
    10.  
      <dt>
    11.  
      @Html.DisplayNameFor(model => model.Customer.CustomerId)
    12.  
      </dt>
    13.  
      <dd>
    14.  
      @Html.DisplayFor(model => model.Customer.CustomerId)
    15.  
      </dd>
    16.  
      <dt>
    17.  
      @Html.DisplayNameFor(model => model.Customer.CustomerName)
    18.  
      </dt>
    19.  
      <dd>
    20.  
      @Html.DisplayFor(model => model.Customer.CustomerName)
    21.  
      </dd>
    22.  
      </dl>
    23.  
      <div class="row">
    24.  
      <div class="col-md-4">
    25.  
      <form method="post">
    26.  
      <div asp-validation-summary="ModelOnly" class="text-danger"></div>
    27.  
      <input type="hidden" asp-for="Customer.CustomerId" />
    28.  
      <div class="form-group">
    29.  
      <label asp-for="Project.ProjectName" class="control-label"></label>
    30.  
      <input asp-for="Project.ProjectName" class="form-control">
    31.  
      </div>
    32.  
      <div class="form-group">
    33.  
      <label asp-for="Project.ProjectStateCode" class="control-label"></label>
    34.  
      <select asp-for="Project.ProjectStateCode" class="form-control"
    35.  
       
    36.  
      asp-items="ViewBag.ProjectStateCode">
    37.  
      </select>
    38.  
      </div>
    39.  
      <div class="form-group">
    40.  
      <input type="submit" value="Save" class="btn btn-default" />
    41.  
      </div>
    42.  
      </form>
    43.  
      </div>
    44.  
      </div>
    45.  
       
    46.  
      <div>
    47.  
      <a asp-page="CustomerProjects" asp-route-id="@Model.Customer.CustomerId">
    48.  
      Back to Customer Projects
    49.  
      </a>
    50.  
      </div>
    51.  
       
    52.  
      @section Scripts {
    53.  
      @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
    54.  
      }

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

    Customer Projects 页面包含Mirarex Oil&Gas的2个项目——用于编辑:

    https://img-blog.csdnimg.cn/20181227224121750

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

    https://img-blog.csdnimg.cn/20181228195522919

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

    https://img-blog.csdnimg.cn/20181227224121795

    通过CustomerProjectDelete页面,此项目的最后一个功能是删除。

    搭建 Customers/CustomerProjectDelete Razor页面:

    https://img-blog.csdnimg.cn/20181227225311112

    初始化~PagesCustomersCustomerProjectDelete.cshtml.cs

    1.  
      using System.Threading.Tasks;
    2.  
      using Microsoft.AspNetCore.Mvc;
    3.  
      using Microsoft.AspNetCore.Mvc.RazorPages;
    4.  
      using Microsoft.EntityFrameworkCore;
    5.  
      using QuantumWeb.Data;
    6.  
      using QuantumWeb.Model;
    7.  
       
    8.  
      namespace QuantumWeb.Pages.Customers
    9.  
      {
    10.  
      public class CustomerProjectDeleteModel : PageModel
    11.  
      {
    12.  
      private readonly QuantumDbContext _context;
    13.  
       
    14.  
      public CustomerProjectDeleteModel(QuantumDbContext context)
    15.  
      {
    16.  
      _context = context;
    17.  
      } // end public CustomerProjectDeleteModel(QuantumContext context)
    18.  
       
    19.  
      [BindProperty]
    20.  
      public Customer Customer { get; set; }
    21.  
      [BindProperty]
    22.  
      public Project Project { get; set; }
    23.  
       
    24.  
      public async Task<IActionResult> OnGetAsync(int? id)
    25.  
      {
    26.  
      if (id == null)
    27.  
      {
    28.  
      return NotFound();
    29.  
      } // endif (id == null)
    30.  
       
    31.  
      Project = await _context.Projects
    32.  
      .Include(p => p.Customer)
    33.  
      .FirstOrDefaultAsync(p => p.ProjectId == id);
    34.  
       
    35.  
      if (Project == null)
    36.  
      {
    37.  
      return NotFound();
    38.  
      } // endif (Project == null)
    39.  
       
    40.  
      Customer = Project.Customer;
    41.  
       
    42.  
      return Page();
    43.  
      } // end public async Task<IActionResult> OnGet(int? id)
    44.  
       
    45.  
      public async Task<IActionResult> OnPostAsync(int? id)
    46.  
      {
    47.  
      if (id == null)
    48.  
      {
    49.  
      return NotFound();
    50.  
      } // endif (id == null)
    51.  
       
    52.  
      Project = await _context.Projects
    53.  
      .Include(p => p.Customer)
    54.  
      .FirstOrDefaultAsync(p => p.ProjectId == id);
    55.  
       
    56.  
      if (Project != null)
    57.  
      {
    58.  
      _context.Projects.Remove(Project);
    59.  
      await _context.SaveChangesAsync();
    60.  
      } // endif (Project != null)
    61.  
       
    62.  
      return RedirectToPage("./CustomerProjects", new { id = Project.Customer.CustomerId });
    63.  
      } // end public async Task<IActionResult> OnPostAsync(int? id)
    64.  
       
    65.  
      } // end public class CustomerProjectDeleteModel : PageModel
    66.  
       
    67.  
      } // end namespace QuantumWeb.Pages.Customer

    初始化~PagesCustomersCustomerProjectDelete.cshtml

    1.  
      @page "{id:int?}"
    2.  
      @model QuantumWeb.Pages.Customers.CustomerProjectDeleteModel
    3.  
      @{
    4.  
      ViewData["Title"] = "Delete Customer Project";
    5.  
      }
    6.  
       
    7.  
      <h2>Delete Customer Project</h2>
    8.  
       
    9.  
      <h3>Are you sure you want to delete this?</h3>
    10.  
      <div>
    11.  
      <dl class="dl-horizontal">
    12.  
      <dt>
    13.  
      @Html.DisplayNameFor(model => model.Customer.CustomerName)
    14.  
      </dt>
    15.  
      <dd>
    16.  
      @Html.DisplayFor(model => model.Customer.CustomerName)
    17.  
      </dd>
    18.  
      <dt>
    19.  
      @Html.DisplayNameFor(model => model.Project.ProjectId)
    20.  
      </dt>
    21.  
      <dd>
    22.  
      @Html.DisplayFor(model => model.Project.ProjectId)
    23.  
      </dd>
    24.  
      <dt>
    25.  
      @Html.DisplayNameFor(model => model.Project.ProjectName)
    26.  
      </dt>
    27.  
      <dd>
    28.  
      @Html.DisplayFor(model => model.Project.ProjectName)
    29.  
      </dd>
    30.  
      <dt>
    31.  
      @Html.DisplayNameFor(model => model.Project.ProjectStateCode)
    32.  
      </dt>
    33.  
      <dd>
    34.  
      @Html.DisplayFor(model => model.Project.ProjectStateCode)
    35.  
      </dd>
    36.  
      </dl>
    37.  
       
    38.  
      <form method="post">
    39.  
      <input type="hidden" asp-for="Project.ProjectId" />
    40.  
      <a asp-page="CustomerProjects" asp-route-id="@Model.Customer.CustomerId">
    41.  
      Back to Customer Projects
    42.  
      </a> |
    43.  
      <input type="submit" value="Delete" class="btn btn-default" />
    44.  
      </form>
    45.  
      </div>

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

    https://img-blog.csdnimg.cn/20181227224121848

    删除客户项目页面——删除Ouachita Shale:

    https://img-blog.csdnimg.cn/20181227225311154

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

    https://img-blog.csdnimg.cn/20181227224121888

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

    Customers, Projects, ProjectStates

    CustomerId

    Customer Name

    ProjectId

    Project Name

    ProjectStateCode

    StateDescription

    1

    Mirarex Oil & Gas, LLC

    1

    Zolar Pipeline

    UnderReview

    Project is under review and negotiation

    1

    Mirarex Oil & Gas, LLC

    2

    Nelar Ranch Gas Fracturing

    Prospect

    Prospective or referred project

    2

    Polyolefin Processing, Inc.

    3

    Port Gibson Plant Expansion

    Prospect

    Prospective or referred project

    2

    Polyolefin Processing, Inc.

    4

    Jackson Plant Control System Upgrade

    Prospect

    Prospective or referred project

    2

    Polyolefin Processing, Inc.

    5

    Eutaw Plant Shutdown & Maintenance

    Prospect

    Prospective or referred project

    下面可以进入第四部分进行学习。 

     https://blog.csdn.net/mzl87/article/details/85312583

    原文地址:https://www.codeproject.com/Articles/1264330/ASP-NET-Core-Razor-Pages-Using-EntityFramework-C-2

  • 相关阅读:
    COM 组件创建实例失败,原因是出现以下错误: c001f011 (Microsoft.SqlServer.ManagedDTS)
    df: `/root/.gvfs': Permission denied
    ora-03113 end-of-file on communication channel 故障处理
    ESXi克隆虚拟机时网卡需要重新设置的问题
    Spark重点难点知识总结
    Hive,Hive on Spark和SparkSQL区别
    Spark分区数、task数目、core数目、worker节点数目、executor数目梳理
    spark RDD中的partition和hdfs中的block的关系
    Spark容错机制
    【干货】大数据框架整理
  • 原文地址:https://www.cnblogs.com/webenh/p/13140541.html
Copyright © 2011-2022 走看看