在要节中将添加一些在数据库中管理电影的类,这些类将成为MVC应用的“Model(模型)”部分。
这些类将与EntityFramework Core (EF Core)一起用于操作数据库,EF Core是可以简化那些不得不写的访问数据库的代码的对象关系映射(ORM)框架,本教程将使用SQLite,但EF Core支持许多数据库引擎。
将创建的模型类被称作POCO类(来自“plain-old CLR objects”),因为它们不依赖于EF Core,它们只是定义了将被存储在数据库中的数据的所有属性。
在这个教程中,将首先写模型类,接着EF Core将会创建数据库,另一种这没有讨论的方法可根据已经存在的数据库生成模型类,要了解这个方法的相关信息,请看ASP.NET Core - Existing Database.
1.添加数据模拟类
在解决方案浏览器中,右击MvcMovie 项目 >Add > New Folder,命名文件夹为 Models.
在解决方案浏览器中,右击所建的Models文件夹> Add > Class,命名类为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应用添加了一个模型。
2.搭建一个控制器
在解决方案浏览器中,右击 Controllers 文件夹 > Add > Controller,
在 Add MVC Dependencies 对话框中, 选择 MinimalDependencies, 再选择Add。
Visual Studio 添加了搭建控制器所需的依赖项,但是控制器本身没有被创建,下一个> Add > Controller的调用才会创建控制器。
在解决方案浏览器中,右击Controller文件夹>Add>Controller,
在 Add Scaffold 对话框中, 点击 MVC Controller with views, usingEntity Framework > Add.
系统自动生成了电影控制器(Controllers/MoviesController.cs)以及创建、删除、详情、编辑、索引等网页的Razor 视图文件。
CRUD (create, read, update, and delete)的行为方法和视图自动创建被称为搭建(scaffolding),这使我们很快就有了一个能管理一个电影数据库的全功能网页应用。
如果运行应用并点击Mvc Movie链接,将会得到一个类似下面所示的错误:
An unhandled exception occurredwhile processing the request.
SqlException: Cannot opendatabase "MvcMovieContext-<GUID removed>"
requested by the login. The loginfailed.
Login failed for user Rick
大意为:
处理这个需求时,发生了未处理的异常。
SqlException: 不能打开登录所需的"MvcMovieContext-<GUIDremoved>" 数据库,登录失败,用户Rick登录失败。
这时,我们需要创建这个数据库,我们将使用EF Core 迁移 功能来完成这个工作,迁移允许创建匹配数据模型的数据库并在数据模型改变时更新数据库。
3.为迁移添加EF加工
In Solution Explorer, right click the MvcMovie project > Edit MvcMovie.csproj.
在解决方案浏览器,右击MvcMovie 项目 > Edit MvcMovie.csproj.
XML
<ItemGroup>
<DotNetCliToolReferenceInclude="Microsoft.VisualStudio.Web.CodeGeneration.Tools"Version="1.0.0" />
<DotNetCliToolReferenceInclude="Microsoft.EntityFrameworkCore.Tools.DotNet"Version="1.0.0" />
</ItemGroup>
注意:上面显示的版本号在写作时是正确的。
保存修改。
4.添加初始迁移并更新数据库
dotnet restore
dotnet ef migrations add Initial
dotnet ef database update
dotnet (.NET Core)是.NET的跨平台实现,可在此阅读相关知识.
dotnet restore :该命令下载在.csproj文件中指定的NuGet包.
dotnet ef migrations add Initial:该命令运行Entity Framework .NET Core CLI迁移命令并创建初始迁移。“add”后面的参数是指定给该迁移的命名,由于本命令是初始的数据库迁移,所以命名该迁移为“Initial(初始的)”。这个操作创建了包含要添加 Movie表到数据库的迁移命令的Data/Migrations/<date-time>_Initial.cs文件。
dotnet ef database update:该命令用刚刚创建的迁移更新数据库。
我们将在下个教程中学习数据库和连接字符串,你可以在添加字段教程中学习有关数据模型的变更。
5.Test the app测试应用
运行应用并点击MvcMoview链接。
点击Create New链接并创建一部电影。
你可能会无法在价格字段中输入小数点或逗号,要使使用逗号“,”作为小数点和使用非美国英语日期格式的非英语场合支持jQuery 验证,必须采取措施来全球化应用,更多信息见附加资源,现在,只需要输入整数如10。
在一些场合下你会需要指定数据格式,见下面的高亮(加粗)代码。
using System;
usingSystem.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 DateTimeReleaseDate { get; set; }
public string Genre { get; set; }
public decimal Price { get; set; }
}
}
我们将的后面的教程中讨论DataAnnotations。
点击Create引发表单被提交给服务器,在那儿电影信息被存储在数据库中,再重定位到/Movies URL,可以在列表中看到最新创建的电影。
多创建几个电影条目,尝试Edit, Details, 和 Delete 等这些全功能链接。
6.Dependency Injection依赖项注入
打开Startup.cs文件并检查ConfigureServices:
public void ConfigureServices(IServiceCollectionservices)
{
// Addframework services.
services.AddMvc();
services.AddDbContext<MvcMovieContext>(options=>
上面高亮(粗体)显示的代码展示了电影数据库上下文被加入到依赖项注入容器中,跟随在services.AddDbContext<MvcMovieContext>(options=>
后面的行没有显示出来(见你的代码),它指定了要使用的数据库和连接字符串。=>是lambda 操作符.
打开Controllers/MoviesController.cs文件并检查其构造器:
public class MoviesController : Controller
{
private readonlyMvcMovieContext _context;
public MoviesController (MvcMovieContext context)
{
_context = context;
}
该构造器使用依赖项注入把数据库上下文(MvcMovieContext)注入到控制器中,数据库上下文在控制器中每个的CRUD方法内被使用。
7.Strongly typed models and the @model keyword强类型方法和@model关键字
在本教程的前面,我们见过控制器如何使用ViewData字典传递数据或对象给视图,ViewData字典是提供方便的后期绑定方法以传递信息给视图的动态对象。MVC也提供了向视图传递强类型模型对象的能力,这种强类型方法可提供更好的代码编译时间检查和更深的智能感知。基架机制在创建方法和视图时使用了这种方法(即,传递强类型模型)和MoviesController类以及视图。
在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:5000/movies/details/1使:
你也可能用如下的查询字符串传值给id:
http://localhost:1234/movies/details?id=1
当电影被找到,电影模型的实例被传递给Details视图:
C#
return View(movie);
检查Views/Movies/Details.cshtml文件的内容:
@model MvcMovie.Models.Movie
@{
ViewData["Title"] ="Details";
}
<h2>Details</h2>
<div>
<h4>Movie</h4>
<hr/>
<dlclass="dl-horizontal">
<dt>
@Html.DisplayNameFor(model =>model.Title)
</dt>
<dd>
@Html.DisplayFor(model =>model.Title)
</dd>
<dt>
@Html.DisplayNameFor(model =>model.ReleaseDate)
</dt>
<dd>
@Html.DisplayFor(model =>model.ReleaseDate)
</dd>
<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>
</dl>
</div>
<div>
<aasp-action="Edit" asp-route-id="@Model.ID">Edit</a> |
<aasp-action="Index">Back to List</a>
</div>
通过在视图文件的顶部包含一个@model语句,可以指定视图期望的对象类型。当创建该电影控制器时,VisualStudio自动在Details.cshtml文件的顶部包含了下面的@mode语句。
HTML
@model MvcMovie.Models.Movie
这个@model指令允许访问控制器通过使用强类型的模型对象传给视图的电影,比如,在Details.cshtml视图中,代码将每个电影字段用强类型模型对象传递给DisplayNameFor 和 DisplayFor辅助工具。Create(创建)和Edit(修改)方法和视图也传递Movie模型对象。
在Movies控制器中检查Index.cshtml视图和Index方法,注意当代码调用View方法时,如何创建一个列表(List)对象, 代码将这个Movies列表从Index行为方法传递给视图。
// GET: Movies
public async Task<IActionResult> Index()
{
return View(await_context.Movie.ToListAsync());
}
当创建该电影控制器,基架自动在Index.cshtml文件的顶部包含了下列@model语句。
@model IEnumerable<MvcMovie.Models.Movie>
@model指令允许访问控制器通过使用强类型的模型对象传递给视图的电影列表 ,比如,在Index.cshtml视图中,代码使用一个foreach语句在强类型模型对象上遍历电影列表的信息。
@model IEnumerable<MvcMovie.Models.Movie>
@{
ViewData["Title"] ="Index";
}
<h2>Index</h2>
<p>
<aasp-action="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model=> model.Title)
</th>
<th>
@Html.DisplayNameFor(model=> model.ReleaseDate)
</th>
<th>
@Html.DisplayNameFor(model=> model.Genre)
</th>
<th>
@Html.DisplayNameFor(model=> model.Price)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</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>
因为该模型对象是强类型(如IEnumerable<Movie>对象),循环中的每一项被显示为电影。在其他的好处中,你还获得了代码编译时检查和在代码编辑中的全智能感知支持:
8.附加的资源
原文
来自 https://blog.csdn.net/jhycjhyc/article/details/73162608?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_title~default-0.no_search_link&spm=1001.2101.3001.4242