演练2-5 电影网站的功能扩展

原文链接:

http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/examining-the-edit-methods-and-edit-view

http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/adding-a-new-field-to-the-movie-model-and-table    

    接下来,我们将使用Entity Framework Code First Migrations,来对模型类的改变做数据迁移,而数据库能相应改变。 

    默认情况下,当你使用EF Code First自动生成数据库时,Code First添加了一个数据库来跟踪数据库和模型类的同步状况。如果它们不同步,EF会抛出一个异常。

一、添加Search动作和视图

    我们将添加一个SerachIndex动作,能够通过类别或名字搜索电影,网址为\Movies\SearchIndexURL。

1.显示SearchIndex表单

    在Movies控制器中,添加SearchIndex()动作。

public ActionResult SearchIndex(string searchString) 
{           
    var movies = from m in db.Movies 
                 select m; 
 
    if (!String.IsNullOrEmpty(searchString)) 
    { 
        movies = movies.Where(s => s.Title.Contains(searchString)); 
    } 
 
    return View(movies); 
}

    s=>s.Title是一个Lambda表达式。
    在SearchIndex()动作中右击“添加视图”。

@model IEnumerable<MvcMovie.Models.Movie> 
 
@{ 
    ViewBag.Title = "SearchIndex"; 
} 
 
<h2>SearchIndex</h2> 
 
<p> 
    @Html.ActionLink("Create New", "Create") 
</p> 
<table> 
    <tr> 
        <th> 
            Title 
        </th> 
        <th> 
            ReleaseDate 
        </th> 
        <th> 
            Genre 
        </th> 
        <th> 
            Price 
        </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.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>

    运行应用程序,导航至/Movies/SearchIndex?searchString=ghost网址。

    然而不可能希望用户每次通过路由来搜索电影,现在我们将在SearchIndex视图中添加搜索文本框,就在@Html.ActionLink("Create New", "Create")后面。

@model IEnumerable<MvcMovie.Models.Movie> 
 
@{ 
    ViewBag.Title = "SearchIndex"; 
} 
 
<h2>SearchIndex</h2> 
 
<p> 
    @Html.ActionLink("Create New", "Create") 
     
     @using (Html.BeginForm()){    
         <p> Title: @Html.TextBox("SearchString") <br />   
         <input type="submit" value="Filter" /></p> 
        } 
</p>

    运行应用程序,使用搜索电影功能。

2.添加按类型搜索

     修改该Movies控制器中SearchIndex动作。

public ActionResult SearchIndex(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(searchString)) 
    { 
        movies = movies.Where(s => s.Title.Contains(searchString)); 
    } 
 
    if (string.IsNullOrEmpty(movieGenre)) 
        return View(movies); 
    else 
    { 
        return View(movies.Where(x => x.Genre == movieGenre)); 
    } 
 
}

    修改SearchIndex视图,添加一个Html.DropDownList来显示类别。

<p> 
    @Html.ActionLink("Create New", "Create") 
    @using (Html.BeginForm("SearchIndex","Movies",FormMethod.Get)){     
         <p>Genre: @Html.DropDownList("movieGenre", "All")   
           Title: @Html.TextBox("SearchString")   
         <input type="submit" value="Filter" /></p> 
        } 
</p>

    运行应用程序,导航至/Movies/SearchIndex,试着按类别和名字搜索。

二、在Movie模型中添加一个新字段Rating

1.当模型改变时,创建Code First数据迁移

(1)删除Movie数据库

    删除服务器连接中的MovieDBContext连接。

    删除App_Data文件夹下的数据库文件Movies.mdf。

    生成解决方案,确保程序没有问题。

    点击“工具"菜单,点击“库程序包管理器 | 程序包管理器控制台“。

    在程序包管理器控制台窗口中,输入"Enable-Migrations -ContextTypeName MvcMovie.Models.MovieDBContext”。

    Enable-Migrations命令,新建了一个Migrations文件夹,里面有Configuration.cs文件。

    打开Configuration.cs文件,将其中的Seed()方法修改如下。

protected override void Seed(MvcMovie.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
       }
   );
   
}

    每次迁移后,Code First调用Seed()方法,更新数据库数据,如果不存在则创建。

    此时生成解决方案,否则会出错。

    接下来,创建一个DbMigration类来初始化数据迁移。在此,迁移将创建一个新的数据库,所以之前需要先删除movie.mdf文件。

    在程序包管理控制台窗口中,输入命令“add-migration Initial”,创建初始迁移。“Initial”名字是任意的,它命名了这次迁移的名字。

    Code First迁移在Migrations文件夹中创建了一个类文件({DateStamp}_Initial.cs),这个类包含了创建数据库的模式代码。然后Seed()方法会运行,使数据库中得到测试数据。

    输入命令"update-database”,创建数据库,运行Seed()方法。

    如果你遇到错误提示说数据表已经存在,不能创建,可能是因为你在删除数据库后又运行过程序。这样的话,再次删除Movies.mdf文件,重新运行命令”update-database”。如果仍旧遇到问题,删除Migrations文件夹,删除数据库文件和服务器链接。

    运行程序,并导航至/Movies网址。

2.在Movie模型类中添加Rating属性

    打开Models\Movie.cs文件,添加属性代码如下。

    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; }
        public string Rating { get; set; }
    }

    生成解决方案。更新\Views\Movies\Index.cshtml视图如下。

@model IEnumerable<MvcMovie.Models.Movie>

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
<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>

     接下来,打开\Views\Movies\Create.cshtml文件,修改代码如下。

<div class="editor-label">
    @Html.LabelFor(model => model.Rating)
</div>
<div class="editor-field">
    @Html.EditorFor(model => model.Rating)
    @Html.ValidationMessageFor(model => model.Rating)
</div>

    运行程序,导航至/Movies网址,遇到错误如下。

    这个错误是因为Movie模型类改变过了,和现有数据库不一致,可以通过以下方案解决:

(1)删除数据库文件和服务器数据连接。这样做虽然简单,但是会丢失所有的数据。

(2)手动修改现有数据库,已达到与模型类文件一致。这样已有的数据库数据得到保存。

(3)使用Code First数据迁移更新数据库模式。

    我们将使用第三种方法。打开Migrations\Configuration.cs文件,添加Rating字段到每个Movie对象。

new Movie
        {
            Title = "When Harry Met Sally",
            ReleaseDate = DateTime.Parse("1989-1-11"),
            Genre = "Romantic Comedy",
            Rating = "G",
            Price = 7.99M
        },

    生成解决方案,打开程序包管理控制台,输入命令“add-migration AddRatingMig”。命令执行后,VS会打开AddRatingMig文件,在Up()方法中,创建了rate列。

    生成解决方案,输入命令“update-database”。

    重新运行应用程序,导航至/Movies网址,查看Rate字段。

 

posted @ 2014-09-18 09:31  liesl  阅读(423)  评论(0编辑  收藏  举报