使用EntityFramework 6 Code First與既有資料庫建立應用程式

by vivid 27. 八月 2014 06:42

.NET Magazine國際中文電子雜誌
者:許薰尹
稿:張智凱
文章編號:N140815102
出刊日期:2014/8/27
開發工具:Visual Studio 2013 Ultimate Update 2Entity Framework Power Tools Beta 4
版本:.NET Framework 4.5.x + ASP.NET MVC 5.x

在《使用Entity Framework 6 Code First與新資料庫建立應用程式》這篇文章之中,我們探討了Entity Framework Code First的設計,使用新資料庫,利用模型來自動建立資料庫的結構描述資訊。這一篇文章之中,則探討Code First 設計的第二種方式,如何從現有的SQL Server Pubs範例資料庫來建立ADO.NET 實體資料模型,以便整合至ASP.NET MVC 5網站應用程式。

使用Entity Framework Power Tools

使用Entity Framework Code First方式設計資料存取程式時,因為Model在記憶體,不需建立實際的EDMX檔案,所以在開發過程之中,看不到Model的長像,在本文的範例中利用Entity Framework Power Tools來檢視模型。你需要先安裝Entity Framework Power Tools,在Visual Studio 2013 –「 Tools」 –「 Extensions and Updates」,下載「Entity Framework Power Tools」,安裝完成要重開Visual Studio 2013工具:

clip_image002

圖 1:安裝Entity Framework Power Tools。

建立ASP.NET MVC 5應用程式專案

我們從建立一個ASP.NET MVC 5應用程式開始。啟動Visual Studio 2013開發環境。從「File」-「New」-「Project」,在「New Project」對話盒中,設定上方的清單的.NET Framework版本為「.NET Framework 4.5.1」;選取左方「Installed」清單-「Templates」-「Visual C#」程式語言,從「Web」分類中,選取「ASP.NET Web Application」。設定專案名稱為「CFExistingDB」。設定專案存放路徑,然後按下「OK」鍵,請參考下圖所示:

clip_image004

圖 2:建立一個ASP.NET MVC 5應用程式。

在「New ASP.NET Project」對話盒中選取「Empty」,勾選下方的「MVC」,然後按下「OK」按鈕建立專案,請參考下圖所示:

clip_image006

圖 3:建立空白MVC專案。

安裝Entity Framework套件

空白網站專案預設沒有安裝Entity Framework套件。我們可以從Visual Studio 2013開發工具-「Solution Explorer」- 專案 - 「Manage NuGet Packages」選項,開啟「Manage NuGet Packages」對話盒,選取左方「Online」清單項目, 在右上方文字方塊中輸入「Entity Framework」關鍵字,搜尋「Entity Framework」,按下「Install」按鈕做安裝。(注意,Entity Framework的版本要6.1以上版本),請參考下圖所示:

clip_image008

圖 4:安裝Entity Framework套件。

若使用Nuget套件管理員下載「Entity Framework」函式庫時,無法找到想使用的Entity Framework版本,你可以直接在Visual Studio工具中下指令下載,並指明想使用的版本。步驟為:在「Solution Explorer」視窗選取專案名稱。從Visual Studio 2013開發工具「TOOLS」-「Library Package Manager」-「Package Manage Console」開啟「Package Manage Console」視窗,然後在提示字元中輸入install-package指令,並使用「-version」指定安裝Entity Framework 6.1.1版本:

Install-Package EntityFramework -Version 6.1.1

 

使用反向工程建立ADO.NET實體資料模型

下一步是使用反向工程的功能來定義模型,我們想要從SQL Server的Pubs範例資料庫來建立模型。在MVC的專案之中,通常將ADO.NET實體資料模型的相關程式置於Models資料夾之中。

從Visual Studio 2013開發工具-「Solution Explorer」- 專案-「Models」目錄上方按滑鼠右鍵,從快捷選單選擇「Add」- 「New Item」,開啟「Add New Item」對話盒,從右上方文字方塊輸入「ado.net」搜尋,選取「ADO.NET Entity Data Model」,設定名稱為「PubsContext」,然後選取「Code First from database」,按下「Next」按鈕,請參考下圖所示:

clip_image010

圖 5:建立ADO.NET實體資料模型。

建立ADO.NET實體資料模型,在下一個畫面,選取「New Connection」建立資料庫連接,請參考下圖所示:

clip_image012

圖 6:建立資料庫連接。

在「Connection Properties」視窗中,設以下屬性:

  • l 資料來源 (Data Source) :Microsoft SQL Server (SQLClient)。
  • l Server name欄位:輸入「.\SQLExpress」。
  • l Log on to server:選取「Use Windows Authentication」。
  • l Select or enter a database name欄位:選擇「Pubs」資料庫。

目前畫面應如下圖所示,完成後按下「OK」按鈕:

clip_image014

圖 7:建立資料庫連接。

接著會回到設定連結的畫面,請參考下圖所示:

clip_image016

圖 8:設定連結畫面。

按「Next」按鈕進入到下一個畫面,以選取資料庫物件,請參考下圖所示:

clip_image018

圖 9:選取資料庫物件。

當精靈完成之後,專案中Models資料夾內將產生兩個檔案:PubsContext.cs與store.cs檔案。其中store.cs檔案定義store類別如下:

namespace CFExistingDB.Models
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using System.ComponentModel.DataAnnotations.Schema;
    using System.Data.Entity.Spatial;

    public partial class store
    {
        [Key]
        [StringLength(4)]
        public string stor_id { get; set; }

        [StringLength(40)]
        public string stor_name { get; set; }

        [StringLength(40)]
        public string stor_address { get; set; }

        [StringLength(20)]
        public string city { get; set; }

        [StringLength(2)]
        public string state { get; set; }

        [StringLength(5)]
        public string zip { get; set; }
    }
}

 

Code First使用.NET類別(Visual Basic或C#)來定義模型。預設.NET Framework會根據命名慣例來建立資料庫的結構描述資訊。例如模型中類別的屬性若命名為「id」或「型別名稱+Id」(ID不區分大小寫,可以是任意大小寫組合),則此屬性將來會用來建立資料庫資料表的主索引鍵(Primary Key)。

根據Pubs資料庫Stores資料表的結構描述資訊,store類別的屬性在產生時,會適當的套用Data Annotation Attribute,例如stor_id上方加註 [key] attribute表示對應到資料表主索引鍵(Primary Key),而zip屬性加註StringLength為5,設定郵遞區號長度為五。

PubsContext.cs檔案內PubsContext類別程式如下,其中將包含一個型別為DbSet<store>的stores屬性:

namespace CFExistingDB.Models {
  using System;
  using System.Data.Entity;
  using System.ComponentModel.DataAnnotations.Schema;
  using System.Linq;

  public partial class PubsContext : DbContext {
    public PubsContext( )
      : base( "name=PubsContext" ) {
    }

    public virtual DbSet<store> stores { get; set; }

    protected override void OnModelCreating( DbModelBuilder modelBuilder ) {
      modelBuilder.Entity<store>( )
          .Property( e => e.stor_id )
          .IsFixedLength( )
          .IsUnicode( false );

      modelBuilder.Entity<store>( )
          .Property( e => e.stor_name )
          .IsUnicode( false );

      modelBuilder.Entity<store>( )
          .Property( e => e.stor_address )
          .IsUnicode( false );

      modelBuilder.Entity<store>( )
          .Property( e => e.city )
          .IsUnicode( false );

      modelBuilder.Entity<store>( )
          .Property( e => e.state )
          .IsFixedLength( )
          .IsUnicode( false );

      modelBuilder.Entity<store>( )
          .Property( e => e.zip )
          .IsFixedLength( )
          .IsUnicode( false );
    }
  }
}

 

PubsContext 類別中改寫了DbContext類別的OnModelCreating 方法,使用Entity Framework Fluent API來設定資料庫資料表與模型類別之間的對應。例如叫用IsUnicode方法來設定支援Unicode字元;

當精靈完成之後,專案中Web.config檔案內則包含連接字串定義:

<connectionStrings>

<add name="PubsContext" connectionString="data source=.\sqlexpress;initial catalog=Pubs;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" />

</connectionStrings>

最後先選取Visual Studio 2013工具「Build」-「Build Solution」建置專案,確保所有程式都自動產生並且存檔。

 

使用Entity Framework Power Tools檢視ADO.NET實體資料模型

若Visual Studio 2013開發工具安裝了Entity Framework Power Tools,可利用此工具以視覺化的方式來檢視專案中建立的ADO.NET實體資料模型。例如在Models資料夾PubsContext.cs檔案上方,按滑鼠右鍵,從快捷選單選擇「Entity Framework」- 「View Entity Data Model」項目,開啟模型,請參考下圖所示:

clip_image020

圖 10:使用Entity Framework Power Tools檢視ADO.NET實體資料模型。

執行結果,請參考下圖所示:

clip_image022

圖 11:檢視ADO.NET實體資料模型。

你也可以選擇檢視ADO.NET實體資料模型原始的XML檔案,同樣在Visual Studio 2013專案Models資料夾PubsContext.cs檔案上方,按滑鼠右鍵,從快捷選單選擇「Entity Framework」- 「View Entity Data Model XML」項目,開啟ADO.NET實體資料模型,XML檔案內容參考以下列表:

<?xml version="1.0" encoding="utf-8"?>
<Edmx Version="3.0" xmlns="http://schemas.microsoft.com/ado/2009/11/edmx">
  <Runtime>
    <ConceptualModels>
      <Schema Namespace="CFExistingDB.Models" Alias="Self" annotation:UseStrongSpatialTypes="false" xmlns:annotation="http://schemas.microsoft.com/ado/2009/02/edm/annotation" xmlns:customannotation="http://schemas.microsoft.com/ado/2013/11/edm/customannotation" xmlns="http://schemas.microsoft.com/ado/2009/11/edm">
        <EntityType Name="store" customannotation:ClrType="CFExistingDB.Models.store, CFExistingDB, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
          <Key>
            <PropertyRef Name="stor_id" />
          </Key>
          <Property Name="stor_id" Type="String" MaxLength="4" FixedLength="true" Unicode="false" Nullable="false" />
          <Property Name="stor_name" Type="String" MaxLength="40" FixedLength="false" Unicode="false" />
          <Property Name="stor_address" Type="String" MaxLength="40" FixedLength="false" Unicode="false" />
          <Property Name="city" Type="String" MaxLength="20" FixedLength="false" Unicode="false" />
          <Property Name="state" Type="String" MaxLength="2" FixedLength="true" Unicode="false" />
          <Property Name="zip" Type="String" MaxLength="5" FixedLength="true" Unicode="false" />
        </EntityType>
        <EntityContainer Name="PubsContext" customannotation:UseClrTypes="true">
          <EntitySet Name="stores" EntityType="Self.store" />
        </EntityContainer>
      </Schema>
    </ConceptualModels>
    <Mappings>
      <Mapping Space="C-S" xmlns="http://schemas.microsoft.com/ado/2009/11/mapping/cs">
        <EntityContainerMapping StorageEntityContainer="CodeFirstDatabase" CdmEntityContainer="PubsContext">
          <EntitySetMapping Name="stores">
            <EntityTypeMapping TypeName="CFExistingDB.Models.store">
              <MappingFragment StoreEntitySet="store">
                <ScalarProperty Name="stor_id" ColumnName="stor_id" />
                <ScalarProperty Name="stor_name" ColumnName="stor_name" />
                <ScalarProperty Name="stor_address" ColumnName="stor_address" />
                <ScalarProperty Name="city" ColumnName="city" />
                <ScalarProperty Name="state" ColumnName="state" />
                <ScalarProperty Name="zip" ColumnName="zip" />
              </MappingFragment>
            </EntityTypeMapping>
          </EntitySetMapping>
        </EntityContainerMapping>
      </Mapping>
    </Mappings>
    <StorageModels>
      <Schema Namespace="CodeFirstDatabaseSchema" Provider="System.Data.SqlClient" ProviderManifestToken="2012" Alias="Self" xmlns:customannotation="http://schemas.microsoft.com/ado/2013/11/edm/customannotation" xmlns="http://schemas.microsoft.com/ado/2009/11/edm/ssdl">
        <EntityType Name="store">
          <Key>
            <PropertyRef Name="stor_id" />
          </Key>
          <Property Name="stor_id" Type="char" MaxLength="4" Nullable="false" />
          <Property Name="stor_name" Type="varchar" MaxLength="40" Nullable="true" />
          <Property Name="stor_address" Type="varchar" MaxLength="40" Nullable="true" />
          <Property Name="city" Type="varchar" MaxLength="20" Nullable="true" />
          <Property Name="state" Type="char" MaxLength="2" Nullable="true" />
          <Property Name="zip" Type="char" MaxLength="5" Nullable="true" />
        </EntityType>
        <EntityContainer Name="CodeFirstDatabase">
          <EntitySet Name="store" EntityType="Self.store" Schema="dbo" Table="stores" />
        </EntityContainer>
      </Schema>
    </StorageModels>
  </Runtime>
  <Designer>
    <Connection>
      <DesignerInfoPropertySet>
        <DesignerProperty Name="MetadataArtifactProcessing" Value="EmbedInOutputAssembly" />
      </DesignerInfoPropertySet>
    </Connection>
    <Options>
      <DesignerInfoPropertySet>
        <DesignerProperty Name="ValidateOnBuild" Value="False" />
        <DesignerProperty Name="CodeGenerationStrategy" Value="None" />
        <DesignerProperty Name="ProcessDependentTemplatesOnSave" Value="False" />
        <DesignerProperty Name="UseLegacyProvider" Value="False" />
      </DesignerInfoPropertySet>
    </Options>
    <Diagrams />
  </Designer>
</Edmx>

你也可以利用Entity Framework Power Tool來檢視DDL,同樣在Visual Studio 2013專案Models資料夾PubsContext.cs檔案上方,按滑鼠右鍵,從快捷選單選擇「Entity Framework」- 「View Entity Data Model DDL SQL」項目,檔案內容參考以下列表:

 

create table [dbo].[stores] (
    [stor_id] [char](4) not null,
    [stor_name] [varchar](40) null,
    [stor_address] [varchar](40) null,
    [city] [varchar](20) null,
    [state] [char](2) null,
    [zip] [char](5) null,
    primary key ([stor_id])
);

 

新增控制器

下一步我們來透過Visual Studio 2013的「Add Scaffold」功能來建立控制器,以及展現資料的檢視(View)。在「Solution Explorer」視窗,專案的「Controllers」資料夾上方,按滑鼠右鍵,選取「Add」-「Controller」,此時會開啟「Add Scaffold」視窗,選取「MVC 5 Controller with views, using Entity Framework」,然後按下「Add」按鈕,請參考下圖所示:

clip_image024

圖 12:使用「Add Scaffold」功能新增控制器。

在「Add Controller」視窗設定以下資料:

  • · Model Class :「store (CFExistingDB.Models)」。
  • · Data context class:「PubsContext (CFExistingDB.Models)」。
  • · 勾選中間的「Generate views」,清除勾選其它核取方塊
  • · Controller Name:「StoreController」。

完成的結果,請參考下圖所示:

clip_image026

圖 13:新增控制器。

Visual Studio 2013會自動在專案中「Views\ Store」資料夾下,產生Index.cshtml、Edit.cshtml、Details.cshtml、Delete.cshtml與Create.cshtml檔案,以及顯示資料的程式碼。以下則是Controller的程式碼列表:

namespace CFExistingDB.Controllers
{
    public class StoreController : Controller
    {
        private PubsContext db = new PubsContext();

        // GET: Store
        public ActionResult Index()
        {
            return View(db.stores.ToList());
        }

        // GET: Store/Details/5
        public ActionResult Details(string id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            store store = db.stores.Find(id);
            if (store == null)
            {
                return HttpNotFound();
            }
            return View(store);
        }

        // GET: Store/Create
        public ActionResult Create()
        {
            return View();
        }

        // POST: Store/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 = "stor_id,stor_name,stor_address,city,state,zip")] store store)
        {
            if (ModelState.IsValid)
            {
                db.stores.Add(store);
                db.SaveChanges();
                return RedirectToAction("Index");
            }

            return View(store);
        }

        // GET: Store/Edit/5
        public ActionResult Edit(string id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            store store = db.stores.Find(id);
            if (store == null)
            {
                return HttpNotFound();
            }
            return View(store);
        }

        // POST: Store/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 = "stor_id,stor_name,stor_address,city,state,zip")] store store)
        {
            if (ModelState.IsValid)
            {
                db.Entry(store).State = EntityState.Modified;
                db.SaveChanges();
                return RedirectToAction("Index");
            }
            return View(store);
        }

        // GET: Store/Delete/5
        public ActionResult Delete(string id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            store store = db.stores.Find(id);
            if (store == null)
            {
                return HttpNotFound();
            }
            return View(store);
        }

        // POST: Store/Delete/5
        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public ActionResult DeleteConfirmed(string id)
        {
            store store = db.stores.Find(id);
            db.stores.Remove(store);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                db.Dispose();
            }
            base.Dispose(disposing);
        }
    }

 

以下則是自動產生在Views\Store資料夾中Index.cshtml檔案的程式碼列表:

@model IEnumerable<CFExistingDB.Models.store>

@{
  Layout = null;
}

<!DOCTYPE html>

<html>
<head>
  <meta name="viewport" content="width=device-width" />
  <title>Index</title>
</head>
<body>
  <p>
    @Html.ActionLink( "Create New" , "Create" )
  </p>
  <table class="table">
    <tr>
      <th>
        @Html.DisplayNameFor( model => model.stor_name )
      </th>
      <th>
        @Html.DisplayNameFor( model => model.stor_address )
      </th>
      <th>
        @Html.DisplayNameFor( model => model.city )
      </th>
      <th>
        @Html.DisplayNameFor( model => model.state )
      </th>
      <th>
        @Html.DisplayNameFor( model => model.zip )
      </th>
      <th></th>
    </tr>

    @foreach ( var item in Model ) {
      <tr>
        <td>
          @Html.DisplayFor( modelItem => item.stor_name )
        </td>
        <td>
          @Html.DisplayFor( modelItem => item.stor_address )
        </td>
        <td>
          @Html.DisplayFor( modelItem => item.city )
        </td>
        <td>
          @Html.DisplayFor( modelItem => item.state )
        </td>
        <td>
          @Html.DisplayFor( modelItem => item.zip )
        </td>
        <td>
          @Html.ActionLink( "Edit" , "Edit" , new { id = item.stor_id } ) |
          @Html.ActionLink( "Details" , "Details" , new { id = item.stor_id } ) |
          @Html.ActionLink( "Delete" , "Delete" , new { id = item.stor_id } )
        </td>
      </tr>
    }

  </table>
</body>
</html>


最後測試一下首頁,從「Solution Explorer」視窗- 選取Views\Opera資料夾下的Index.cshtml檔案,按CTRL+F5執行Index 檢視,執行結果參考如下,資料表所有內容表列在網頁之中:

clip_image028

圖 14:測試首頁,資料列表。

啟用資料移轉功能

當你的應用程式在繼續開發的過程中,資料庫的結構描述資訊可能會需要修改,此時你可以使用Entity Framework 的Code First Migration功能來因應異動的部分。Code First Migration可以記住你資料庫結構描述異動過程中的各個版本。

先在專案啟用資料移轉功能,從Visual Studio 2013開發工具「TOOLS」-「Library Package Manager」-「Package Manage Console」開啟「Package Manage Console」視窗,然後在提示字元中輸入enable-migrations,啟用Entity Framework資料庫移轉功能:

enable-migrations

此命令的執行結果,請參考下圖所示:

clip_image030

圖 15:啟用資料移轉功能。

接著Visual Studio 2013工具會自動在專案中產生一個「Migrations」資料夾,其中包含一個Configuration.cs檔案。程式碼如下:

namespace CFExistingDB.Migrations {
  using System;
  using System.Data.Entity;
  using System.Data.Entity.Migrations;
  using System.Linq;

  internal sealed class Configuration : DbMigrationsConfiguration<CFExistingDB.Models.PubsContext> {
    public Configuration( ) {
      AutomaticMigrationsEnabled = false;
    }

    protected override void Seed( CFExistingDB.Models.PubsContext context ) {
      //  This method will be called after migrating to the latest version.

      //  You can use the DbSet<T>.AddOrUpdate() helper extension method
      //  to avoid creating duplicate seed data. E.g.
      //
      //    context.People.AddOrUpdate(
      //      p => p.FullName,
      //      new Person { FullName = "Andrew Peters" },
      //      new Person { FullName = "Brice Lambson" },
      //      new Person { FullName = "Rowan Miller" }
      //    );
      //
    }
  }
}

 

建立初始遷移版本

由於Pubs資料庫Store資料表已經存在於SQL Server資料庫,我們可以將現有的資料庫結構描述資訊,當做是資料遷移動作的第一個版本,簡單的說就是建立現有資料庫的快照,首先從Visual Studio 2013開發工具「TOOLS」-「Library Package Manager」-「Package Manage Console」開啟「Package Manage Console」視窗,然後在提示字元中輸入以下指令,叫用Add-Migration,建立一個名為InitialCreate的快照,設定IgnoreChanges參數表示目地資料庫結構描述資訊與現在的模型相容:

Add-Migration InitialCreate –IgnoreChanges

此命令的執行結果,請參考下圖所示:

clip_image032

圖 16:建立初始遷移版本。

Visual Studio 2013開發工具將會在專案中Migrations資料夾內,建立一個空白的InitialCreate類別:

namespace CFExistingDB.Migrations {
  using System;
  using System.Data.Entity.Migrations;

  public partial class InitialCreate : DbMigration {
    public override void Up( ) {
    }

    public override void Down( ) {
    }
  }
}


接著在「Package Manage Console」視窗提示字元中,輸入以下指令:

Update-Database

此動作將套用InitialCreate到資料庫,請參考下圖所示:

clip_image034

圖 17:套用InitialCreate到資料庫。

使用Visual Studio 2013 「Server Explorer」視窗來檢視資料庫,資料庫中將會自動建立一個__MigrationHistory資料表,並新增一筆資料,請參考下圖所示:

clip_image036

圖 18:__MigrationHistory資料表。

修改模型

namespace CFExistingDB.Models {
  using System;
  using System.Collections.Generic;
  using System.ComponentModel.DataAnnotations;
  using System.ComponentModel.DataAnnotations.Schema;
  using System.Data.Entity.Spatial;

  public partial class store {
    [Key]
    [StringLength( 4 )]
    public string stor_id { get; set; }

    [StringLength( 40 )]
    public string stor_name { get; set; }

    [StringLength( 40 )]
    public string stor_address { get; set; }

    [StringLength( 20 )]
    public string city { get; set; }

    [StringLength( 2 )]
    public string state { get; set; }

    [StringLength( 5 )]
    public string zip { get; set; }

   [StringLength( 40 )]
    public string note { get; set; }
  }
}

現在我們來修改模型,為store類別加上一個string型別的note屬性:

 

除了變更模型之外,我們還需要修改資料庫結構描述資訊,以反應模型的變更。從Visual Studio 2013開發工具「TOOLS」-「Library Package Manager」-「Package Manage Console」開啟「Package Manage Console」視窗,然後在提示字元中輸入Add-Migration,將名稱設定為「AddNote」:

Add-Migration AddNote

Add-Migration指令會檢查從上次建立資料移轉到目前為止,模型異動的資訊。執行結果,請參考下圖所示:

clip_image038

圖 19:Add-Migration。

接著Visual Studio 2013工具會自動在專案中「Migrations」資料夾,新增一個XXXX_AddNote.cs

檔案。程式碼如下,Up方法升級時叫用,描述新增一個note欄位;Down方法降級時呼叫,表示將新增的欄位移除:

namespace CFExistingDB.Migrations {
  using System;
  using System.Data.Entity.Migrations;

  public partial class AddNote : DbMigration {
    public override void Up( ) {
      AddColumn( "dbo.stores" , "note" , c => c.String( maxLength: 40 ) );
    }

    public override void Down( ) {
      DropColumn( "dbo.stores" , "note" );
    }
  }
}


在「Package Manage Console」視窗提示字元中輸入指令,套用異動,新增欄位到資料庫:

Update-Database

執行結果,請參考下圖所示:

clip_image040

圖 20:新增欄位到資料庫。

此時使用Visual Studio 2013 「Server Explorer」視窗來檢視資料庫,資料庫中__MigrationHistory資料表,將新增一筆資料,請參考下圖所示:

clip_image042

圖 21:新增遷移記錄到資料庫。

還原回初始遷移版本

未來你可以視需求將資料庫結構描述還原回初始遷移版本,或指定的版本,例如在「Package Manage Console」視窗提示字元中輸入指令,設定TargetMigration,指定回到InitialCreate版本。Verbose參數則可要求將執行的SQL陳述句印出:

Update-Database -TargetMigration:InitialCreate –Verbose

執行結果,請參考下圖所示:

clip_image044

圖 22:還原回初始遷移版本。

執行的SQL如下:

Using StartUp project 'CFExistingDB'.

Using NuGet project 'CFExistingDB'.

Specify the '-Verbose' flag to view the SQL statements being applied to the target database.

Target database is: 'Pubs' (DataSource: .\sqlexpress, Provider: System.Data.SqlClient, Origin: Configuration).

Reverting migrations: [201407210951376_AddNote].

Reverting explicit migration: 201407210951376_AddNote.

DECLARE @var0 nvarchar(128)

SELECT @var0 = name

FROM sys.default_constraints

WHERE parent_object_id = object_id(N'dbo.stores')

AND col_name(parent_object_id, parent_column_id) = 'note';

IF @var0 IS NOT NULL

EXECUTE('ALTER TABLE [dbo].[stores] DROP CONSTRAINT [' + @var0 + ']')

ALTER TABLE [dbo].[stores] DROP COLUMN [note]

DELETE [dbo].[__MigrationHistory]

WHERE (([MigrationId] = N'201407210951376_AddNote') AND ([ContextKey] = N'CFExistingDB.Migrations.Configuration'))

此時使用Visual Studio 2013 「Server Explorer」視窗來檢視資料庫,資料庫中__MigrationHistory資料表,將移除一筆資料,只留下InitialCreate,請參考下圖所示:

clip_image046

圖 23:__MigrationHistory資料表。

還原回指定的AddNote版本

如有需求,可隨時還原回指定的AddNote版本,只要在「Package Manage Console」視窗提示字元中輸入指令,設定TargetMigration,指定回到AddNote版本。

Update-Database -TargetMigration:AddNote -Verbose

執行結果,請參考下圖所示:

clip_image048

圖 24:還原回指定的版本。

執行的SQL如下:

Using StartUp project 'CFExistingDB'.

Using NuGet project 'CFExistingDB'.

Specify the '-Verbose' flag to view the SQL statements being applied to the target database.

Target database is: 'Pubs' (DataSource: .\sqlexpress, Provider: System.Data.SqlClient, Origin: Configuration).

Applying explicit migrations: [201407210951376_AddNote].

Applying explicit migration: 201407210951376_AddNote.

ALTER TABLE [dbo].[stores] ADD [note] [nvarchar](40)

INSERT [dbo].[__MigrationHistory]([MigrationId], [ContextKey], [Model], [ProductVersion])

VALUES (N'201407210951376_AddNote', N'CFExistingDB.Migrations.Configuration',

略…

, N'6.1.1-30610')

Running Seed method.

 

此時使用Visual Studio 2013 「Server Explorer」視窗來檢視資料庫,資料庫中__MigrationHistory資料表內容如下:

clip_image050

圖 25:還原回指定的AddNote版本。

Tags:

.NET Magazine國際中文電子雜誌 | ASP.NET MVC | Entity Framework | 許薰尹Vivid Hsu

評論 (53) -

cours de theatre paris
cours de theatre paris United States
2017/9/30 下午 04:48:48 #

Muchos Gracias for your post.Much thanks again. Really Great.

回覆

can ho vung tau
can ho vung tau United States
2017/10/7 上午 01:18:27 #

Thank you ever so for you blog post.Really thank you! Keep writing.

回覆

Osimi seaview
Osimi seaview United States
2017/10/9 下午 07:06:17 #

Thanks for the article. Really Great.

回覆

buy hacklink
buy hacklink United States
2017/10/12 下午 09:45:17 #

Muchos Gracias for your blog post.Thanks Again. Really Cool.

回覆

visit homepage
visit homepage United States
2017/10/14 下午 05:01:11 #

A round of applause for your article.Really thank you! Great.

回覆

dragon city hack apk download
dragon city hack apk download United States
2017/10/15 下午 04:31:49 #

Really informative article post.Really thank you! Much obliged.

回覆

click resources
click resources United States
2017/10/17 下午 03:49:16 #

Thanks-a-mundo for the post.Really looking forward to read more. Awesome.

回覆

sletrokor
sletrokor United States
2017/10/17 下午 09:21:38 #

I really like and appreciate your blog post.Thanks Again. Will read on...

回覆

porn
porn United States
2017/10/19 上午 08:25:56 #

I loved your article post.Really thank you! Want more.

回覆

Get More Info
Get More Info United States
2017/10/19 下午 07:27:17 #

Very informative article.Much thanks again. Want more.

回覆

vung tau melody
vung tau melody United States
2017/10/21 上午 04:44:48 #

I value the article post.Much thanks again. Really Cool.

回覆

carte grise en ligne
carte grise en ligne United States
2017/10/21 上午 08:24:05 #

Really appreciate you sharing this blog.Thanks Again.

回覆

Osimi Sea View
Osimi Sea View United States
2017/10/28 下午 01:32:12 #

Im thankful for the blog post.Really looking forward to read more. Great.

回覆

life leadership
life leadership United States
2017/11/1 下午 12:42:47 #

Awesome blog.Thanks Again. Great.

回覆

phenocal
phenocal United States
2017/11/1 下午 08:18:09 #

Enjoyed every bit of your blog post.Really looking forward to read more. Fantastic.

回覆

phentaslim review
phentaslim review United States
2017/11/3 上午 10:39:30 #

A big thank you for your article.Really thank you! Awesome.

回覆

sciatica home remedies
sciatica home remedies United States
2017/11/15 上午 06:58:45 #

Great post.Thanks Again. Want more.

回覆

Wow, great article post.Much thanks again. Want more.

回覆

drupal change favicon
drupal change favicon United States
2017/11/22 上午 02:06:49 #

I really like and appreciate your post.Really looking forward to read more. Really Great.

回覆

bikinis
bikinis United States
2017/11/23 下午 09:00:01 #

Hey, thanks for the blog. Awesome.

回覆

Chad Boonswang and Jeffrey Goodman
Chad Boonswang and Jeffrey Goodman United States
2017/11/26 下午 05:09:24 #

Really informative post.Really thank you! Keep writing.

回覆

Chad Boonswang SEO
Chad Boonswang SEO United States
2017/11/26 下午 11:10:04 #

Hey, thanks for the post.Much thanks again. Much obliged.

回覆

cash for cars scammer
cash for cars scammer United States
2017/11/29 下午 03:34:47 #

I really liked your blog article.Really looking forward to read more. Much obliged.

回覆

Saigon Pentaview
Saigon Pentaview United States
2017/11/29 下午 10:08:52 #

Thanks again for the blog article.Much thanks again. Fantastic.

回覆

building business credit
building business credit United States
2017/12/1 上午 12:00:55 #

Thanks for the post.Really thank you! Awesome.

回覆

porno
porno United States
2017/12/1 下午 03:40:32 #

Really informative article post.Really looking forward to read more. Much obliged.

回覆

Initial coin offering
Initial coin offering United States
2017/12/3 上午 03:59:36 #

I really like and appreciate your blog article. Great.

回覆

moble porn
moble porn United States
2017/12/5 上午 08:45:58 #

I think this is a real great post.Thanks Again. Really Cool.

回覆

Im thankful for the blog.Really looking forward to read more. Really Great.

回覆

http://betabestauto.services/story/13422
http://betabestauto.services/story/13422 United States
2017/12/10 上午 08:00:28 #

Great article post.Much thanks again. Much obliged.

回覆

my blog
my blog United States
2017/12/10 下午 06:24:21 #

Wow, great post. Really Cool.

回覆

Merrilee Heywood
Merrilee Heywood United States
2017/12/14 上午 08:31:47 #

Major thankies for the blog article.Really looking forward to read more. Keep writing.

回覆

official source
official source United States
2017/12/14 下午 03:22:35 #

Really enjoyed this blog post.Really thank you! Will read on...

回覆

Christmas Songs
Christmas Songs United States
2017/12/14 下午 09:53:07 #

Great, thanks for sharing this article post. Cool.

回覆

canon driver software
canon driver software United States
2017/12/16 下午 05:05:29 #

I cannot thank you enough for the post.Really looking forward to read more. Keep writing.

回覆

This is one awesome article post.Much thanks again. Cool.

回覆

I truly appreciate this article post.Much thanks again. Cool.

回覆

Home Page
Home Page United States
2017/12/17 下午 11:48:44 #

Im thankful for the article post.Really thank you! Fantastic.

回覆

earn money from home
earn money from home United States
2017/12/20 下午 05:58:07 #

Really enjoyed this blog post. Will read on...

回覆

driver canon
driver canon United States
2017/12/23 上午 06:03:17 #

Really informative post. Much obliged.

回覆

Darwin Horan
Darwin Horan United States
2017/12/23 下午 04:31:45 #

I am so grateful for your post.Really thank you! Will read on...

回覆

driver hp
driver hp United States
2017/12/25 下午 06:04:55 #

I value the article post.Really looking forward to read more. Fantastic.

回覆

Looking forward to reading more. Great blog post. Want more.

回覆

SOCCER HIGHLIGHTS
SOCCER HIGHLIGHTS United States
2017/12/26 下午 05:11:10 #

This is one awesome blog post.Really thank you! Really Great.

回覆

drivers hp
drivers hp United States
2018/1/2 上午 05:40:37 #

Thanks again for the post.Really thank you! Keep writing.

回覆

his response
his response United States
2018/1/2 下午 01:37:38 #

Muchos Gracias for your article post. Keep writing.

回覆

Great post.Much thanks again. Much obliged.

回覆

Epson drivers
Epson drivers United States
2018/1/3 上午 04:56:24 #

Im grateful for the blog article.Thanks Again. Will read on...

回覆

online casino games real money usa
online casino games real money usa United States
2018/1/4 下午 03:28:17 #

Great blog. Want more.

回覆

FBA
FBA United States
2018/1/6 上午 09:07:56 #

Im obliged for the article. Awesome.

回覆

web hosting
web hosting United States
2018/1/10 下午 01:53:29 #

Really informative article.Thanks Again. Want more.

回覆

新增評論




  Country flag
biuquote
  • 評論
  • 線上預覽
Loading






NET Magazine國際中文電子雜誌

NET Magazine國際中文電子版雜誌,由恆逸資訊創立於2000,自發刊日起迄今已發行超過500篇.NET相關技術文章,擁有超過40000名註冊讀者群。NET Magazine國際中文電子版雜誌希望藉於電子雜誌與NET Developer達到共同學習與技術新知分享,歡迎每一位對.NET 技術有興趣的朋友們多多支持本雜誌,讓作者群們可以有持續性的動力繼續爬文。<請加入免費訂閱>

月分類Month List