索引:html
目录索引web
Adding a model to an ASP.NET Core MVC app
在 asp.net core mvc 中添加一个model (模型)
2017-3-30 8 分钟阅读时长
本文内容
1. Add a data model class
添加一个数据模型类
2. Scaffolding a controller
控制器基架
3. Add EF tooling and perform initial migration
添加EF工具并作基本迁移
4. Test the app
测试应用
5. Dependency Injection
依赖注入
6. Strongly typed models and the @model keyword
强类型模型与 @model 关键字
7. Additional resources
附加资源
By Rick Anderson and Tom Dykstra
In this section you'll add some classes for managing movies in a database.
在本节,咱们将添加一些类用于在db中管理 movies。
These classes will be the "Model" part of the MVC app.
这些类是 MVC 中的 Model部分。
You’ll use these classes with the Entity Framework Core (EF Core) to work with a database.
咱们将使用 EF core 在DB上操做这些类与数据。
EF Core is an object-relational mapping (ORM) framework that simplifies the data-access code that you have to write.
EF core 是一个对象关系映射框架,能够简化操做数据库所须要写的代码及代码量。
For this tutorial you'll use SQLite, but EF Core supports many database engines.
本教程中咱们使用 SQLite数据库,固然EF core 支持不少种数据库。
The model classes you'll create are known as POCO classes (from "plain-old CLR objects") because they don't have any dependency on EF Core.
咱们将建立一些简单模型类,由于他们对EF core 没有任何依赖。
They just define the properties of the data that will be stored in the database.
仅在类中定义DB中所要存储的字段属性。
In this tutorial you'll write the model classes first, and EF Core will create the database.
在本教程中,咱们采用 Code First 模式,先定义类,再用EF core 建立DB.
An alternate approach not covered here is to generate model classes from an already-existing database.
另外一种作法是DB First 模式,用一个已存在的DB自动生成数据模型类。
For information about that approach, see ASP.NET Core - Existing Database.
查看文章 ASP.NET Core - Existing Database. 以获取更多关于DB First 模式的信息。
Add a data model class
添加一个数据模型类
In Solution Explorer, right click the MvcMovie project > Add > New Folder. Name the folder Models.
在解决方案资源管理器中,右击 MvcMovie 项目 > Add > New Folder 菜单。并命名文件夹为 Models 。
Right click the Models folder > Add > Class. Name the class Movie and add the following properties:
右击 Models 文件夹 > Add > Class 菜单。命名类的名字为Movie ,并在其中添加以下的属性代码:数据库
1 using System; 2 3 namespace MvcMovie.Models 4 { 5 public class Movie 6 { 7 public int ID { get; set; } 8 public string Title { get; set; } 9 public DateTime ReleaseDate { get; set; } 10 public string Genre { get; set; } 11 public decimal Price { get; set; } 12 } 13 }
The ID field is required by the database for the primary key.
ID 字段是数据库要求必须有的主键。
Build the project to verify you don't have any errors. You now have a Model in your MVC app.
编译项目检查确保没有错误。如今咱们在程序中就有了MVC中的M。
Scaffolding a controller
控制器基架
In Solution Explorer, right-click the Controllers folder > Add > Controller.
在解决方案资源管理器中,右击 Controllers 文件夹,选择 > Add > Controller 菜单。express
In the Add MVC Dependencies dialog, select Minimal Dependencies, and select Add.
在Add MVC Dependencies 对话框中,选择 Minimal Dependencies 并点击Add 按钮。bash
Visual Studio adds the dependencies needed to scaffold a controller, but the controller itself is not created.
VS会添加控制器基架所需的依赖项,但控制器如今尚未被建立。
The next invoke of > Add > Controller creates the controller.
继续点击 > Add > Controller 菜单,会添加一个控制器。
In Solution Explorer, right-click the Controllers folder > Add > Controller.
在解决方案资源管理器中,右击 Controllers 文件夹并选择> Add > Controller 菜单。服务器
In the Add Scaffold dialog, tap MVC Controller with views, using Entity Framework > Add.
在 Add Scaffold 对话框中,点击 MVC Controller with views, using Entity Framework 选项并点击Add 按钮。mvc
Complete the Add Controller dialog:
完成 Add Controller 对话框:
• Model class: Movie (MvcMovie.Models)
Model class :Movie (MvcMovie.Models)(前边儿添加的模型类)
• Data context class: Select the + icon and add the default MvcMovie.Models.MvcMovieContext
Data context class :点击 + 按钮并添加默认的 MvcMovie.Models.MvcMovieContext 。app
• Views: Keep the default of each option checked
Views:保持默认的选项选择状态
• Controller name: Keep the default MoviesController
Controller name:保持默认的名字 MoviesController 。
• Tap Add
点击 Add 按钮。框架
Visual Studio creates:
VS将会建立以下项:
• An Entity Framework Core database context class (Data/MvcMovieContext.cs)
一个 EF Core 数据上下文类:Data/MvcMovieContext.cs
• A movies controller (Controllers/MoviesController.cs)
一个控制器类:Controllers/MoviesController.cs
• Razor view files for Create, Delete, Details, Edit and Index pages (Views/Movies/\.cshtml*)
CRUD的视图文件:Views/Movies/\.cshtml*
The automatic creation of the database context and CRUD (create, read, update, and delete) action methods and views is known as scaffolding.
自动建立 DB上下文类,CRUD 控制器 方法及相应视图的工具是一个 被称为基架。
You'll soon have a fully functional web application that lets you manage a movie database.
你立刻就会有一个完整功能的web应用,可让你管理一个 movie DB。
If you run the app and click on the Mvc Movie link, you'll get an error similar to the following:
若是你运行应用并点击 Mvc Movie 连接,你会看到以下一个错误提示:asp.net
An unhandled exception occurred while processing the request. SqlException: Cannot open database "MvcMovieContext-<GUID removed>" requested by the login. The login failed. Login failed for user Rick
You need to create the database, and you'll use the EF Core Migrations feature to do that.
你须要建立一个DB,咱们将用EF Core的Migrations 特性来实现。
Migrations lets you create a database that matches your data model and update the database schema when your data model changes.
Migrations 特性可让你由项目中的Models建立一个DB,而且当model变化时会将变化同步到DB结构中。
Add EF tooling and perform initial migration
添加EF工具并执行初始化迁移
In this section you'll use the Package Manager Console (PMC) to:
在本节,咱们将使用包管理控制台:
• Add the Entity Framework Core Tools package. This package is required to add migrations and update the database.
添加 EF core 工具包。这个包要求有migrations 及更新 db。
• Add an initial migration.
添加一个初始化的migration
• Update the database with the initial migration.
用初始化的migration 更新数据库。
From the Tools menu, select NuGet Package Manager > Package Manager Console.
在Tools 菜单,选择 NuGet Package Manager > Package Manager Console 菜单:
In the PMC, enter the following commands:
在 PMC 命令板上,输入下面的命令:
Install-Package Microsoft.EntityFrameworkCore.Tools Add-Migration Initial Update-Database
The Add-Migration command creates code to create the initial database schema.
Add-Migration 命令生成了初始化db结构的代码。
The schema is based on the model specified in the DbContext(In the *Data/MvcMovieContext.cs file).
Db结构 基于专门建立的 DbContext 模型类。
The Initialargument is used to name the migrations. You can use any name, but by convention you choose a name that describes the migration.
Initial 参数用于命名migrations 。你能够在这里使用任何名字,可是习惯上要使用一个能够描述 migration 的名字。
See Introduction to migrations for more information.
查看 Introduction to migrations 能够得到更多信息。
The Update-Database command runs the Up method in the Migrations/<time-stamp>_InitialCreate.csfile, which creates the database.
Update-Database 命令执行了 Migrations/<time-stamp>_InitialCreate.csfile 文件中的 Up 方法建立DB。
Test the app
测试应用
• Run the app and tap the Mvc Movie link.
运行应用并点击 Mvc Movie 连接。
• Tap the Create New link and create a movie.
点击 Create New 连接并建立一条电影。
• You may not be able to enter decimal points or commas in the Price field.
你可能不能在 Price 字段里输入小数点或逗号。
To support jQuery validation for non-English locales that use a comma (",") for a decimal point,
使用 jQuery validation 支持在非英文场景使用逗号与小数点,
and non US-English date formats, you must take steps to globalize your app.
以及非美式日期格式,你须要作一些操做来全球化你的应用。
See Additional resourcesfor more information.
查看 Additional resources 能够得到更多信息。
For now, just enter whole numbers like 10.
目前,我先只输入像10这样的整数。
• In some locales you need to specify the date format. See the highlighted code below.
在某些场景,你须要专门指定特殊的日期格式。看下面高亮的代码部分:
1 using System; 2 using System.ComponentModel.DataAnnotations; 3 4 namespace MvcMovie.Models 5 { 6 public class Movie 7 { 8 public int ID { get; set; } 9 public string Title { get; set; } 10 [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)] 11 public DateTime ReleaseDate { get; set; } 12 public string Genre { get; set; } 13 public decimal Price { get; set; } 14 } 15 }
We'll talk about DataAnnotations later in the tutorial.
咱们将在本教程的后面讲解数据注解。
Tapping Create causes the form to be posted to the server, where the movie information is saved in a database.
点击 Create 将会向服务器发送表单,而后电影数据的信息就会保存到数据库。
The app redirects to the /Movies URL, where the newly created movie information is displayed.
应用重定向到 /Movies 地址,在这个页面,新建立的电影信息就会显示出来。
Create a couple more movie entries. Try the Edit, Details, and Delete links, which are all functional.
建立更多的电影条目,尝试 Edit, Details, and Delete 连接操做,他们都是功能完整的。
Dependency Injection
依赖注入
Open the Startup.cs file and examine ConfigureServices:
打开 Startup.cs 文件,并查看 ConfigureServices 方法:
1 public void ConfigureServices(IServiceCollection services) 2 { 3 // Add framework services. 4 services.AddMvc(); 5 6 services.AddDbContext<MvcMovieContext>(options => 7 options.UseSqlServer(Configuration.GetConnectionString("MvcMovieContext"))); 8 }
The highlighted code above shows the movie database context being added to the Dependency Injection container.
上面高亮的代码显示 movie DB上下文已经添加到了DI容器中。
The line following services.AddDbContext<MvcMovieContext>(options => is not shown (see your code).
services.AddDbContext<MvcMovieContext>(options => 这行代码下的代码没有展现(查看代码文件就能看到)。
It specifies the database to use and the connection string. => is a lambda operator.
它指定了数据库使用的链接字符串。=> 符号是 lambda 操做符。
Open the Controllers/MoviesController.cs file and examine the constructor:
打开 Controllers/MoviesController.cs 文件并查看构造函数:
1 public class MoviesController : Controller 2 { 3 private readonly MvcMovieContext _context; 4 5 public MoviesController(MvcMovieContext context) 6 { 7 _context = context; 8 }
The constructor uses Dependency Injection to inject the database context (MvcMovieContext) into the controller.
构造函数使用 DI 注入DB上下文到控制器中。
The database context is used in each of the CRUD methods in the controller.
DB上下文将会在控制器中的每一个CRUD方法中使用。
Strongly typed models and the @model keyword
强类型Model与@model 关键字
Earlier in this tutorial, you saw how a controller can pass data or objects to a view using the ViewDatadictionary.
在教程的前面部分,你已经明白如何用 ViewData 字典将数据从控制器传递给视图使用。
The ViewData dictionary is a dynamic object that provides a convenient late-bound way to pass information to a view.
ViewData 字典是一个动态对象,它提供了一个后绑定方式以传递数据到视图中。
MVC also provides the ability to pass strongly typed model objects to a view.
MVC同时也提供了向视图传递强类型视图的方式。
This strongly typed approach enables better compile-time checking of your code.
强类型在编译代码时能更好的检查你的代码。
The scaffolding mechanism used this approach (that is, passing a strongly typed model) with the MoviesController class and views when it created the methods and views.
基架的机制使用的相似这种,在建立控制器方法与视图的时候。
Examine the generated Details method in the Controllers/MoviesController.cs file:
在 Controllers/MoviesController.cs 文件中查看自动生成的 Details 方法:
1 // GET: Movies/Details/5 2 public async Task<IActionResult> Details(int? id) 3 { 4 if (id == null) 5 { 6 return NotFound(); 7 } 8 9 var movie = await _context.Movie 10 .SingleOrDefaultAsync(m => m.ID == id); 11 if (movie == null) 12 { 13 return NotFound(); 14 } 15 16 return View(movie); 17 }
The id parameter is generally passed as route data. For example http://localhost:5000/movies/details/1 sets:
id 参数一般是路由参数传递过来的。例如 http://localhost:5000/movies/details/1 中有多个路由段:
• The controller to the movies controller (the first URL segment).
第一段是 movies 控制器。
• The action to details (the second URL segment).
第二段是 details action方法。
• The id to 1 (the last URL segment).
第三段是 id=1 参数。
You can also pass in the id with a query string as follows:
固然你也能够吧 id 参数放到查询字符串里面,以下URL:
http://localhost:1234/movies/details?id=1
The id parameter is defined as a nullable type (int?) in case an ID value is not provided.
id 参数被定义为了可空类型,以适应ID未提供的状况。
A lambda expression is passed in to SingleOrDefaultAsync to select movie entities that match the route data or query string value.
一个lambda 表达式 被作为 SingleOrDefaultAsync 方法的参数以找出相应的数据实体(与路由参数或查询字符串参数一致的的)。
1 var movie = await _context.Movie 2 .SingleOrDefaultAsync(m => m.ID == id);
If a movie is found, an instance of the Movie model is passed to the Details view:
若是数据实体被找到,则会如代码所示的方式传递给视图:
1 return View(movie);
Examine the contents of the Views/Movies/Details.cshtml file:
查看 Views/Movies/Details.cshtml 文件的内容,以下:
1 @model MvcMovie.Models.Movie 2 3 @{ 4 ViewData["Title"] = "Details"; 5 } 6 7 <h2>Details</h2> 8 9 <div> 10 <h4>Movie</h4> 11 <hr /> 12 <dl class="dl-horizontal"> 13 <dt> 14 @Html.DisplayNameFor(model => model.Title) 15 </dt> 16 <dd> 17 @Html.DisplayFor(model => model.Title) 18 </dd> 19 <dt> 20 @Html.DisplayNameFor(model => model.ReleaseDate) 21 </dt> 22 <dd> 23 @Html.DisplayFor(model => model.ReleaseDate) 24 </dd> 25 <dt> 26 @Html.DisplayNameFor(model => model.Genre) 27 </dt> 28 <dd> 29 @Html.DisplayFor(model => model.Genre) 30 </dd> 31 <dt> 32 @Html.DisplayNameFor(model => model.Price) 33 </dt> 34 <dd> 35 @Html.DisplayFor(model => model.Price) 36 </dd> 37 </dl> 38 </div> 39 <div> 40 <a asp-action="Edit" asp-route-id="@Model.ID">Edit</a> | 41 <a asp-action="Index">Back to List</a> 42 </div>
By including a @model statement at the top of the view file, you can specify the type of object that the view expects.
经过在顶部包含一个@model 语句,你能够指定视图所要使用的模型类型。
When you created the movie controller, Visual Studio automatically included the following @model statement at the top of the Details.cshtml file:
在你添加movie控制器时,vs 自动在Details.cshtml 文件的顶部包含了@model 语句,以下所示:
1 @model MvcMovie.Models.Movie
This @model directive allows you to access the movie that the controller passed to the view by using a Model object that's strongly typed.
@model 指令容许你在视图上以强类型的方式访问控制器传递过来的Model 对象。
For example, in the Details.cshtml view, the code passes each movie field to the DisplayNameFor and DisplayFor HTML Helpers with the strongly typed Modelobject.
例如在Details.cshtml 视图中,代码用 DisplayNameFor 和DisplayFor 展示强类型Model 对象的每个字段。
The Create and Edit methods and views also pass a Movie model object.
Create 和Edit 一样在视图中解析Movie 模型对象。
Examine the Index.cshtml view and the Index method in the Movies controller.
查看Index.cshtml 视图及控制器中的 Index 方法。
Notice how the code creates a List object when it calls the View method.
注意代码中在调用View 方法时是如何建立一个List 集合对象的。
The code passes this Movies list from the Index action method to the view:
代码中从Index 方法传递Movies 列表到视图中,以下:
1 // GET: Movies 2 public async Task<IActionResult> Index() 3 { 4 return View(await _context.Movie.ToListAsync()); 5 }
When you created the movies controller, scaffolding automatically included the following @modelstatement at the top of the Index.cshtml file:
当你建立movie控制器,基价自动会将以下代码放到Index.cshtml 文件的顶部:
1 @model IEnumerable<MvcMovie.Models.Movie>
The @model directive allows you to access the list of movies that the controller passed to the view by using a Model object that's strongly typed.
@model 指令容许你以强类型的方式在视图上访问控制器传递过来的movies 列表。
For example, in the Index.cshtml view, the code loops through the movies with a foreach statement over the strongly typed Model object:
例如,在Index.cshtml 视图中,经过foreach 语句循环movie列表中的每一个强类型Model 对象:
1 @model IEnumerable<MvcMovie.Models.Movie> 2 3 @{ 4 ViewData["Title"] = "Index"; 5 } 6 7 <h2>Index</h2> 8 9 <p> 10 <a asp-action="Create">Create New</a> 11 </p> 12 <table class="table"> 13 <thead> 14 <tr> 15 <th> 16 @Html.DisplayNameFor(model => model.Title) 17 </th> 18 <th> 19 @Html.DisplayNameFor(model => model.ReleaseDate) 20 </th> 21 <th> 22 @Html.DisplayNameFor(model => model.Genre) 23 </th> 24 <th> 25 @Html.DisplayNameFor(model => model.Price) 26 </th> 27 <th></th> 28 </tr> 29 </thead> 30 <tbody> 31 @foreach (var item in Model) { 32 <tr> 33 <td> 34 @Html.DisplayFor(modelItem => item.Title) 35 </td> 36 <td> 37 @Html.DisplayFor(modelItem => item.ReleaseDate) 38 </td> 39 <td> 40 @Html.DisplayFor(modelItem => item.Genre) 41 </td> 42 <td> 43 @Html.DisplayFor(modelItem => item.Price) 44 </td> 45 <td> 46 <a asp-action="Edit" asp-route-id="@item.ID">Edit</a> | 47 <a asp-action="Details" asp-route-id="@item.ID">Details</a> | 48 <a asp-action="Delete" asp-route-id="@item.ID">Delete</a> 49 </td> 50 </tr> 51 } 52 </tbody> 53 </table>
Because the Model object is strongly typed (as an IEnumerable<Movie> object), each item in the loop is typed as Movie.
由于Model 对象是强类型的,循环中的每一个对象都是Movie 类型。
Among other benefits, this means that you get compile-time checking of the code:
还有其它有点,好比你在编译的同时也由编译器自动检查了代码的正确性:
Additional resources
其它资源
• Tag Helpers
• Globalization and localization
蒙
2017-07-20 16:31 周四
2017-07-21 15:10 修正