mvc數據遷移

在本节中,我们将使用Entity Framework Code First 数据迁移功能将模型类的改变应用到数据库中。

默 认情况下,当我们使用Entity Framework Code First 自动创建一个数据库,像我们之前教程中讲的那样,Code First 添加一个table帮我们跟踪数据库结构是否与模型类同步。如果不同步,Entity Framework 将抛出一个错误,这样更方便我们在开发的时候发现问题,否则只能在运行时通过晦涩的错误来查找了。

为模型更改设置 Code First 数据迁移

在解决方案资源管理器中,删除自动创建的 Movies.mdf 文件。

在工具菜单中,选择“库程序包管理器”>“程序包管理器控制台”:

图1:打开“程序包管理器控制台”菜单项

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

图2:运行命令

Enable-Migrations 命令创建了一个Migrations文件夹和Configuration.cs文件。

图3:新添加的文件

打开 Configuration.cs 文件,使用以下代码替换 Seed 方法:

代码清单1:Seed 方法 - Configruation.cs

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
       }
   );
}

使用这段代码的时候,需要添加 using MvcMovie.Models 的引用。

Code First 数据迁移在每次迁移(在程序包管理器控制台中调用 update-database)的时候都会调用Seed方法。

在进行下一步之前,先编译解决方案,否则下一步会出错误。

下一步,为初始化迁移创建一个 DbMigration 类。这次迁移创建一个新数据库,这也是我们为什么要删除之前的数据库的原因。

在“程序包管理器控制台”窗口,输入命令 add-migration Initial  创建初始化迁移。名称“Initial”是随意命名的,它用来命名创建好的迁移文件。

图4:创建初始化迁移

Code First Migrations 创建在Migrations文件夹中创建了一个文件(文件名是 {DateStamp}_Initial.cs ),这个类包含了创建数据库结构的代码。迁移文件的文件名以DateStamp开头是为了更好的排序,打开 {DateStamp}_Initial.cs  文件,它包含了为数据库MovieDB创建Movies表的指令。当你使用下面的命令更新数据库时,{DateStamp}_Initial.cs  文件将会运行并创建数据库结构,然后将执行 Seed 方法将测试数据插入数据库中。

在“程序包管理器控制台”中输入命令 update-database

图5:执行更新数据库命令

运行应用程序,浏览/Movies 地址,我们在Seed方法中添加的数据如下:

图6:浏览程序

为Movie模型添加Rating字段

上面的内容一直在介绍如何进行数据迁移,现在开始为Movie类添加Rating字段,打开Movie.cs 文件,为它添加一个Rating字段,添加后的代码如下:

代码清单2:添加Rating字段后的Movie类

public class Movie
{
    public int ID { get; set; }
    public string Title { get; set; }
    [Display(Name = "Release Date")]
    [DataType(DataType.Date)]
    public DateTime ReleaseDate { get; set; }
    public string Genre { get; set; }
    public decimal Price { get; set; }
    set; }
}

编译解决方案。

现在我们已经更新了Movie类,你还需要修改\Views\Movies\Index.cshtml  和 \Views\Movies\Create.cshtml 视图。修改后的代码如下:

代码清单3:修改后的Index.cshtml

@model IEnumerable<MvcMovie.Models.Movie>

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
@using (Html.BeginForm("Index", "Movies", FormMethod.Get))
{
    <p>
        Genre: @Html.DropDownList("movieGenre", "All")
        Title: @Html.TextBox("SearchString") <br />
        <input type="submit" value="Filter" />
    </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>

代码清单3:修改后的Create.cshtml

@model MvcMovie.Models.Movie

@{
    ViewBag.Title = "Create";
}

<h2>Create</h2>

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true)

    <fieldset class="form-horizontal">
        <legend>Movie</legend>

        <div class="control-group">
            @Html.LabelFor(model => model.Title, new { @class = "control-label" })
            <div class="controls">
                @Html.EditorFor(model => model.Title)
                @Html.ValidationMessageFor(model => model.Title, null, new { @class = "help-inline" })
            </div>
        </div>

        <div class="control-group">
            @Html.LabelFor(model => model.ReleaseDate, new { @class = "control-label" })
            <div class="controls">
                @Html.EditorFor(model => model.ReleaseDate)
                @Html.ValidationMessageFor(model => model.ReleaseDate, null, new { @class = "help-inline" })
            </div>
        </div>

        <div class="control-group">
            @Html.LabelFor(model => model.Genre, new { @class = "control-label" })
            <div class="controls">
                @Html.EditorFor(model => model.Genre)
                @Html.ValidationMessageFor(model => model.Genre, null, new { @class = "help-inline" })
            </div>
        </div>

        <div class="control-group">
            @Html.LabelFor(model => model.Price, new { @class = "control-label" })
            <div class="controls">
                @Html.EditorFor(model => model.Price)
                @Html.ValidationMessageFor(model => model.Price, null, new { @class = "help-inline" })
            </div>
        </div>

div class="control-group">
            @Html.LabelFor(model => model.Rating, new { @class = "control-label" div class="controls">
                @Html.EditorFor(model => model.Rating)
                @Html.ValidationMessageFor(model => model.Rating, null, new { @class = "help-inline" div>
        </div>

        <div class="form-actions no-color">
            <input type="submit" value="Create" class="btn" />
        </div>
    </fieldset>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

现在我们已经在程序中为Rating字段做成了修改。再次运行程序,浏览/movies 地址,这时我们会得到一个错误:

图7:错误页面

出现这个错误的原因是Movie模型类发生了变化,而与它对应的数据表 Movie 中并不存在Rating字段。

There are a few approaches to resolving the error:

解决这个问题有以下几种途径:

  1. 让Entity Framework自动删除并根据新的模型自动创建数据库。这种方式在早起开发过程中的测试数据库中非常方便,它可以快速的修改模型和数据库结构。另一方面,这样做将会使你丢失已有的数据,因此这种方式不能用在生产环境的数据库中。
  2. 在数据库中加上Rating字段,使数据库和Model类的结构相同。这种方式的优点是能够保留数据,你可以手动修改或使用数据库脚本修改。
  3. 使用Code First 迁移来升级数据库结构。

在本教程中,我们使用Code First 迁移。

更新Seed 方法,使它为Rating字段提供一个值。打开 Migrations\Configuration.cs 文件,为每一个Movie对象的Rating字段赋值。

代码清单4:修改后的Seek方法

protected override void Seed(MvcMovie.Models.MovieDBContext context)
{
    context.Movies.AddOrUpdate(i => i.Title,
        new Movie
        {
            Title = "龙门飞甲",
            ReleaseDate = DateTime.Parse("2012-1-11"),
            Genre = "动作",
            Price = 30M,
            Rating = "优"
        },
        new Movie
        {
            Title = "冰河世纪",
            ReleaseDate = DateTime.Parse("2011-3-1"),
            Genre = "动漫",
            Price = 65M,
            Rating = "良"
        },
        new Movie
        {
            Title = "中国合伙人",
            ReleaseDate = DateTime.Parse("2013-6-18"),
            Genre = "励志",
            Price = 70M,
            Rating = "良"
        }
   );
}

重新编译解决方案,然后打开“程序包管理器控制台”,执行命令:add-migration Rating

add-migration 命令告诉迁移程序去检查当前的Movie模型与当前数据库之间的差异,创建迁移数据库到最新模型的代码。名称 Rating 是可以随便命名的,此处用来命名迁移文件。

当命令执行完成之后,Visual Studio 会打开刚刚添加的继承自 DbMigration 的类文件,文件中有两个方法 Up和Down,分别用来升级和降级数据库。在Up方法中我们可以看到为数据库添加列的代码,而Down方法中的代码则是删除Rating列。

代码清单5:Rating类

public partial class Rating : DbMigration
{
    public override void Up()
    {
        AddColumn("dbo.Movies", "Rating", c => c.String());
    }

    public override void Down()
    {
        DropColumn("dbo.Movies", "Rating");
    }
}

编译解决方案,然后执行命令 update-database 。“程序包管理器控制台”窗口的输出如下图(Rating前的时间戳可能不尽相同):

图8:更新数据库

刷新我们出错的页面,你能看到已经加入了Rating字段:

图9:加入了Rating字段的界面

点击“Create New”链接试着添加一个电影信息,不要忘记为Rating字段赋值。

图10:新增页面

输入完成之后点击“Create”按钮,保存电影信息。

图11:保存后的列表

你还需要在Edit、Details和Delete视图中添加Rating字段。

如果你再次执行 "update-database" 命令,将不会做出任何修改,因为数据库结构和模型的结构已经相同了。

现在,通过项目中使用数据迁移,我们在添加字段或更新模型结构的时候不用再删除数据库了。在下一节中,我们将对结构做出更多的更改,并使用数据迁移来更新数据库。

时间: 2024-12-08 22:27:30

mvc數據遷移的相关文章

MVC+Ninject+三层架构+代码生成 -- 总结(四、數據層)

1.數據層使用了SqlSugar 庫類 . 數據層使用了SqlSugar 庫類 ,有興趣的 可以學習  http://www.codeisbug.com/Doc/8/1133,個人覺得比EF 簡單,容易上手,推薦+1. 數據層使用代碼生成,所以考慮得比較多. 1.GetAllList()--獲取全部數據 2.GetAllListByCache()--通過緩存獲取全部數據 3.GetListByCondition(string queryJson)--通過條件獲取數據 4.GetListByPag

數據準備是大數據分析的無名英雄

隨著企業花越來越多的時間來分析數據,清理和準備數據的解決方案將會變得更有價值 現在大數據[注]是熱門話題,你在任何地方與任何人交談很難不提到大數據.事實上,大數據的術語有點被過度使用,它對不同的人意味著不同的東西,但所有這些定義都有一個共同點,那就是數據! 上面我們說大數據依賴於數據,這似乎很明顯,但大數據分析的成功需要的不僅僅是原始數據,還需要好的高質量數據.所以,更準確的說法應該是,大數據的成功需要準備好的數據.對於分析,有句古老的格言,「進來是垃圾,出去也是垃圾」,這意味著如果你把大量參差

Active Record: 資料庫遷移(Migration) (转)

Active Record: 資料庫遷移(Migration) Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the Universe trying to produce bigger and better idiots. So far, the Universe is winning. - Rick Cook

「量化風投」:用數據挖掘潛在項目

形勢變遷:創業者有了更多話語權曾就職於風投機構GeneralCatalyst和BessemerVenturePartners的克里斯·法爾莫(ChrisFarmer)指出,風投行業曾經是個封閉的圈子,只有少數基金能接觸到谷歌.Facebook這種企業.法爾莫正在籌建一家基於數據的新基金並計劃於明年初開始融資,該基金能以智能化方式向投資人提供來自CrunchBase.社交媒體.網頁計量和多個獨家數據來源的大量信息,從而幫助投資人判斷最佳投資機會.法爾莫解釋了如今的形勢變化:在過去,風投機構可以憑藉

數據挖掘的七大任務

數據挖掘的任務可以分為:分類.聚類.關聯.回歸.預測.序列分析等,具體的介紹如下:一.分類:分類是找出資料庫中一組數據對象的共同特點並按照分類模式將其劃分為不同的類,其目的是通過分類模型,將資料庫中的數據項映射到某個給定的類別.它可以應用到客戶的分類.客戶的屬性和特徵分析.客戶滿意度分析.客戶的購買趨勢預測等,如一個汽車零售商將客戶按照對汽車的喜好劃分成不同的類,這樣營銷人員就可以將新型汽車的廣告手冊直接郵寄到有這種喜好的客戶手中,從而大大增加了商業機會.典型的分類演算法:決策樹演算法.神經網路

大數據時代的經營

維克托•邁爾•舍恩伯格所著的<大數據時代>是國外大數據研究的經典之作,維克托認為,大數據時代,人們處理數據的方式從抽樣分析,發展為對全體數據的分析.相應的,人們的思維模式也從原來的因果邏輯思維,逐漸演變成關聯思維. 在經驗時代,當所有人都在盲人摸象的時候,企業之間比拼的是決策者的頭腦和思維.當進入大數據時代,僅僅有思維和頭腦已經不夠了,因為有人已經站在大數據頂端,全面地看到了整頭大象,只知道埋頭工作不知道抬頭看方向的企業,是要被淘汰的.今天企業做經營決策不能再依靠經驗模式,而是要用大數據分析的

數據用戶需要什麼數據?

這裡首先需要說明的是標題中的「用戶」指的是數據的用戶,或者數據的需求方,這些用戶往往不是網站或企業面向的外部用戶,數據的消費者通常是公司內部各個部門和領域的人員.為什麼會提出這個問題,其實我們經常會遇到這樣的情況:公司的高層抱怨從報表裡面看不到有用的東西,是不是可以對報表做下整理(於是下面就忙開了),但是該怎麼整理或者他們到底需要的是什麼數據(好吧,高層的需求一般是不會明說的,我們要試著自己去揣摩):同時各個部門也在不斷地提各類數據需求,往往他們的需求就比較明確,有時可能會細得嚇人,需要每個用戶

深入淺出談數據挖掘

本文對數據挖掘概念的產生,數據挖掘與常規數據分析的主要區別,所能解決的幾大類問題和所應用的領域都有著非常清晰的論述.作者在此篇文章中認為數據挖掘最重要的要素是分析人員的相關業務知識和思維模式.豐富的業務知識是設計有效的相關變數的必要條件,而分析人員的思維模式從另外一個方面也保障了設計變數的結構化和完整性.所以我們在掌握豐富的業務知識同時,如果能夠按照正確的思維模式去思考問題,將會發現解決問題並不是很困難的.一. 數據挖掘的本質一般來說,比較狹義的觀點認為數據挖掘區別於常規數據分析的關鍵點在於:數

大數據時代浪潮的「弄潮兒」

進入2015年,海量的數據正在迅速膨脹並變大,它決定著企業的未來發展,雖然現在企業可能並沒有意識到數據爆炸性增長帶來的問題的隱患,但是隨著時間的推移,人們將越來越多的意識到數據對企業的重要性. 面臨海量數據的挑戰 大數據(big data)是時下非常熱門的話題,大數據是用來描述和定義信息爆炸時代產生的海量數據.大數據的發展能夠為人們獲得更為深刻.全面的洞察能力提供前所未有的空間與潛力,那麼如何看待大數據給IT市場帶來的機遇和挑戰呢? 紐約時報網站此前刊載文章稱,大數據時代已經來臨並且正在對每個領