Giáo trình Mô hình MVC

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.

pdf120 trang | Chia sẻ: NamTDH | Lượt xem: 1594 | Lượt tải: 0download
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:

  • pdfgiao_trinh_mo_hinh_mvc_3_nguyen_ich_hoan_7502.pdf
Tài liệu liên quan