Tất cả bắt đầu vào những năm 70 của thế kỷ 20, tại phòng thí nghiệm
Xerox PARC ở Palo Alto. Sự ra đời của giao diện đồ họa (Graphical User
Interface) và lập trình hướng đối tượng (Object Oriented Programming) cho
phép lập trình viên làm việc với những thành phần đồ họa nhưnhững đối tượng
đồ họa có thuộc tính và phương thức riêng của nó. Không dừng lại ở đó, những
nhà nghiên cứu ở Xerox PARC còn đi xa hơn khi cho ra đời cái gọi là kiến trúc
MVC (viết tắt của Model -View - Controller).
MVC được phát minh tại Xerox Parc vào những năm 70, bởi
TrygveReenskaug. MVC lần đầu tiên xuất hiện công khai là trong Smalltalk-80.
Sau đó trong một thời gian dài hầu như không có thông tin nào về MVC, ngay cả
trong tài liệu 80 Smalltalk. Các giấy tờ quan trọng đầu tiên được công bố trên
MVC là “A Cookbook for Using the Model-View-Controller User Interface
Paradigm in Smalltalk - 80”, bởi Glenn Krasner và Stephen Pope, xuất bản trong
tháng 8 / tháng 9 năm 1988.
120 trang |
Chia sẻ: NamTDH | Lượt xem: 1594 | Lượt tải: 0
Bạn đang xem trước 20 trang nội dung tài liệu Giáo trình Mô hình MVC, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
i bạn đã hoàn thành, hãy đóng kết nối lại (Nếu không
đóng kết nối, có thể sẽ gặp lỗi trong lần run project kế tiếp).
Hiện tại chúng ta đã có database và một list page đơn giản để hiển thị nội
dung từ database. phần tiếp theo, chúng ta sẽ kiểm tra tiếp phần còn lại của
scaffolded và thêm vào phương thức SearchIndex và một SearchIndex view cho
phép chúng ta tìm kiếm các sản phẩm trong database.
4. Hiệu chỉnh và thêm mới một số phương thức tạo sẵn:
Trong phần này, chúng ta sẽ kiểm tra các phương thức và view đã được
tạo cho SanPham controller. Sau đó chúng ta sẽ thêm mới trang search.
Chạy ứng dụng và browse đến controller SanPham bằng cách thêm
/SanPham vào URL. Click vào liên kết Edit để thấy URL được liên kết tới.
( Docx Converter - Unregistered )
Liên kết Edit đã được tao ra bởi phương thức Html.ActionLink trong view
Views\SanPham \Index.cshtml:
@Html.ActionLink("Edit", "Edit", new { id=item.ID }) |
Đối tượng Html là một hepler, các thuộc tính của đối tượng này thuộc class
WebViewPage. phương thức ActionLink giúp chúng ta dễ dàng tạo ra các siêu
liên kết HTML động liên kết đến các phương thức trên controller. Argument đầu
tiên của phương thức này là link text (ví dụ, Edit). Argument thứ hai là tên của
phương thức gọi ra. cuối cùng là một đối tượng anonymous để tạo ra đường đi
(trong trường hợp này là giá trị của ID là 2).
Liên kết được tạo ra trong ảnh trước đó là
URL mặc định chúng ta nhận được có
dạng {controller}/{action}/{id}.
( Docx Converter - Unregistered )
Vì thế, ASP.NET phiên dịch thành
một yêu cầu đến phương thức Edit của SanPham controller với tham số ID là 2.
Ngoài ra chúng ta có thể truyền tham số vào cho phương thức bằng cách
sử dụng chuỗi truy vấn.
Ví dụ, một URL để truyền
tham số ID là 2 cho phương thức edit của SanPham controller.
Mở controller SanPham và xem 2 phương thức sau:
// GET: /SanPham/Edit/5
public ActionResult Edit(int id)
{
SanPham sanpham = db.SanPhams.Find(id);
return View(sanpham);
}
//
// POST: /SanPham/Edit/5
( Docx Converter - Unregistered )
[HttpPost]
public ActionResult Edit(SanPham sanpham)
{
if (ModelState.IsValid)
{
db.Entry(sanpham).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(sanpham);
}
Lưu ý là phương thức Edit được xử lí bởi thuộc tính HttpPost. Thuộc tính
này chỉ định rằng sự nạp chồng phương thức Edit có thể được gọi ra cho POST
request. Chúng ta có thể áp dụng thuộc tính HttpGet cho phương thức edit đầu
tiên, nhưng không cần thiết bởi vì nó đã mặc định như thế.
Phương thức HttpGet Edit nhận vào tham số là ID của SanPham, sau đó
sẽ tìm SanPham bằng cách sử dụng phương thức EF Find, và trả về SanPham
được chọn để Edit view. Khi hệ thống scaffold tạo Edit view, nó sẽ kiểm tra
class SanPham và tao code để render ra thành phần và cho mỗi
thuộc tính của class. Ví dụ sau cho thấy Edit view đã được tạo:
@model NguyenIchHoan.Models.SanPham
@{
ViewBag.Title = "Edit";
}
Edit
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")"
type="text/javascript">
<script
src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")"
type="text/javascript">
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
SanPham
@Html.LabelFor(model => model.masp)
@Html.EditorFor(model => model.masp)
( Docx Converter - Unregistered )
@Html.ValidationMessageFor(model => model.masp)
@Html.HiddenFor(model => model.ID)
@Html.LabelFor(model => model.tensp)
@Html.EditorFor(model => model.tensp)
@Html.ValidationMessageFor(model => model.tensp)
@Html.LabelFor(model => model.mancc)
@Html.EditorFor(model => model.mancc)
@Html.ValidationMessageFor(model => model.mancc)
@Html.LabelFor(model => model.madongsp)
@Html.EditorFor(model => model.madongsp)
@Html.ValidationMessageFor(model => model.madongsp)
@Html.LabelFor(model => model.mota)
@Html.EditorFor(model => model.mota)
@Html.ValidationMessageFor(model => model.mota)
@Html.LabelFor(model => model.anh)
@Html.EditorFor(model => model.anh)
@Html.ValidationMessageFor(model => model.anh)
@Html.LabelFor(model => model.thongtinthem)
@Html.EditorFor(model => model.thongtinthem)
@Html.ValidationMessageFor(model => model.thongtinthem)
( Docx Converter - Unregistered )
@Html.LabelFor(model => model.ngaynhaphang)
@Html.EditorFor(model => model.ngaynhaphang)
@Html.ValidationMessageFor(model => model.ngaynhaphang)
@Html.LabelFor(model => model.dongia)
@Html.EditorFor(model => model.dongia)
@Html.ValidationMessageFor(model => model.dongia)
}
@Html.ActionLink("Back to List", "Index")
Scaffold code sử dụng một vài phương thức helper để tổ chức luồng
HTML markup. Html.LabelFor dùng để hiển thị tên trường (ví dụ như mã sản
phẩm, tên sản phẩm, đơn giá, mã nhà cung cấp,....). Html.EditorFor hiển thị một
thẻ . Html.ValidationMessageFor hiển thị bấy kì tin nhắn kiểm tra dữ liệu
liên kết với thuộc tính đó.
(Scaffold là có nghĩa là giàn giáo. Ở nước ngoài, giàn giáo xếp lại được,
khi cần dựng lên, ghép cao hơn để xây dựng. Thuật ngữ Scaffold xuất hiện phổ
biến trong Ruby On Rails để mô tả về khung mã nguồn tự động sinh ra cho các
hàm Create, Read, Update, Delete (CRUD). Như vậy lập trình không phải viết
nhiều đoạn code lặp đi lặp lại nữa)
Chạy ứng dụng và điều hướng đến /SanPham URL. Click liên kết Edit.
Trong trình duyệt, xem source của trang chúng ta sẽ thấy như trong ví dụ sau:
( Docx Converter - Unregistered )
Thành phần là một thành phần của HTML Form mà thuộc tính
action được set post đến URL /SanPham/Edit. Dữ liệu form sẽ được post đến
server khi button Edit được click.
Xử lí POST request
( Docx Converter - Unregistered )
Đoạn code sau đây trình bày phiên bản HttpPost của phương thức Edit:
[HttpPost]
public ActionResult Edit(SanPham sanpham)
{
if (ModelState.IsValid)
{
db.Entry(sanpham).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(sanpham);
}
ASP.NET framework model gắn kết các giá trị của form được post và tạo
một đối tượng SanPham được truyên đi như một tham số.
Model.IsValid kiểm tra dữ submit trong form có thể dùng để điều chỉnh đối
tượng SanPham. Nếu dữ liệu là hợp lệ, code xử lí sẽ lưu dữ liệu SanPham đến đối
tượng SanPham collection của SanPhamDBContext.
Sau đó sẽ lưu dữ liệu SanPham mới này nào database bằng cách gọi
phương thức SaveChanges của SanPhamDBContext để lưu thay đổi vào
database. Sau khi lưu dữ liệu, code sẽ redirect người dùng đến phương thức Index
của class SanPham Controller, và hiển thị danh sách các sản phẩm vừa được cập
nhật.
( Docx Converter - Unregistered )
Làm cho phương thức Edit trở nên mạnh mẽ hơn
Phương thức HttpGet Edit được sinh ra bởi hệ thống scafffolding không có
kiểm tra dữ liệu được truyền vào (trong trường hợp này là ID). Nếu người dùng
bỏ đi phần ID của URL ( sẽ xuất hiện lỗi
như sau:
Ngoài ra người dùng có thể truyền vào ID không tồn tại trong cơ sở dữ
liệu, ví dụ Chúng ta có thể tránh xảy
ra lỗi này bằng cách điều chỉnh phương thức Http Edit. Trước hết, thay đổi tham
số ID về giá trị mặc định là 0 khi ID được truyền vào không rõ ràng. Ngoài ra
chúng ta có thể kiểm tra bằng phương thức Find để tìm một sản phẩm tồn tại thực
sự trước khi return đối tượng SanPham về cho view template. Phương thức Edit
được cập nhật như sau:
public ActionResult Edit(int id)
{
SanPham sanpham = db.SanPhams.Find(id);
if (sanpham == null)
{
return HttpNotFound();
}
return View(sanpham);
}
Nếu như không tìm thấy phim, phương thức HttpNotFound sẽ được gọi và
hiển thị ra một trang trắng để không gây lỗi khi sử dụng trang web:
( Docx Converter - Unregistered )
Tất cả các phương thức HttpGet sau đây điều có cùng mẫu (pattern) tương
tự nhau. Chúng lấy một đối tượng (hoặc danh sách các đối tượng, trong trường
hợp này là phương thức Index), và truyền model đến view. Phương thức create
truyền một đối tượng SanPham rỗng đến Create view. Tất cả các phương thức
create, edit, delete, hoặc các phương thức điều chỉnh dữ liệu khác cũng thực hiện
tương tự trong nạp chồng phương thức HttpPost.
Thêm phương thức Search và Search View
Trong phần này chúng ta sẽ thêm một phương thức SearchIndex cho phép
chúng ta tìm kiếm các sản phẩm theo tên hoặc mã dòng sản phẩm. URL sử dụng
cho phương thức này là /SanPham /SearchIndex. Yêu cầu hiển thị dưới dạng
HTML form chứa input cho phép người dùng điền thông tin tìm kiếm. Khi người
dùng submit form, phương thức sẽ lấy giá trị tìm kiếm được nhập vào bởi người
dùng và sử dụng giá trị đó để tìm kiếm trong database.
Hiển thị form SearchIndex
Bắt đầu bằng cách thêm một phương thức SearchIndex vào class
SanPhamController. Phương thức này sẽ trả về một view chứa đựng HTML form.
Đây là code:
public ActionResult SearchIndex(string searchString)
{
var sanpham = from m in db.SanPhams
select m;
if (!String.IsNullOrEmpty(searchString))
{
sanpham = sanpham.Where(s =>
s.tensp.Contains(searchString));
}
return View(sanpham);
}
( Docx Converter - Unregistered )
Dòng đầu tiên của phương thức là tạo một truy vấn LINQ để chọn ra các
sản phẩm thỏa điều kiện tìm kiếm:
var sanpham = from m in db.SanPhams
select m;
Nếu tham số searchString chứa chuỗi, câu truy vấn sẽ được điều chỉnh để
lọc kết quả dựa trên chuỗi giá trị tìm kiếm, sử dụng code sau đây:
if (!String.IsNullOrEmpty(searchString))
{
sanpham = sanpham.Where(s =>
s.tensp.Contains(searchString));
}
Truy vấn LINQ không thực thi ngay khi được định nghĩa hoặc khi chúng
được điều chỉnh bằng cách gọi một phương thức như Where hoặc OrderBy. Thay
vào đó, việc thực thi truy vấn sẽ được hoãn lại. Trong ví dụ SearchIndex, truy vấn
được thực thi trong SearchIndex view. Để biết thêm thông tin về hoãn thực thi
truy vấn, chúng ta có thể xem Query Execution
Bây giờ chúng ta đã có thể triển khai SearchIndex view, view này sẽ hiển
thị form cho người dùng. Click phải vào phương thức SearchIndex và sau đó click
Add View. Trong họp thoại Add View, chỉ định như trong hình để truyền một đối
tượng SanPham đến view template. Trong danh sách scaffold template, chọn List,
sau đó click Add.
( Docx Converter - Unregistered )
b
Khi chúng ta click Add, view template Views\SanPham
\SearchIndex.cshtml sẽ được tạo. Bởi vì chúng ta đã chọn trong danh sách
scaffold template, Visual web developer tự động sinh ra nội dung (code) mặc định
( Docx Converter - Unregistered )
trong view. Scaffolf đã tạo một HTML form. Nó kiểm tra class SanPham và đã
tạo ra code để render ra thành phần cho mỗi thuộc tính của class. Sau đây
là code sinh ra khi tạo view:
@model IEnumerable
@{
ViewBag.Title = "SearchIndex";
}
SearchIndex
@Html.ActionLink("Create New", "Create")
masp
tensp
mancc
madongsp
mota
anh
thongtinthem
ngaynhaphang
dongia
@foreach (var item in Model) {
@Html.DisplayFor(modelItem => item.masp)
( Docx Converter - Unregistered )
@Html.DisplayFor(modelItem => item.tensp)
@Html.DisplayFor(modelItem => item.mancc)
@Html.DisplayFor(modelItem => item.madongsp)
@Html.DisplayFor(modelItem => item.mota)
@Html.DisplayFor(modelItem => item.anh)
@Html.DisplayFor(modelItem => item.thongtinthem)
@Html.DisplayFor(modelItem => item.ngaynhaphang)
@Html.DisplayFor(modelItem => item.dongia)
@Html.ActionLink("Edit", "Edit", new { id=item.ID }) |
@Html.ActionLink("Details", "Details", new { id=item.ID
}) |
@Html.ActionLink("Delete", "Delete", new { id=item.ID
})
}
Đầu tiên trong bảng của chúng ta gồm có tất cả các bản ghi là:
( Docx Converter - Unregistered )
Chạy ứng dụng và điều hướng đến /SanPham/SearchIndex. Thêm vào url
chuỗi truy vấn ?searchString=điện thoại. Các bộ sản phẩm đã lọc ra với tên sản
phẩm= điện thoại được hiển thị.
Ta thử với chuỗi tìm kiếm khác là “máy tính” thì kết quả
( Docx Converter - Unregistered )
Hoặc để trống chuỗi tìm kiếm:
( Docx Converter - Unregistered )
Nếu chúng ta điều chỉnh phương thức SearchIndex để có một tham số với
tên là id, tham số id này sẽ được ghép với vị trí {id} cho đường dẫn mặc định
được gán trong tập tin Global.asax.
{controller}/{action}/{id}
Phương thức SearchIndex được điều chỉnh như sau:
public ActionResult SearchIndex(string id)
{
string searchString = id;
var sanpham = from m in db.SanPhams
select m;
if (!String.IsNullOrEmpty(searchString))
{
sanpham = sanpham.Where(s =>
s.tensp.Contains(searchString));
}
return View(sanpham);
}
Bây giờ chúng ta có thể truyền giá trị tìm kiếm như một đường dẫn dữ liệu
(một phần của URL) thay vì phải truyền một chuỗi truy vấn giá trị.
( Docx Converter - Unregistered )
( Docx Converter - Unregistered )
Tuy nhiên, chúng ta không thể mong đợi người dùng điều chỉnh URL cho
mỗi lần tìm kiếm. vì vậy, bây giờ chúng ta sẽ tạo thêm một User Interface để giúp
họ lọc ra các sản phẩm, thay đổi phương thức SearchIndex để nhận vào chuỗi
tham số có tên searchString:
Mở tập tin Views\SanPham\SearchIndex.cshtml, thêm đoạn mã sau vào
sau @Html.ActionLink(“Create New”, “Create”)
@using (Html.BeginForm())
{
Nhập nội dung tìm kiếm là tên sản phẩm :
@Html.TextBox("SearchString")
( Docx Converter - Unregistered )
}
Html.BeginForm tạo ra một form dạng post back khi người dùng submit
form bằng cách click vào nút “Tìm Kiếm Sản Phẩm”.
Hãy chạy ứng dụng lên:
Và thử tìm kiếm một sản phẩm theo tên là “điện thoại”.
Hoặc tên sản phẩm là “máy tính”:
( Docx Converter - Unregistered )
Sẽ không có nạp chồng phương thức HtpPost SearchIndex. Chúng ta
không cần nó, bởi vì phương thức này không làm thay đổi trạng thái của ứng dụng
mà nó chỉ lọc dữ liệu.
Chúng ta có thể thêm phương thức HttpPost SearchIndex. trong trường
hợp này, hành động gọi ra sẽ được ghép với phương thức HttpPost SearchIndex,
và phương thức này sẽ chạy như hình hiển thị bên dưới.
Để giải quyết vấn đề trên là sử dụng nạp chồng phương thức của
BeginForm chỉ định rõ POST request nên thêm vào thông tin tìm kiếm vào URL
và thông tin này sẽ được gửi đến HttpGet của phương thức SearchIndex. Đặt các
tham số sau vào phương thức BeginForm như sau:
@using (Html.BeginForm("SearchIndex","SanPham",FormMethod
.Post))
Ở trong cửa sổ Code sẽ hiện lên chú thích cho phương thứ BeginForm
( Docx Converter - Unregistered )
Bầy giờ chúng ta submit một tìm kiếm, URL chứa một chuỗi truy vấn. Tìm
kiếm sẽ đi đến phương thức HttpGet SearchIndex, thậm chí chúng ta có phương
thức HtpPost SearchIndex.
Truyền bằng phương thức GET khi truyền qua URL
Truyền bằng phương thức POST khi bấm nút tìm kiếm sản phẩm:
( Docx Converter - Unregistered )
Thêm tìm kiếm theo dòng sản phẩm
Nếu chúng ta đã thêm một phiên bản HttpPost của phương thức
SearchIndex thì hãy xóa nó đi.
Tiếp theo, chúng ta sẽ thêm một tính năng mới cho phép người dùng tìm
kiếm các sản phẩm theo dòng sản phẩm. Sửa lại đoạn mã sau trong phương thức
SearchIndex:
public ActionResult SearchIndex(string madongSP, string
searchString)
{
var ListDongSP= new List();
var QueryDongSp = from d in db.SanPhams
orderby d.madongsp
select d.madongsp;
ListDongSP.AddRange(QueryDongSp.Distinct());
ViewBag.madongSp = new SelectList(ListDongSP);
var sanpham = from m in db.SanPhams
select m;
if (!String.IsNullOrEmpty(searchString))
{
sanpham = sanpham.Where(s => s.tensp.Contains(searchString));
}
if (string.IsNullOrEmpty(madongSP))
return View(sanpham);
else
{
return View(sanpham.Where(x => x.madongsp ==
madongSP));
}
}
( Docx Converter - Unregistered )
Phương thức phương thức SearchIndex nhận vào một tham số là tên thể
loại. Dòng đầu tiên của đoạn mã trên là tạo một danh sách đối tượng để lưu trữ
các thể loại phim từ cơ sở dữ liệu.
Đoạn mã sau đây là một truy vấn LINQ để lấy tất cả các thể loại trong cơ sở dữ liệu.
var QueryDongSp = from d in db.SanPhams
orderby d.madongsp
select d.madongsp;
Đoạn mã sử dụng phương thức AddRange của generic List collection để
thêm tất cả các thể loại(Không trùng nhau) vào trong list.
ListDongSP.AddRange(QueryDongSp.Distinct());
Dòng tiếp theo sau dùng để lưu danh sách các thể loại vào trong đối tượng
ViewBag.
ViewBag.madongSp = new SelectList(ListDongSP);
Đoạn mã sau dùng để kiểm tra tham số madongSp truyền vào. Nếu tham số truyền vào
khác rỗng, kết quả trả về là danh sách các sản phẩm được chọn thỏa điều điều kiện là tên thể
loại có chứa giá trị của tham số truyền vào.
if (string.IsNullOrEmpty(madongSP))
return View(sanpham);
else
{
return View(sanpham.Where(x => x.madongsp == madongSP));
}
Ta sẽ test thử với chuỗi URL:
/SanPham/SearchIndex?madongSP=DTDD
( Docx Converter - Unregistered )
Tương tự với chuỗi URL:
/SanPham/SearchIndex?madongSP=MTB
( Docx Converter - Unregistered )
Thêm các thẻ markup vào SearchIndex View để hỗ trợ việc tìm kiếm theo
dòng sản phẩm
Thêm một helper Html.DropDownList vào tập tin Views\SanPham
\SearchIndex.cshtml ngay trước helper Textbox.Markup hoàn chỉnh như sau:
@Html.ActionLink("Create New", "Create")
@using (Html.BeginForm("SearchIndex","SanPham",FormMethod
.Get))
{
Nhập nội dung tìm kiếm là tên sản phẩm :
@Html.TextBox("SearchString")
Genre: @Html.DropDownList("madongsp", "All")
}
Trong phần này chúng ta đã kiểm tra các phương thức CRUD và các view
được sinh ra bởi framework. Chúng ta đã tạo một phương thức search và view
( Docx Converter - Unregistered )
cho phép người dùng tìm kiếm theo tên sản phẩm và dòng sản phẩm. Trong phần
tiếp theo, chúng ta sẽ biết được cách thêm một thuộc tính vào model SanPham
như thế nào.
Thêm mới một trường vào table và model SanPham
Trong phần này chúng ta sẽ tạo một sự thay đổi trong class model và biết
được cách làm thế nào để cập nhật cơ sở dữ liệu cho phù hợp với sự thay đổi trên
model.
Thêm thuộc tính DanhGiaSanPham vào model SanPham
Bắt đầu bằng cách thêm một thuộc tính DanhGiaSanPham vào class đang
tồn tại. Mở file SanPham.cs và thêm vào thuộc tính như sau:
public string DanhGiaSanPham { get; set; }
Class SanPham hoàn chỉnh có như sau:
namespace NguyenIchHoan.Models
{
public class SanPham
{
//Khai báo các biến toàn cục đại diện cho các trường
public string masp { get; set; }
public int ID { get; set; }
public string tensp { get; set; }
public string mancc { get; set; }
public string madongsp { get; set; }
public string mota { get; set; }
public string anh { get; set; }
public string thongtinthem { get; set; }
public DateTime ngaynhaphang { get; set; }
public decimal dongia { get; set; }
public string DanhGiaSanPham { get; set; }
public class SanPhamDBContext : DbContext
{
public DbSet SanPhams{ get; set; }
}
}
}
Biên dịch lại ứng dụng bằng cách sử dụng lệnh Debug > Build trên menu.
Hiện tại chúng ta đã cập nhật class Model, ngoài ra chúng ta cần cập nhật
các view template \Views\SanPham\Index.cshtml và \Views\SanPham\Create.cshtml
để hỗ trợ thuộc tính Rating.
( Docx Converter - Unregistered )
Mở file \Views\ SanPham\Index.cshtml và thêm vào một cột với tiêu đề là
Đánh Giá Sản Phẩm sau cột Giá Tiền. Sau đó thêm cột
@Html.DisplayFor(modelItem => item.DanhGiaSanPham)
vào gần cuối của template để render giá trị item.DanhGiaSanPham.
Bên dưới là nội dung file view template Index.cshtml đã được cập nhật.
Tiếp theo, mở file \Views\SanPham\Create.cshtml và thêm markup sau vào
gần cuối của form. Markup này sẽ render ra một text box vì vậy chúng ta có thể
thực hiện việc đánh giá khi một sản phẩm mới được tạo ra.
@Html.LabelFor(model => model.DanhGiaSanPham)
@Html.EditorFor(model => model.DanhGiaSanPham)
@Html.ValidationMessageFor(model =>
model.DanhGiaSanPham)
Kiểm soát sự khác nhau giữa lược đồ cơ sở dữ liệu và model
Chúng ta đã cập nhật code của ứng dụng để hỗ trợ thuộc tính
DanhGiaSanPham. Bây giờ chúng ta hãy chạy ứng dụng và navigate đến URL
/SanPham. Khi chúng ta làm điều này, chúng ta sẽ gặp lỗi sau:
( Docx Converter - Unregistered )
Chúng ta gặp lỗi này là vì đã cập nhật class model SanPham trong ứng
dụng hiện tại khác với bảng SanPham đang tồn tài trong csdl. (Không có cột
DanhGiaSanPham trong csdl)
Theo mặc định, khi chúng ta sử dụng Entity Framework Code First để tạo
database tự động, như đã làm từ trước, Code First thêm một bảng vào cơ sở dữ
liệu để giúp theo dõi lược đồ cơ sở dữ liệu có đồng bộ với class model đã được
sinh ra từ nó hay không. Nếu chúng không đồng bộ, Entity Framework sẽ đưa ra
lỗi. Điều này làm cho việc giám dễ dàng sát các lỗi phát sinh trong thời gian phát
triển mà chúng ta chỉ thấy trong lúc thực thi. Đặc trưng kiểm tra đồng bộ này là
nguyên nhân làm xuất hiện thông báo lỗi mà chúng ta đã thấy.
Có hai hướng để tiếp cận giải quyết lỗi:
1. Entity Framework tự động xóa và tạo lại cơ sở dữ liệu dựa trên cơ
sở lược đồ class model mới. Phương pháp này rất thuận tiện khi hoạt động phát
triển thực hiện trên một cơ sở dữ liệu thử nghiệm, bởi vì nó cho phép chúng ta
nhanh chóng triển khai model với lược đồ cơ sở dữ liệu với nhau. Nhược điểm là
( Docx Converter - Unregistered )
sẽ làm mất dữ liệu đang tồn tại trong cơ sở dữ liệu, vì vậy chúng ta không muốn
sử dụng phương pháp tiếp cận này.
2. Chỉnh sửa một cách tường minh trong cơ sở dữ liệu đang tồn tại để
phù hợp với class model. Thuận lợi của phương pháp này là chúng ta có thể giữ
được dữ liệu. Chúng ta có thể thực hiện việc điều chỉnh bằng tay hoặc tạo script
điều chỉnh database.
Với hướng dẫn này, chúng ta sẽ sử dụng phương pháp thứ nhất, chúng ta
sẽ có Entity Framework Code First tự động tạo lại cơ sở dữ liệu bất kỳ lúc nào
model thay đổi.
Tự động tạo lại csdl dựa trên sự thay đổi của model
Hãy cập nhật lại ứng dụng vì Code First tự động xóa và tạo lại cơ sở dữ
liệu bất kỳ thời điểm nào khi chúng ta điều chỉnh model cho ứng dụng.
Trong Solution Explorer, click phải trên folder Models, chọn Add, và sau
đó chọn Class.
Đặt tên class là “SanPhamInitializer”. Cập nhật class SanPhamInitializer
với nội dụng sau:
public class SanPhamInitializer : DropCreateDatabaseIfModelChanges<
SanPhamDBContext>
{
protected override void Seed(SanPhamDBContext context)
{
var SanPhams = new List {
new SanPham { masp="sp001",
tensp="Nokia6300",
mancc="Nokia",
madongsp ="DTDD",
ngaynhaphang=DateTime.Parse("2013-1-11"),
DanhGiaSanPham="Good",
dongia=7.99M
},
new SanPham{ masp="sp002",
tensp="Nokia7700",
mancc="Nokia",
madongsp ="DTDD",
( Docx Converter - Unregistered )
ngaynhaphang=DateTime.Parse("2013-1-11"),
DanhGiaSanPham="Good",
dongia=15.99M
},
new SanPham{ masp="sp003",
tensp="Galaxy III",
mancc="SS",
madongsp ="MTB",
ngaynhaphang=DateTime.Parse("2013-1-11"),
DanhGiaSanPham="Very Good",
dongia=20.99M
},
new SanPham{ masp="sp004",
tensp="Galaxy II",
mancc="SS",
madongsp ="MTB",
ngaynhaphang=DateTime.Parse("2013-1-11"),
DanhGiaSanPham="Good",
dongia=14.99M},
};
SanPhams.ForEach(d => context.SanPhams.Add(d));
}
}
Clas SanPhamInitializer chỉ định csdl sử dụng bởi model nên được xóa và
tự động tạo lại nếu class model có bất kì sự thay đổi nào. Code trên bao gồm
phương thức Seed để chỉ định một vài dữ liệu mặc định để tự động thêm vào csdl
bất kỳ khi nào nó được tạo ra (hoặc tạo lại). Ưu điểm của phương pháp này là dữ
liệu mẫu trong csdl được tự động populate mà chúng ta không cần thực hiện bằng
tay khi có sự thay đổi trên model.
Hiện tại chúng ta đã định nghĩa xong class SanPhamInitializer, chúng ta
muốn thực hiện nó mỗi lần ứng dụng thực thi, nó kiểm tra sự khác nhau giữ class
model và lược đồ csdl. Nếu tìm thấy sự khác nhau, chúng ta có thể chạy initializer
để tại lại csdl cho phù hợp với class model và sau đó thêm vào csdl với dữ liệu
mẫu.
Mở file Global.asax trong project:
( Docx Converter - Unregistered )
Tập tin Global.asax chứa class mà nó định nghĩa cho toàn bộ ứng dụng cho
project, và chứa sự kiện Applocation_Start thực thi khi ứng dụng bắt đầu lần đầu
tiên.
Trong tập tin Global.asax chúng ta using thêm hai namespace, namespace
thứ nhât để sử dụng Entity Framework và namespace thứ hai để sử dụng class
SanPhamInitializer:
using System.Data.Entity; // Database.SetInitialize
using NguyenIchHoan.Models; // SanPhamInitializer
Sau đó tìm phương thức Application_Start và gọi Database.SetInitializer
vào đầu phương thức, như trình bày bên dưới:
( Docx Converter - Unregistered )
Việc chúng ta gọi Database.SetInitializer là để chỉ ra là database dùng bởi
SanPhamDBContext nên được tự động xóa hoặc tạo lại nếu lược đồ và database
không phù hợp với nhau. Như chúng ta thấy, nó sẽ thêm vào database dữ liệu mẫu
đã được xác định trong class SanPhamInitializer.
Đóng file Gobal.asaxThực thi lại ứng dụng và navigate đến URL
/SanPham. Khi ứng dụng bắt đầu, nó sẽ phát hiện cấu trúc của model không phù
hợp với lược đồ csdl. Nó sẽ tự động tạo lại database để cho phù hợp với cấu trúc
model mới và thêm vào csdl với một ít dữ liệu mẫu:
Cl
Các file đính kèm theo tài liệu này:
- giao_trinh_mo_hinh_mvc_3_nguyen_ich_hoan_7502.pdf