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; }
}
}
再创建几个电影条目。尝试 Edit 、 Details 、 Delete 链接来执行各个功能。
检查生成的代码
打开 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
对象传递所有的电影字段到 DisplayNameFor
和 DisplayFor
HTML 帮助类(HTML Helper)里。 Create
和 Edit
方法和视图(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
。除了其他好处外,这意味着你将获得代码的编译时检查以及在代码编辑器里得到完整的智能感知支持:
现在你有了数据库和用于显示、编辑、更新以及删除数据的页面。在下一篇教程中,我们将学习使用数据库。
额外的资源
修订历史
- 2016/07/08,MS1;
- 2016/07/09,修订至 1.0.0
- 修订人:娄宇(Lyrics)
- 校对人:孟帅洋(书缘)
ASP.NET Core 中文文档 第二章 指南(4.4)添加 Model的更多相关文章
- ASP.NET Core 中文文档 第二章 指南(4.6)Controller 方法与视图
原文:Controller methods and views 作者:Rick Anderson 翻译:谢炀(Kiler) 校对:孟帅洋(书缘) .张仁建(第二年.夏) .许登洋(Seay) .姚阿勇 ...
- ASP.NET Core 中文文档 第二章 指南 (09) 使用 Swagger 生成 ASP.NET Web API 在线帮助测试文档
原文:ASP.NET Web API Help Pages using Swagger 作者:Shayne Boyer 翻译:谢炀(kiler) 翻译:许登洋(Seay) 对于开发人员来说,构建一个消 ...
- ASP.NET Core 中文文档 第二章 指南(1)用 Visual Studio Code 在 macOS 上创建首个 ASP.NET Core 应用程序
原文:Your First ASP.NET Core Application on a Mac Using Visual Studio Code 作者:Daniel Roth.Steve Smith ...
- ASP.NET Core 中文文档 第二章 指南(2)用 Visual Studio 和 ASP.NET Core MVC 创建首个 Web API
原文:Building Your First Web API with ASP.NET Core MVC and Visual Studio 作者:Mike Wasson 和 Rick Anderso ...
- ASP.NET Core 中文文档 第二章 指南(3)用 Visual Studio 发布一个 Azure 云 Web 应用程序
原文:Getting Started 作者:Rick Anderson 翻译:谢炀(Kiler) 校对:孟帅洋(书缘).刘怡(AlexLEWIS).何镇汐 设置开发环境 安装最新版本的 Azure S ...
- ASP.NET Core 中文文档 第二章 指南(4.1)ASP.NET Core MVC 与 Visual Studio 入门
原文:Getting started with ASP.NET Core MVC and Visual Studio 作者:Rick Anderson 翻译:娄宇(Lyrics) 校对:刘怡(Alex ...
- ASP.NET Core 中文文档 第二章 指南(4.5)使用 SQL Server LocalDB
原文:Working with SQL Server LocalDB 作者:Rick Anderson 翻译: 魏美娟(初见) 校对: 孟帅洋(书缘).张硕(Apple).许登洋(Seay) Appl ...
- ASP.NET Core 中文文档 第二章 指南(5) 在 Nano Server 上运行ASP.NET Core
原文 ASP.NET Core on Nano Server 作者 Sourabh Shirhatti 翻译 娄宇(Lyrics) 校对 刘怡(AlexLEWIS).许登洋(Seay).谢炀(kile ...
- ASP.NET Core 中文文档 第二章 指南(8) 使用 dotnet watch 开发 ASP.NET Core 应用程序
原文:Developing ASP.NET Core applications using dotnet watch 作者:Victor Hurdugaci 翻译:谢炀(Kiler) 校对:刘怡(Al ...
随机推荐
- .NET 基础 一步步 一幕幕[面向对象之方法、方法的重载、方法的重写、方法的递归]
方法.方法的重载.方法的重写.方法的递归 方法: 将一堆代码进行重用的一种机制. 语法: [访问修饰符] 返回类型 <方法名>(参数列表){ 方法主体: } 返回值类型:如果不需要写返回值 ...
- SASS教程sass超详细教程
SASS安装及使用(sass教程.详细教程) 采用SASS开发CSS,可以提高开发效率. SASS建立在Ruby的基础之上,所以得先安装Ruby. Ruby的安装: 安装 rubyinstaller- ...
- 在DevExpress程序中使用GridView直接录入数据的时候,增加列表选择的功能
在我上篇随笔<在DevExpress程序中使用Winform分页控件直接录入数据并保存>中介绍了在GridView以及在其封装的分页控件上做数据的直接录入的处理,介绍情况下数据的保存和校验 ...
- js数组去重几种思路
在一些后台语言中都内置了一些方法来处理数组或集合中重复的数据.但是js中并没有类似的方法,网上已经有一些方法,但是不够详细.部分代码来源于网络.个人总计如下:大致有4种思路 1)使用两次循环比较原始的 ...
- atitit.细节决定成败的适合情形与缺点
atitit.细节决定成败的适合情形与缺点 1. 在理论界有两种观点:一种是"细节决定成败",另一种是"战略决定成败".1 1.1. 格局决定成败,方向决定成败 ...
- Atitit.研发管理如何避免公司破产倒闭的业务魔咒
Atitit.如何避免公司破产倒闭的业务魔咒 1. 大型公司的衰落或者倒闭破产案例1 1.1. 摩托罗拉1 1.2. 诺基亚2 1.3. sun2 2. 为什么他们会倒闭?? 常见的一些倒闭元素2 2 ...
- 设计模式之工厂模式VS抽象工厂
一.工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的. 工厂模式在<Java与模式>中分为三类:1)简单工厂模式(Simple Factor ...
- 萌新笔记——vim命令“=”、“d”、“y”的用法(结合光标移动命令,一些场合会非常方便)
vim有许多命令,网上搜有一堆贴子.文章列举出各种功能的命令. 对于"="."d"."y",我在无意中发现了它们所具有的相同的一些用法,先举 ...
- 【一起学OpenFoam】01 OpenFoam的优势
CFD技术发展到今天,已经超过了大半个世纪了,已经涌现出非常多的CFD软件可供人们使用.通用商业CFD软件譬如Fluent.CFX.Star CCM+等在工业上得到了广泛的应用,另外一些专用的软件(如 ...
- mono for android Json 上传文件
void button_Click(object sender, EventArgs e) { string Url = "上传地址,服务器端负责接收"; byte[] fbyte ...