寫在前面
以前逛園子的時候,很多大牛寫的一些東西,什么AOP、DDD之類的,看過之后一頭霧水,遠望大牛,回過頭看看自己,原來程序員的差距還可以這么大。每個程序員都有個大牛夢想,當然小菜我也是,只是還在開始的路上。
因為前幾天研究easyui,準備寫個mvc+ef+easyui的簡單示例,當然這對很多人來說很簡單,有段時間也研究過別人寫的,但這是小菜我第一次自己寫,勿噴。而且這周安排給自己的任務:設計模式第五篇-控制反轉(ioc),前段時間做些其他方面的事,設計模式也好久沒寫了,所以這周必須把它完成,想研究完ioc之后,試著再寫上面的簡單示例,把ioc融入到mvc中,想想應該有搞頭。
關于Code First,昨晚無意間看到一位園友翻譯的相關教程:http://www.cnblogs.com/qouoww/archive/2011/12/31/2309066.html,這邊小弟先謝過,前面幾篇還可以看下去,但是后面幾篇就有點不知所云了,學習是一方面,實踐是另一方面,做的過程中才能學到更多的東西,這邊也試著寫個關于Code First的小示例。
自己動手,豐衣足食。
新建項目
我使用的是vs2012,如果使用vs2010需要安裝NuGet。
Nuget是一個.NET平臺下的開源的項目,它是Visual Studio的擴展。在使用Visual Studio開發基于.NET Framework的應用時,Nuget能把在項目中添加、移除和更新引用的工作變得更加快捷方便。
新建-項目-Visual C#-windows-控制臺應用程序,命名為:CodeFirstDemo。
這邊需要注意的是:選擇.net framework的時候要4.0以上版本,要不然下面NuGet安裝EntityFramework擴展的時候會報創建項目版本底無法完成安裝的錯誤,.net framework改成4.0就可以了,但是換了一臺電腦3.5版本測試安裝又是好的,不知是個什么情況,反正.net framework版本最好選擇4.0以上。
安裝EntityFramework程序包
新建好CodeFirstDemo項目后,我們先來安裝EntityFramework,項目-管理NuGet程序包-聯機-搜索“EntityFramework”,下載安裝。
安裝完成后會在項目下自動添加EntityFramework引用:
在Program.cs代碼文件中添加下面命名空間:
1 using System.Data.Entity;
創建模型
Code First顧名思義就是代碼先行的意思,除了Code First,還有Model First、DatabaseFirst,關于他們幾個的區別:http://blog.bossma.cn/csharp/when-is-code-first-not-code-first/。
下面我們在Program.cs中創建幾個模型,平常我們可以分離出來。
1 public class New 2 { 3 public int NewId { get; set; } 4 public string Title { get; set; } 5 6 public int NewTypeId { get; set; } 7 public virtual NewType NewType { get; set; } 8 } 9 10 public class NewType 11 { 12 public int NewTypeId { get; set; } 13 public string Name { get; set; } 14 15 public int BlogId { get; set; } 16 public virtual List<New> New { get; set; } 17 }
NewId和NewTypeId在創建的時候會做為表的主鍵,因為包含有ID關鍵字,如果不包含的話,需要我們指定主鍵,要不然創建就會報未找到主鍵的錯誤,添加命名空間:
1 using System.ComponentModel.DataAnnotations;
并在屬性前添加[Key]標注,指示此字段作為主鍵,例如:
1 [Key] 2 public string UserName { get; set; }
當然除了Key,System.ComponentModel.DataAnnotations命名空間下還有其他的Attribute,這邊就不多說,可以查看msdn有關教程:http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.aspx。
需要注意的另外一點,上面定義模型屬性的時候有virtual關鍵字,表示延遲加載,我的理解是這樣:當我訪問主實體的時候,啟動延遲加載,而不會查詢數據庫的子實體,只有要訪問它的時候才會去數據庫查詢加載,泛型List表示此實體是一對多的關系。
EF默認是啟動延遲加載的,我們如果不需要也可以手動禁止:
1 db.Configuration.LazyLoadingEnabled = false;,
創建上下文DbContext
我對EF中上下文的理解:可以把上下文看成一個數據庫控制器,我們可以在其中查詢、更改、刪除數據,然后通過連接獲取或是提交。就像是遙控車的遙控器一樣,EF是這個遙控器的核心部件,天線是連接字符串,遙控車是數據庫,這個比喻可能不是很恰當,但就是這個意思,大家都懂得。
1 public class NewsContext : DbContext 2 { 3 public DbSet<New> News { get; set; } 4 public DbSet<NewType> NewTypes { get; set; } 5 }
DbSet表示上下文中給定類型的所有實體的集合或可從數據庫中查詢的給定類型的所有實體的集合,就像是一個包裹,需要什么東西就往里面裝什么東西。
創建數據庫、讀/寫數據
在Program.cs的Main方法中填寫代碼:
1 using (var db = new NewsContext()) 2 { 3 Console.Write("輸入新聞類型標題: "); 4 var name = Console.ReadLine(); 5 6 var type_Model = new NewType { Name = name }; 7 db.NewTypes.Add(type_Model); 8 db.SaveChanges(); 9 10 Console.WriteLine("查詢新聞類型標題:"); 11 var search_type = Console.ReadLine(); 12 var query = from b in db.NewTypes 13 where b.Name == search_type 14 select b; 15 16 Console.WriteLine("查詢結果:"); 17 foreach (var item in query) 18 { 19 Console.WriteLine(item.Name); 20 } 21 22 Console.ReadKey(); 23 }
上面代碼創建一個上下文對象實例,通過該實例添加一個新聞實體,然后通過輸入的值,linq查詢結果輸出。
通過上面的操作,我們并沒有創建什么連接字符串和數據庫操作,但是打開數據庫就可以看到我們通過Code First創建的數據庫了。
我當時做的時候,運行代碼沒有錯誤,但是用.\SQLEXPRESS和localhost登陸都看不到數據庫,安裝vs2012就給自動安裝了localdb,因為我本地沒 .\SQLEXPRESS,MSDN相關注解:
- 如果本地 SQL Express 實例可用(默認情況下隨 Visual Studio 2010 安裝),則 Code First 已對該實例創建了數據庫
- 如果 SQL Express 不可用,則 Code First 將嘗試使用 LocalDb(默認情況下隨 Visual Studio 2012 安裝)
配置連接字符串
通過上面默認生成數據庫規則可以看出,數據庫名是項目命名空間+上下文,有時候我們需要自己定義生成數據庫名稱,或是生成數據庫到指定的服務器,而且有時候數據庫遷移了,我們不能再重新生成一遍吧,這時候我們就要自定義數據庫連接字符串了:
1 <connectionStrings> 2 <add name="NewContext" providerName="System.Data.SqlClient" connectionString="Server=.\SQLEXPRESS;Database=CodeFirstDemoDB;Trusted_Connection=true" /> 3 </connectionStrings>
需要注意的是:連接字符串的名稱必須要和上下文一致,而且connectionStrings必須放在configuration節點內的最下面,如果放在最上面會報下面這種錯誤:
我們重新按照上面的操作運行程序,就可以在指定的服務器.\SQLEXPRESS,生成指定的數據庫CodeFirstDemoDB。
Code First 遷移
關于Code First 遷移其實就是我們在更改模型的時候,數據庫要相應的更改,打開工具-庫程序包管理器-程序包管理器控制臺。
1,例如我們上面創建NewTypes表的時候,沒有指定字段的長度,默認是創建字段類型是nvarchar(MAX),有時候我們覺得字段長度太長,需要修改一下字段長度,不要直接去修改數據庫,而是在模型中修改:
1 [MaxLength(50)] 2 public string Name { get; set; }
MaxLength就是上面我們說到DataAnnotations命名空間下的類型,這邊我們注意下,我們在生成數據庫的時候添加了一條數據,Name字段值是“newtype one”,看看我們修改字段長度后,字段值是否發生變化?
2,在程序包管理器控制臺輸入“Enable-Migrations”命令來啟用遷移,運行完成后在項目中會創建一個Migrations文件夾,下來有兩類文件:
- Configuration.cs — 此文件包含“遷移”將用來遷移 BloggingContext 的設置。在本演練中不需要進行任何更改,但是,在此處可以指定種子數據、為其他數據庫注冊提供程序、更改生成遷移的命名空間等。
- <時間戳>_InitialCreate.cs — 這是第一個遷移,它表示已經應用于數據庫的更改。應用更改的目的是將其從空數據庫遷移至包含博客和文章表的數據庫。盡管我們讓 Code First 自動創建這些表,現在我們選擇“遷移”(已轉化為一次“遷移”)。Code First 還在本地數據庫中記錄:該“遷移”已經應用。文件名中的時間戳用于排序。
需要注意的是:在我們生成數據庫的時候,除了New和NewType表外,還有一個系統生成表__MigrationHistory,從表名上就可以看出是遷移歷史記錄表。
3,在程序包管理器控制臺輸入“Add-Migration Update-NewType-Name”命令,Add-Migration表示增加一個遷移,后面是遷移名稱,這個我們可以隨便寫,運行后會自動檢測模型和數據庫發生的變化,在Migrations文件夾下會生成一個“201403290930423_Update-NewType-Name.cs”文件,打開我們可以看到更新內容:
1 public partial class UpdateNewTypeName : DbMigration 2 { 3 public override void Up() 4 { 5 AlterColumn("dbo.NewTypes", "Name", c => c.String(maxLength: 50)); 6 } 7 8 public override void Down() 9 { 10 AlterColumn("dbo.NewTypes", "Name", c => c.String()); 11 } 12 }
從上面可以看出就是我們上面修改模型的內容,當然你也可以在這上面直接修改,比如你再加一個更新,可以一起提交到數據庫。
4,在程序包管理器控制臺輸入“Update-Database”命令,表示將所有的遷移應用到數據庫,打開數據庫,我們看一下效果:
從上面可以看出,字段Name的類型已經修改為nvarchar(50),而且字段值并沒有發生變化,可以證明,Code First遷移并不是刪除數據庫再創建。
Code First遷移除了上面說的字段類型修改還有很多內容,比如添加字段,刪除字段,刪除表等等,但都是大同小異,可以舉一反三。
示例Demo下載
下載地址:http://pan.baidu.com/s/1i3DS9b3
后記
凡事貴在開始,更貴在堅持,與你共勉。。。
如果你覺得本篇文章對你有所幫助,請點擊右下部“推薦”,^_^
文章列表