在上一节里,我们从数据库中读取了数据并将其显示在页面上。在本章中,我们将实现对于数据的编辑操作。
5.1 创建的带有Create,Update,Delete与Details方法的控制器
首先,我们将要创建一个新的控制器,名为StroeManagerController。这个控制器将要支持Create(创建数据)action方法与 Update(更新数据)action方法。所以在创建控制器的时候,我们需要选取“为Create,Update,Delete与Details场景添 加action方法”这个复选框,如图5-1所示。
图5-1 选取“为Create,Update与Details场景添加action方法”这个复选框
点击添加按钮,Visual Web Developer将会创建一个带有默认的Create,Update,Delete与Details方法的控制器,默认方法中带有TODO语句,提示我们填入我们的应用程序中的逻辑,代码如代码清单5-1所示。
代码清单5-1 默认创建的带有Create,Update,Delete与Details方法的控制器
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MvcBookStore.Controllers
{
public class StroeManagerController : Controller
{
//
// GET: /StroeManager/
public ActionResult Index()
{
return View();
}
//
// GET: /StroeManager/Details/5
public ActionResult Details(int id)
{
return View();
}
//
// GET: /StroeManager/Create
public ActionResult Create()
{
return View();
}
//
// POST: /StroeManager/Create
[HttpPost]
public ActionResult Create(FormCollection collection)
{
try
{
// TODO: Add insert logic here
return RedirectToAction("Index");
}
catch
{
return View();
}
}
//
// GET: /StroeManager/Edit/5
public ActionResult Edit(int id)
{
return View();
}
//
// POST: /StroeManager/Edit/5
[HttpPost]
public ActionResult Edit(int id, FormCollection collection)
{
try
{
// TODO: Add update logic here
return RedirectToAction("Index");
}
catch
{
return View();
}
}
//
// GET: /StroeManager/Delete/5
public ActionResult Delete(int id)
{
return View();
}
//
// POST: /StroeManager/Delete/5
[HttpPost]
public ActionResult Delete(int id, FormCollection collection)
{
try
{
// TODO: Add delete logic here
return RedirectToAction("Index");
}
catch
{
return View();
}
}
}
}
本教程中不需要使用Details这个action方法,所以可以将其删除。
5.2 添加作者类
我们的StroeManager控制器将要针对我们的书籍作者进行管理,所以在书写控制器中的代码之前,首先我们需要添加一个简单的Author(作者) 这个模型类,鼠标右击解决方案资源管理器中的Models文件夹,添加一个名为Author.cs的类,书写如代码清单5-2所示的代码。
代码清单5-2 Author(作者)类的代码
namespace MvcBookStore.Models
{
public class Author
{
public int AuthorId { get; set; }
public string Name { get; set; }
}
}
接下来,我们将要在我们的Book(书籍)类中添加一个Author(作者)属性。Entity Framework自身可以知道如何根据默认约定来读取和显示与书籍相关联的作者信息,不需要我们进行其他额外的设置。更新后的Book类的代码如代码清单5-3所示。
代码清单5-3 Book(书籍)类的代码
namespace MvcBookStore.Models
{
public class Book
{
public int Id { get; set; }
public int GenreId { get; set; }
public int AuthorId { get; set; }
public string Title { get; set; }
public decimal Price { get; set; }
public virtual Genre Genre { get; set; }
public virtual Author Author { get; set; }
}
}
使用如下所示的sql语句在数据库中手工添加Authors数据表。
CREATE TABLE [dbo].[Authors](
[AuthorId] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](120) NULL,
PRIMARY KEY CLUSTERED
(
[AuthorId] ASC
)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
CREATE NONCLUSTERED INDEX [IPK_Author] ON [dbo].[Authors]
(
[AuthorId] ASC
)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF,
DROP_EXISTING = OFF, ONLINE = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
使用如下所示的语句为Books表添加一个与Author相关联的索引键。
CREATE NONCLUSTERED INDEX [IFK_Author_Book] ON [dbo].[Books]
(
[AuthorId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF,
DROP_EXISTING = OFF, ONLINE = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
最后,我们需要在我们的BookStoreEnties类中追加一个DbSet<Author>集合,以便直接读取数据库中的作者信息,而不需要通过Book类来装载,代码如代码清单5-4所示。
代码清单5-4 BookStoreEnties类
using System.Data.Entity;
namespace MvcBookStore.Models
{
public class BookStoreEntities : DbContext
{
public DbSet<Book> Books { get; set; }
public DbSet<Genre> Genres { get; set; }
public DbSet<Author> Authors { get; set; }
}
}
5.3 修改StroeManager控制器中的Index方法
就像在我们的Store控制器中那样,我们需要在StroeManager控制器中创建一个对象,用以实例化我们的BookStoreEnties类。首先,在文件头部追加一个using语句,来引用MvcBookStore.Models命名空间。
using MvcBookStore.Models;
接下来创建一个storeDB对象,代码如下所示。
public class StoreManagerController : Controller
{
BookStoreEntities storeDB = new BookStoreEntities();
接下来我们修改StroeManager控制器中的Index这个action方法,使其能够显示一个书籍清单,所以action中的代码与之前我们所创 建的Store控制器中的Index方法中的代码极其类似。我们使用LINQ来读取所有书籍,及其相关联的书籍种类信息以及作者信息。
//
// GET: /StoreManager/
public ActionResult Index()
{
var books = storeDB.Books
.Include("Genre").Include("Author")
.ToList();
return View(books);
}
5.4 将视图模板支架化
我们的StoreManager控制器中的Index视图将要具有ASP.NET MVC中的支架特色。支架允许我们以控制器中的action方法中传过来的对象类型为基础,自动创建强类型的视图。在创建视图模板时,支架体系使用反射体制,所以它可以以控制器中将要传递的对象类型为基础,创建一个新的强类型的视图。
支架提供一个快速的方法来创建强类型的视图,而不需要我们手工书写我们的视图代码。我们可以使用支架快速生成一个默认的视图模板,然后来修改该视图模板中 的代码。现在,我们使用List(清单或列表、表格)模板来生成一个Book(书籍)类的强类型视图,我们可以生成一个视图来显示表格,该表格中显示书籍 信息。
首先,在StoreManager控制器的Index方法中点击鼠标右键,然后点击“添加视图”菜单。我们将要在添加视图对话框中添加两个设置。首先,选 取“创建强类型视图”复选框,并在模型类下拉框中选择Book(书籍)类。接下来,在支架模板下拉框中选择List,如图5-2所示。
图5-2 创建强类型视图模板
接下来,让我们来看一下Visual Web Developer自动创建的强类型视图模板中的代码,如代码清单5-5所示(代码中笔者添加了中文化处理)。
代码清单5-5 在index方法中创建的强类型视图模板
@model IEnumerable<MvcBookStore.Models.Book>
@{
ViewBag.Title = "书籍列表";
}
<h2>书籍列表</h2>
<p>
@Html.ActionLink("添加书籍", "Create")
</p>
<table>
<tr>
<th></th>
<th>种类编号</th>
<th>作者编号</th>
<th>书名</th>
<th>单价</th>
</tr>
@foreach (var item in Model) {
<tr>
<td>
@Html.ActionLink("编辑","Edit", new { id=item.BookId }) |
@Html.ActionLink("详细","Details", new { id=item.BookId }) |
@Html.ActionLink("删除","Delete", new { id=item.BookId })
</td>
<td>@item.GenreId</td>
<td>@item.AuthorId</td>
<td>@item.Title</td>
<td>@String.Format("{0:F}",item.Price)</td>
</tr>
}
</table>
请注意,这段代码是Visual Web Developer自动创建的强类型视图模板中的代码,与我们所需要的代码还有些区别。例如,它使用了Html.ActionLink帮助器来生成对于其他控制器中的action的连接。
这里我们只需要显示书名,作者名与书籍种类,所以我们可以删除与修改有关列,使其代码如下所示。
<p>
@Html.ActionLink("添加书籍", "Create")
</p>
<table>
<tr>
<th></th>
<th>书名</th>
<th>作者</th>
<th>种类</th>
</tr>
@foreach (var item in Model) {
<tr>
<td>
@Html.ActionLink("编辑","Edit", new { id=item.BookId }) |
@Html.ActionLink("删除","Delete", new { id=item.BookId })
</td>
<td>@item.Title</td>
<td>@item.Author.Name</td>
<td>@item.Genre.Name</td>
</tr>
}
</table>
在运行这段应用程序之前,请首先在本节中创建的Author(作者)数据表中添加如表5-1所示数据。
表5-1 在Authors(作者)数据表中添加的数据
AuthorId(作者ID,自增长字段) | Name(作者名) |
1 | 韩寒 |
2 | 陈升 |
3 | 村上春树 |
4 | 安妮宝贝 |
5 | 陈晨 |
6 | 六六 |
7 | 米兰•昆德拉 |
8 | 卡勒德•胡赛尼 |
9 | (空字符串) |
追加了作者信息之后,现在你可以运行应用程序,并且在浏览器中输入“/StoreManager”,浏览器中显示结果如图5-3所示。
图5-3 书籍列表显示画面