᳓前言
本篇文章將"Adding a New Field"整理而成。᳓重點整理
- 在完全沒有資料庫檔案的狀況下,透過Code First建立資料庫及資料表。
- 在已經透過Code First建立的資料庫中,進行資料表的修改。
記得先刪除在之前的練習中自動建立的App_Data/*.mdf檔案後再進行下列的練習。
᳓實作2. 啟用Migrations-在Package Manager Console輸入指令
1. 輸入"Enable-Migrations -ContextTypeName {WebApplication1}.Models.MovieDBContext"->Enter |
2. 指令執行完畢後,會在專案中自動建立Migrations資料夾,且在該資料夾中新增Configuration.cs檔案 |
᳓實作3. 新增Migration-修改Migrations/Configuration.cs、在Package Manager Console輸入指令
修改完Congiguration.cs之後,一定要先重建專案,否則指令會執行失敗。當"add-migration Initial"指令執行完畢後,會自動產生所變更內容的{201804021004386}_Initial.cs檔案。需要注意的是,每次進行Code First Migrations (也就是輸入下一步的update-database指令)都會執行Seed()方法中的程式碼。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace WebApplication1.Migrations | |
{ | |
using System; | |
using System.Data.Entity; | |
using System.Data.Entity.Migrations; | |
using System.Linq; | |
using WebApplication1.Models; // Movie | |
internal sealed class Configuration : DbMigrationsConfiguration<WebApplication1.Models.MovieDBContext> | |
{ | |
public Configuration() | |
{ | |
AutomaticMigrationsEnabled = false; | |
} | |
protected override void Seed(WebApplication1.Models.MovieDBContext context) | |
{ | |
context.Movies.AddOrUpdate(i => i.Title, | |
new Movie | |
{ | |
Title = "When Harry Met Sally", | |
ReleaseDate = DateTime.Parse("1989-1-11"), | |
Genre = "Romantic Comedy", | |
Price = 7.99M | |
}, | |
new Movie | |
{ | |
Title = "Ghostbusters ", | |
ReleaseDate = DateTime.Parse("1984-3-13"), | |
Genre = "Comedy", | |
Price = 8.99M | |
}, | |
new Movie | |
{ | |
Title = "Ghostbusters 2", | |
ReleaseDate = DateTime.Parse("1986-2-23"), | |
Genre = "Comedy", | |
Price = 9.99M | |
}, | |
new Movie | |
{ | |
Title = "Rio Bravo", | |
ReleaseDate = DateTime.Parse("1959-4-15"), | |
Genre = "Western", | |
Price = 3.99M | |
} | |
); | |
} | |
} | |
} |
1. 輸入"add-migration Initial"->Enter |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace WebApplication1.Migrations | |
{ | |
using System; | |
using System.Data.Entity.Migrations; | |
public partial class Initial : DbMigration | |
{ | |
public override void Up() | |
{ | |
CreateTable( | |
"dbo.Movies", | |
c => new | |
{ | |
ID = c.Int(nullable: false, identity: true), | |
Title = c.String(), | |
ReleaseDate = c.DateTime(nullable: false), | |
Genre = c.String(), | |
Price = c.Decimal(nullable: false, precision: 18, scale: 2), | |
}) | |
.PrimaryKey(t => t.ID); | |
} | |
public override void Down() | |
{ | |
DropTable("dbo.Movies"); | |
} | |
} | |
} |
當"update-database"指令執行完畢,便已完成資料庫、資料表的建立,可開啟瀏覽器查看。
1. 輸入"update-database"->Enter |
2. 網址列輸入"http://{localhost:port}/Movies/Index" |
᳓實作5. 新增Rating新欄位-修改Models/Movie.cs、Controllers/MoviesController.cs、Views/Movies/Index.cshtml、Views/Movies/Create.cshtml、
接著要在Movie.cs新增一個Rating欄位,因此MoviesController.cs的Create Action需要增加Bind的欄位、Index.cshtml及Create.cshtml需要增加輸入欄位,而其他頁面,像是Edit.cshtml、Details.cshtml、Delete.cshtml也需要修改,但在這裡省略說明。值得注意的是,修改完畢後可以成功重建專案,但在瀏覽器瀏覽時會出現下圖的錯誤訊息,那是因為Model已經修改,但資料表還沒有更新,所以會以錯誤訊息提示必須更新資料表。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.ComponentModel.DataAnnotations; // Display | |
using System.Data.Entity; // DbContext | |
using System.Linq; | |
using System.Web; | |
namespace WebApplication1.Models | |
{ | |
public class Movie | |
{ | |
public int ID { get; set; } | |
public string Title { get; set; } | |
[Display(Name = "Rease Date")] | |
[DataType(DataType.Date)] | |
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)] | |
//[DisplayFormat(DataFormatString = "0:d", ApplyFormatInEditMode = true)] | |
public DateTime ReleaseDate { get; set; } | |
public string Genre { get; set; } | |
public decimal Price { get; set; } | |
public string Rating { get; set; } | |
} | |
public class MovieDBContext : DbContext | |
{ | |
public DbSet<Movie> Movies { get; set; } | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Data; | |
using System.Data.Entity; | |
using System.Linq; | |
using System.Net; | |
using System.Web; | |
using System.Web.Mvc; | |
using WebApplication1.Models; | |
namespace WebApplication1.Controllers | |
{ | |
public class MoviesController : Controller | |
{ | |
private MovieDBContext db = new MovieDBContext(); | |
// GET: Movies/Index?searchString={text} | |
public ActionResult Index(string movieGenre, string searchString) | |
{ | |
var GenreLst = new List<string>(); | |
var GenreQry = (from d in db.Movies | |
orderby d.Genre | |
select d.Genre); | |
GenreLst.AddRange(GenreQry.Distinct()); | |
ViewBag.movieGenre = new SelectList(GenreLst, "愛情片"); | |
var movies = (from m in db.Movies | |
select m); | |
if (!String.IsNullOrEmpty(movieGenre)) | |
{ | |
movies = movies.Where(s => s.Genre == movieGenre); | |
} | |
if(!String.IsNullOrEmpty(searchString)) | |
{ | |
movies = movies.Where(s => s.Title.Contains(searchString)); | |
} | |
return View(movies); | |
} | |
// GET: Movies/Details/5 | |
public ActionResult Details(int? id) | |
{ | |
if (id == null) | |
{ | |
return new HttpStatusCodeResult(HttpStatusCode.BadRequest); | |
} | |
Movie movie = db.Movies.Find(id); | |
if (movie == null) | |
{ | |
return HttpNotFound(); | |
} | |
return View(movie); | |
} | |
// GET: Movies/Create | |
public ActionResult Create() | |
{ | |
return View(); | |
} | |
// POST: Movies/Create | |
// To protect from overposting attacks, please enable the specific properties you want to bind to, for | |
// more details see http://go.microsoft.com/fwlink/?LinkId=317598. | |
[HttpPost] | |
[ValidateAntiForgeryToken] | |
public ActionResult Create([Bind(Include = "ID,Title,ReleaseDate,Genre,Price,Rating")] Movie movie) | |
{ | |
if (ModelState.IsValid) | |
{ | |
db.Movies.Add(movie); | |
db.SaveChanges(); | |
return RedirectToAction("Index"); | |
} | |
return View(movie); | |
} | |
// GET: Movies/Edit/5 | |
public ActionResult Edit(int? id) | |
{ | |
if (id == null) | |
{ | |
return new HttpStatusCodeResult(HttpStatusCode.BadRequest); | |
} | |
Movie movie = db.Movies.Find(id); | |
if (movie == null) | |
{ | |
return HttpNotFound(); | |
} | |
return View(movie); | |
} | |
// POST: Movies/Edit/5 | |
// To protect from overposting attacks, please enable the specific properties you want to bind to, for | |
// more details see http://go.microsoft.com/fwlink/?LinkId=317598. | |
[HttpPost] | |
[ValidateAntiForgeryToken] | |
public ActionResult Edit([Bind(Include = "ID,Title,ReleaseDate,Genre,Price")] Movie movie) | |
{ | |
if (ModelState.IsValid) | |
{ | |
db.Entry(movie).State = EntityState.Modified; | |
db.SaveChanges(); | |
return RedirectToAction("Index"); | |
} | |
return View(movie); | |
} | |
// GET: Movies/Delete/5 | |
public ActionResult Delete(int? id) | |
{ | |
if (id == null) | |
{ | |
return new HttpStatusCodeResult(HttpStatusCode.BadRequest); | |
} | |
Movie movie = db.Movies.Find(id); | |
if (movie == null) | |
{ | |
return HttpNotFound(); | |
} | |
return View(movie); | |
} | |
// POST: Movies/Delete/5 | |
[HttpPost, ActionName("Delete")] | |
[ValidateAntiForgeryToken] | |
public ActionResult DeleteConfirmed(int id) | |
{ | |
Movie movie = db.Movies.Find(id); | |
db.Movies.Remove(movie); | |
db.SaveChanges(); | |
return RedirectToAction("Index"); | |
} | |
protected override void Dispose(bool disposing) | |
{ | |
if (disposing) | |
{ | |
db.Dispose(); | |
} | |
base.Dispose(disposing); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@model IEnumerable<WebApplication1.Models.Movie> | |
@{ | |
ViewBag.Title = "Index"; | |
} | |
<h2>Index</h2> | |
<p> | |
@Html.ActionLink("Create New", "Create") | |
@using (Html.BeginForm("Index", "Movies", FormMethod.Get)) | |
{ | |
<p> | |
類型:@Html.DropDownList("movieGenre", "全部") | |
標題:@Html.TextBox("searchString")<br /> | |
<input type="submit" value="搜尋" /> | |
</p> | |
} | |
</p> | |
<table class="table"> | |
<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> | |
@Html.DisplayNameFor(model => model.Rating) | |
</th> | |
<th></th> | |
</tr> | |
@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> | |
@Html.DisplayFor(modelItem => item.Rating) | |
</td> | |
<td> | |
@Html.ActionLink("Edit", "Edit", new { id=item.ID }) | | |
@Html.ActionLink("Details", "Details", new { id=item.ID }) | | |
@Html.ActionLink("Delete", "Delete", new { id=item.ID }) | |
</td> | |
</tr> | |
} | |
</table> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@model WebApplication1.Models.Movie | |
@{ | |
ViewBag.Title = "Create"; | |
} | |
<h2>Create</h2> | |
@using (Html.BeginForm()) | |
{ | |
@Html.AntiForgeryToken() | |
<div class="form-horizontal"> | |
<h4>Movie</h4> | |
<hr /> | |
@Html.ValidationSummary(true, "", new { @class = "text-danger" }) | |
<div class="form-group"> | |
@Html.LabelFor(model => model.Title, htmlAttributes: new { @class = "control-label col-md-2" }) | |
<div class="col-md-10"> | |
@Html.EditorFor(model => model.Title, new { htmlAttributes = new { @class = "form-control" } }) | |
@Html.ValidationMessageFor(model => model.Title, "", new { @class = "text-danger" }) | |
</div> | |
</div> | |
<div class="form-group"> | |
@Html.LabelFor(model => model.ReleaseDate, htmlAttributes: new { @class = "control-label col-md-2" }) | |
<div class="col-md-10"> | |
@Html.EditorFor(model => model.ReleaseDate, new { htmlAttributes = new { @class = "form-control" } }) | |
@Html.ValidationMessageFor(model => model.ReleaseDate, "", new { @class = "text-danger" }) | |
</div> | |
</div> | |
<div class="form-group"> | |
@Html.LabelFor(model => model.Genre, htmlAttributes: new { @class = "control-label col-md-2" }) | |
<div class="col-md-10"> | |
@Html.EditorFor(model => model.Genre, new { htmlAttributes = new { @class = "form-control" } }) | |
@Html.ValidationMessageFor(model => model.Genre, "", new { @class = "text-danger" }) | |
</div> | |
</div> | |
<div class="form-group"> | |
@Html.LabelFor(model => model.Price, htmlAttributes: new { @class = "control-label col-md-2" }) | |
<div class="col-md-10"> | |
@Html.EditorFor(model => model.Price, new { htmlAttributes = new { @class = "form-control" } }) | |
@Html.ValidationMessageFor(model => model.Price, "", new { @class = "text-danger" }) | |
</div> | |
</div> | |
<div class="form-group"> | |
@Html.LabelFor(model => model.Rating, htmlAttributes: new { @class = "control-label col-md-2" }) | |
<div class="col-md-10"> | |
@Html.EditorFor(model => model.Rating, new { htmlAttributes = new { @class = "form-control" } }) | |
@Html.ValidationMessageFor(model => model.Rating, "", new { @class = "text-danger" }) | |
</div> | |
</div> | |
<div class="form-group"> | |
<div class="col-md-offset-2 col-md-10"> | |
<input type="submit" value="Create" class="btn btn-default" /> | |
</div> | |
</div> | |
</div> | |
} | |
<div> | |
@Html.ActionLink("Back to List", "Index") | |
</div> |
1. 網址列輸入"http://{localhost:port}/Movies/Index" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace WebApplication1.Migrations | |
{ | |
using System; | |
using System.Data.Entity; | |
using System.Data.Entity.Migrations; | |
using System.Linq; | |
using WebApplication1.Models; // Movie | |
internal sealed class Configuration : DbMigrationsConfiguration<WebApplication1.Models.MovieDBContext> | |
{ | |
public Configuration() | |
{ | |
AutomaticMigrationsEnabled = false; | |
} | |
protected override void Seed(WebApplication1.Models.MovieDBContext context) | |
{ | |
context.Movies.AddOrUpdate(i => i.Title, | |
new Movie | |
{ | |
Title = "When Harry Met Sally", | |
ReleaseDate = DateTime.Parse("1989-1-11"), | |
Genre = "Romantic Comedy", | |
Price = 7.99M, | |
Rating = "PG" | |
}, | |
new Movie | |
{ | |
Title = "Ghostbusters ", | |
ReleaseDate = DateTime.Parse("1984-3-13"), | |
Genre = "Comedy", | |
Price = 8.99M, | |
Rating = "PG" | |
}, | |
new Movie | |
{ | |
Title = "Ghostbusters 2", | |
ReleaseDate = DateTime.Parse("1986-2-23"), | |
Genre = "Comedy", | |
Price = 9.99M, | |
Rating = "PG" | |
}, | |
new Movie | |
{ | |
Title = "Rio Bravo", | |
ReleaseDate = DateTime.Parse("1959-4-15"), | |
Genre = "Western", | |
Price = 3.99M, | |
Rating = "PG" | |
} | |
); | |
} | |
} | |
} |
1. 輸入"add-migration Rating"->Enter |
2. 輸入"update-database"->Enter |
3. 網址列輸入"http://{localhost:port}/Movies/Index"可以看到Rating欄位已經輸入預設值"PG" |