ASP.NET Core 中文文檔 第二章 指南(4.4)添加 Model


原文:Adding a model
作者:Rick Anderson
翻譯:婁宇(Lyrics)
校對:許登洋(Seay)孟帥洋(書緣)姚阿勇(Mr.Yao)夏申斌

在這一節里,你將添加一些類來管理數據庫中的電影數據。這些類將成為 MVC 應用程序中的 “Model” 部分。

你將使用 .NET Framework 中名為 Entity Framework Core 的數據庫訪問技術來定義和使用這些數據模型類。Entity Framework Core (通常被稱為 EF Core) 有一種具有特色的被稱為 Code First 的開發模式。你先編寫代碼,然后通過這些代碼創建數據庫表。 Code First 允許你通過編寫一些簡單的類(也被稱為 POCO 類, "plain-old CLR objects." )來創建數據模型對象,然后根據你的類創建數據庫。如果你需要先創建數據庫,你仍然可以按照本教程來學習 MVC 和 EF 應用程序開發。

使用個人用戶賬戶身份認證創建新項目

在 Visual Studio 當前版本的 ASP.NET Core MVC 工具中,僅在以個人用戶賬戶身份認證方式創建新項目時支持通過基架生成模型。我們希望在下一個工具更新中修復這個問題。直到問題被修復之前,你需要以相同的名稱創建新項目。因為項目有相同的名字,你需要在其他的文件夾中創建。

在 Visual studio 起始頁(Start Page),點擊 新建項目(New Project)

或者,你可以使用菜單來創建新項目。點擊 文件(File)> 新建(New) > 項目(Project)

完成 新建項目(New Project) 對話框:

  • 在左窗格,點擊 Web
  • 在中間窗格,點擊 ASP.NET Core Web Application (.NET Core)
  • 將位置更改為你創建的前一個項目的不同目錄,否則你將遇到錯誤
  • 命名項目為“MvcMovie”(將項目命名為“MvcMovie”非常重要,當你復制代碼時,命名空間將會匹配)
  • 點擊 確定(OK)

警告
在本教程中,你必須將 身份驗證(Authentication) 設置為 個人用戶賬戶(Individual User Accounts) ,以便基架引擎能正常工作(譯者注:不同的身份認證通過基架引擎生成的代碼不一樣,為了教程順利進行,此處必須選用個人用戶賬戶的認證方式)。

New ASP.NET Core Web Application - MvcMovie 對話框中:

  • 點擊 Web 應用程序(Web Application)
  • 點擊 更改身份驗證(Change Authentication) 按鈕並將身份驗證改為 Individual User Accounts(個人用戶賬戶) 之后點擊 確定(OK)

按照 change-title-link-reference-label 的指示你可以點擊 MvcMovie 鏈接來調用 Movie 控制器(Controller)。我們將在本教程中通過基架生成 Movie 控制器(Controller)。

添加數據模型類

在解決方案資源管理器中,右鍵點擊 Models 文件夾 > 添加 > 。將類名命名為 Movie 並且添加以下屬性:

using System;

namespace MvcMovie.Models
{
    public class Movie
    {
        public int ID { get; set; }  //手動高亮
        public string Title { get; set; }
        public DateTime ReleaseDate { get; set; }
        public string Genre { get; set; }
        public decimal Price { get; set; }
    }
}

除了你用來構造電影的屬性,還需要一個 ID 字段來作為數據庫主鍵。生成項目。如果你沒有生成這個應用程序,你將在下一節中遇到錯誤。我們終於為這個 MVC 應用程序添加了一個 Model 。

通過基架生成一個控制器(Controller)

解決方案資源管理器 中,右鍵點擊 Controllers 文件夾 > 添加 > 控制器

添加基架 對話框中,點擊 MVC Controller with views, using Entity Framework > 添加

完成 添加控制器(Add Controller) 對話框

  • 模型類(Model class): Movie(MvcMovie.Models)
  • 數據上下文類(Data context class): ApplicationDbContext(MvcMovie.Models)
  • 視圖(Views): 保持默認的選項
  • 控制器名稱(Controller name): 保持默認的 MoviesController
  • 點擊 添加(Add)

Visual Studio 基架引擎創建的東西如下:

  • 一個電影控制器(Controller)(Controllers/MoviesController.cs
  • Create、Delete、Details、Edit 以及 Index 的 Razor 視圖文件(Views/Movies)

Visual Studio 為你自動創建 CRUD(創建、讀取、更新以及刪除)Action 方法和視圖(View)(自動創建 CRUD Action 方法和 View 視圖被稱為 搭建基架(scaffolding))。很快你將擁有一個可以讓你創建、查看、編輯以及刪除電影條目的完整功能的 Web 應用程序。

運行這個應用程序並且點擊 Mvc Movie 鏈接。你將遇到以下錯誤:

我們將按照這些指示來為 Movie 應用程序准備好數據庫。

更新數據庫

警告
你必須在更新數據庫之前停止 IIS Express。

停止 IIS Express:

  • 右鍵點擊通知區域的 IIS Express 系統托盤圖標

  • 點擊 退出(Exit) 或者 停止站點(Stop Site)

  • 除此之外, 你可以退出並重啟 Visual Studio

  • 在項目文件夾(MvcMovie/src/MvcMovie)打開命令提示符。按照以下說明,以一個快捷的方式打開項目文件夾

    • 打開一個在項目根目錄下的文件(在這個例子中,使用 Startup.cs )。
    • 右鍵點擊 Startup.cs > 打開所在的文件夾(Open Containing Folder)

    • Shift + 右鍵點擊一個文件夾 > 在此處打開命令窗口(Open command window here)

    • 運行 cd .. 將路徑退回項目文件夾
  • 在命令提示符中運行以下命令:

  dotnet ef migrations add Initial
  dotnet ef database update

注意
如果 IIS-Express 在運行中,你會遇到錯誤 CS2012: Cannot open 'MvcMovie/bin/Debug/netcoreapp1.0/MvcMovie.dll' for writing -- 'The process cannot access the file 'MvcMovie/bin/Debug/netcoreapp1.0/MvcMovie.dll' because it is being used by another process.'

dotnet ef 命令

  • dotnet (.NET Core) 是 .NET 的跨平台實現。你可以在這里了解它。
  • dotnet ef migrations add Initial 運行 Entity Framework .NET Core CLI 遷移命令並創建初始化遷移。參數 "Initial" 可以是任意值,但是通常用這個作為第一個(初始的) 數據庫遷移。這個操作創建了一個 Data/Migrations/ _Initial.cs 文件,這個文件包含了添加(或刪除)Movie 表到數據庫的遷移命令。
  • dotnet ef database update dotnet ef database update 用我們剛剛創建的遷移來更新數據庫。

測試一下

注意
如果你的瀏覽器不能連接到 Movie 應用程序,你可能需要等待 IIS Express 加載它。它有時需要 30 秒來構建應用程序並准備好響應請求。

  • 運行應用程序並點擊 Mvc Movie 鏈接
  • 點擊 Create New 鏈接並創建電影

注意
你也許不能在 Price 字段中輸入小數點或逗號。為了實現對非英語環境中用逗號(",")來表示小數點,以及非美國英語日期格式的 jQuery 驗證,你必須采取措施國際化你的應用程序。查看額外的資源獲取更多的信息。現在僅僅輸入完整的數字,比如10。


注意
在某些地區你需要指定日期格式。查看下方高亮代碼。

點擊 Create 提交表單到服務器,將電影數據保存到數據庫中。然后重定向到 /Movies URL ,你可以在列表中看到新創建的電影。

using System;
using System.ComponentModel.DataAnnotations; //手動高亮

namespace MvcMovie.Models
{
    public class Movie
    {
        public int ID { get; set; }
        public string Title { get; set; }
        [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)] //手動高亮
        public DateTime ReleaseDate { get; set; }
        public string Genre { get; set; }
        public decimal Price { get; set; }
    }
}

再創建幾個電影條目。嘗試 EditDetailsDelete 鏈接來執行各個功能。

檢查生成的代碼

打開 Controllers/MoviesController.cs 文件並檢查生成的 Index 方法。 MoviesController 中包含 Index 方法的部分如下所示:

public class MoviesController : Controller
{
    private readonly ApplicationDbContext _context;

    public MoviesController(ApplicationDbContext context)
    {
        _context = context;
    }

    // GET: Movies
    public async Task<IActionResult> Index()
    {
        return View(await _context.Movie.ToListAsync());
    }

構造函數使用依賴注入將數據庫上下文注入到控制器(Controller)。 數據上下文在控制器(Controller)中被用來執行增刪改查(CRUD)方法。

一個到 MoviesController 的請求從 Movies 表返回所有的條目,然后傳遞數據到 Index 視圖 (View) 。

強類型模型與 @model 關鍵字

在之前的教程中,你看到了控制器(Controller)如何通過 ViewData 字典傳遞數據到一個視圖(View)。 ViewData 字典是一個動態類型對象,它提供了一種便捷的后期綁定方式將信息傳遞給視圖。

MVC 也提供了傳遞強類型數據給視圖的能力。這種強類型的方式可以提供給你更好的代碼編譯時檢查,並在 Visual Studio(VS) 中具有更豐富的智能感知。VS 中的基架機制在為 MoviesController 類創建方法(Action)和視圖(View)的時候就采用了這種方式(即,傳遞強類型模型)。

檢查在 Controllers/MoviesController.cs 文件中生成的 Details 方法:

// GET: Movies/Details/5
public async Task<IActionResult> Details(int? id)
{
    if (id == null)
    {
        return NotFound();
    }

    var movie = await _context.Movie.SingleOrDefaultAsync(m => m.ID == id);
    if (movie == null)
    {
        return NotFound();
    }

    return View(movie);
}

id 參數一般作為路由數據傳遞,例如 http://localhost:1234/movies/details/1 將:

  • Controller 設置為 movies(對應第一個 URL 段)
  • Action 設置為 details(對應第二個 URL 段)
  • id 設置為 1(對應最后一個 URL 段)

你也可以向下面一樣通過查詢字符串(Query String)傳遞 id

http://localhost:1234/movies/details?id=1

如果電影被找到了, Movie 模型(Model)的實例將被傳遞給 Details 視圖(View)。

  return View(movie);

檢查 Views/Movies/Details.cshtml 文件的內容:

@model MvcMovie.Models.Movie  <!--手動高亮-->

@{
    ViewData["Title"] = "Details";
}

<h2>Details</h2>

<div>
    <h4>Movie</h4>
    <hr />
    <dl class="dl-horizontal">
        <dt>
            @Html.DisplayNameFor(model => model.Genre)
        </dt>
        <dd>
            @Html.DisplayFor(model => model.Genre)
        </dd>
        <dt>
            @Html.DisplayNameFor(model => model.Price)
        </dt>
        <dd>
            @Html.DisplayFor(model => model.Price)
        </dd>
        <dt>
            @Html.DisplayNameFor(model => model.ReleaseDate)
        </dt>
        <dd>
            @Html.DisplayFor(model => model.ReleaseDate)
        </dd>
        <dt>
            @Html.DisplayNameFor(model => model.Title)
        </dt>
        <dd>
            @Html.DisplayFor(model => model.Title)
        </dd>
    </dl>
</div>
<div>
    <a asp-action="Edit" asp-route-id="@Model.ID">Edit</a> |
    <a asp-action="Index">Back to List</a>
</div>

通過在視圖(View Template)文件頂部加入一個 @model 語句,你可以指定視圖(View)所期望的對象類型。當你創建這個 MoviesController 時, Visual Studio 自動在 Details.cshtml 頂部加入了 @model 語句后面的部分。

  @model MvcMovie.Models.Movie

@model 指令允許你訪問從控制器(Controller)傳遞給視圖(View)的這個強類型電影 Model 對象。例如,在 Details.cshtml 視圖中,代碼用強類型 Model 對象傳遞所有的電影字段到 DisplayNameForDisplayFor HTML 幫助類(HTML Helper)里。 CreateEdit 方法和視圖(View)也傳遞一個 Movie 模型(Model)對象。

檢查 Index.cshtml 視圖(View)和 MoviesController 里的 Index 方法。注意觀察代碼在調用 View 方法時,是如何創建一個 列表(List) 對象的。這段代碼將 Movies 列表從 Index Action 方法傳遞給視圖(View):

public async Task<IActionResult> Index()
{
    return View(await _context.Movie.ToListAsync());
}

當你創建這個 MoviesController 時,Visual Studio 自動在 Index.cshtml 頂部加入以下 @model 語句:

@model IEnumerable<MvcMovie.Models.Movie>

@model 指令允許你訪問電影列表這個從控制器(Controller)傳遞給視圖(View)的強類型 Model 對象。例如,在 Index.cshtml 視圖中,代碼通過 foreach 語句遍歷了電影列表這個強類型的 模型(Model) 對象。

@model IEnumerable<MvcMovie.Models.Movie>   <!--手動高亮-->

@{
    ViewData["Title"] = "Index";
}

<h2>Index</h2>
<p>
    <a asp-action="Create">Create New</a>
</p>

<table class="table">
    <thead>
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.Genre)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Price)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.ReleaseDate)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Title)
            </th>
            <th></th>
        </tr>
    </thead>
    <tbody>
@foreach (var item in Model) {    <!--手動高亮-->
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.Genre)   <!--手動高亮-->
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Price)   <!--手動高亮-->
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.ReleaseDate)   <!--手動高亮-->
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Title)   <!--手動高亮-->
            </td>
            <td>
                <a asp-action="Edit" asp-route-id="@item.ID">Edit</a> |         <!--手動高亮-->
                <a asp-action="Details" asp-route-id="@item.ID">Details</a> |   <!--手動高亮-->
                <a asp-action="Delete" asp-route-id="@item.ID">Delete</a>       <!--手動高亮-->
            </td>
        </tr>
}
    </tbody>
</table>

因為 模型(Model) 對象是強類型的(作為 IEnumerable<Movie> 對象),循環中的每一個 item 的類型被類型化為 Movie 。除了其他好處外,這意味着你將獲得代碼的編譯時檢查以及在代碼編輯器里得到完整的智能感知支持:

現在你有了數據庫和用於顯示、編輯、更新以及刪除數據的頁面。在下一篇教程中,我們將學習使用數據庫。

額外的資源

修訂歷史

  1. 2016/07/08,MS1;
  2. 2016/07/09,修訂至 1.0.0

返回目錄


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM