Entity Framework - 使用Code First模式 Ver 5.0

30 May 2013 — Written by Sky Chang
#ASP.NET MVC#Entity Framework#SQL Server

還記得大概一年多前,EF 4.1的時候,小弟我有非常簡單的介紹過Code First,然後就沒消沒息了XDD,其實後續還是有一兩個case有稍微用過這個東西,但是當時用,也不算是真正的Code First,而是偽Code First ( 因為還是先建立DB Table,再利用工具去產生Class… ),而中間,也不斷被真正愛用Code First的人,給問倒問題XDD。

當然,無論是官方的推崇,與國外的論壇,小弟也知道Code First的好處,但沒全力投入,還是無法深深的感覺到;其次,通常都是一人專案,要如何帶到整個Team協同,也是一個問題…特別是DBA反彈的聲音最大…( 還好現在Team裡面的dba很好講話XDD 是個好人~~ );而最近,剛好有機會,就強迫教育了Team member,正式把Code First帶到Team裡面,而Team member裡面使用過的人,都說讚!!( 好險- -||| )

經過一年,EF也已經5.0版本,甚至已經在跑6.0的阿發版本了,官方的各大專案,也使用Code First當作基礎,所以,小弟一年過後,又回來重寫一下之前的文章啦XDDD

What’s Code First

不知道大家是怎樣開始專案的呢?我相信,最常聽到的應該是,看使用者的需求,然後來規劃資料庫,畫出ER圖,然後就開始努力地下去Coding了( 這裡就不討論怎樣軟體開發流程是好是壞了。 )。

接下來呢!?早期小弟在寫ASP的時候,會在裡面加上一堆SQL、邏輯、畫面,組合成義大利麵式的程式碼!( 可惜實際上不夠美味 ),後來使用ASP.NET的時候,也差不了多少,一樣在.cs的檔案裏面放上一堆SQL,只是那時候用Dataset,感覺上比較高級了,後來懂得把Table變成一個又一個的物件,至少有拆開了=w=,到現在,會使用Repository Patten來拆開資料存取層,也會利用EntityFramework來進行ORM,至少有進步了XDD。

但是無論怎樣的設計上,還是會先考慮資料庫模型,想好Table的關聯,畫好ER圖,建好DB後,在開始寫程式。

而這樣的作法,也不是說好或不好,畢竟,沒有不好的方法,只有用錯的地方=w=,但今天,EntityFramework帶來另外一種作法,也就是Code First。( 如果先建立DB,就稱為DB First,如果利用EF工具,先建立好模型,就稱為Model First。)

廢話了一堆,Code First,簡單的說,就是不先建立db,也不用EF的工具建立模型,而是直接利用建立好的類別產生DB!

有沒有很酷!,老實說我覺得酷斃了,尤其是像小弟那麼懶的人,每次想到還要建立Table,真的就懶了…還是寫Class比較親切!?…

建立Code First Demo

首先,我們這個case就用MVC來Demo吧 ( 但不會講到MVC喔 ),建立完MVC後,可以去NuGet檢查一下,是否有Entity Framework套件。

image

然後,假設我們要寫一個客戶的管理系統,那自然,就要先建立一個客戶的Class,我們新增一個Class,取名為ClientBasic。

接下來呢!?當然就是開始打ClientBasic的程式碼啦!,那db呢!?,別忘了我們現在是Code First,顧名思義,就是先打Code!!

我們建立一個ID,代表唯一的編號,和一個Name,就這麼簡單。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;

namespace TestMVC.Models
{
    public class Customer
    {
        public int ID { get; set; }
        public string Name { get; set; }

    }
}

然後,我們要建立另外一個程式碼,這個程式碼主要繼承於DbContext,簡單的說,就像是個資料庫一樣的感覺,而另外要注意的是,我們也要有個建構子,並且傳入字串"name=TestContext",這個字串的意思,是代表,我們App.config( 如果是網頁,則是Web.config ),裡面會有TestContext的連線字串;接下來,我們會設定一個屬性為ClientBasics( 這裡通常會用複數 ),而這個屬性是DbSet型別,而這個屬性,感覺就像是Table一樣。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Entity;

namespace MigrationsCodeDemo
{
    public class IMSContext : DbContext
    {
        public TestContext()
            : base("name=TestContext")
        {

        }
        public DbSet<clientbasic> ClientBasics { get; set; }
    }
}

接下來,我們看一下App.config( 或是Web.config ),我們需要一個名稱為TestContext的連線字串,這邊我們使用LocalDB,如果想要連線到SQL Server 2012,就直接給SQL Server 2012的連線字串。

  <connectionStrings>
     <add name="TestContext" providerName="System.Data.SqlClient" 
         connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=TestContext;
         Integrated Security=SSPI;
         AttachDBFilename=|DataDirectory|\TestContext.mdf" />
  </connectionStrings>

接下來,我們去修改一下HomeController,在Index的這個Action下,把剛剛打好的TestContext物件給new起來( 變數稱為db ),而這裡面會有許多方法,用來處理所有和資料庫有關的行為,這邊我們new了一個新的Customer物件,並且加入到TestContext裡面( 可以想像成,加上一筆資料),而裡面有屬性Name( 可以想像成欄位Name ),值為Sky,最後利用SaveChanges方法,就會將資料寫回到資料庫。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using TestMVC.Models;

namespace TestMVC.Controllers
{
    public class HomeController : Controller
    {

        // GET: /Home/
        public ActionResult Index()
        {
            var db = new TestContext();
            //新增一筆資料
            var cust = new Customer();
            cust.Name = "Sky";
            db.Customers.Add(cust);
            db.SaveChanges();
            return View();
        }
    }
}

然後,我們把執行看看。( 當然,View要自己建立阿~@@~ )

當我們去看資料庫,就會發現,他自動地幫我們建立了資料庫和Table!!,神奇吧!!就如前面所說的,我們可以完全不用考慮db該如何建,而會專心思考物件要怎麼寫!!

另外,這邊要特別補充,並不是把TestContext給new出來,db就會自動建立,而是會在真正新增刪除修改查詢db的時候,才會觸發建立db的動作…此外,也別忘記,Linq有延遲載入的功能,所以上面範例,才會使用add當作範例。

image

如果去查資料,可以查到一筆

image

後記

小弟這個範例,就是很簡單的先去建立類別,然後資料庫就自動幫忙建立起來了,但是聰明的你應該已經注意到了,那如果Class的屬性增加後,資料庫會不會自動變更!?答案已經很清楚了,在EF他會丟出例外給你看XDD,早期遇到問題,必須先刪除掉資料庫,才能重新Run一次,但現在,EF已經提出新的機制了( 其實一年前就提出了 ) 有興趣的可以參考這篇來解決此問題。

參考資料

  • [http://msdn.microsoft.com/zh-tw/data/ee712907](http://msdn.microsoft.com/zh-tw/data/ee712907 "http://msdn.microsoft.com/zh-tw/data/ee712907")
  • Sky & Study4.TW