使用CodeFirst創建并更新數據庫

本文主要介紹如何使用CodeFirst模式來新建并更新數據庫

在使用Entity Framwork的三種方式(ModelFist、DBFirst、CodeFirst)中,CodeFirst方式書寫的代碼最為干凈。

至于CodeFist方式的詳細優缺點請各位讀者自行搜索,這里不多贅述。

1. 使用CodeFirst方式創建數據庫

我們新建一個控制臺項目,項目中添加兩個Model:Author和Blog以及DbContext。 DbContext的添加方式如下:

項目上右鍵->添加->新建項->ADO.NET Entity Data Model->Empty Code First model

項目代碼如下:

 1 //默認生成的數據表名為類名+字母s,這里使用TableAttribute來指定數據表名為T_Authors
 2     [Table("T_Authors")]
 3     public class Author
 4     {
 5         public int Id { set; get; }
 6         public string Name { set; get; }
 7         /*
 8         此處定義了Blog類型的屬性,所以要確保Blog類中至少要有一個表示主鍵的字段,即public int Id { set; get; }。
      否則在生成數據表時會報錯:"EntityType 'Blog' has no key defined. Define the key for this EntityType.
9     Blogs: EntityType: EntitySet 'Blogs' is based on type 'Blog' that has no keys defined." 10     */ 11 public virtual ICollection<Blog> Blogs { set; get; } 12 } 13 14 [Table("T_Blogs")] 15 public class Blog 16 { 17 public int Id { set; get; } 18 public string Title { set; get; } 19 public DateTime Time { set; get; } 20 public int AuthorId { set; get; } 21 public virtual Author Author { set; get; } 22 } 23 24 public class MyDbContext: DbContext 25 { 26 public MyDbContext() 27 : base("name=MyDbContext") 28 { 29 } 30 //DbContext會根據配置文件中connectionStrings指定的數據庫名稱來建立數據庫 31 //DbContext根據DbSet屬性的類型來創建數據表,這里指定了Author類型的屬性,所以會生成T_Authors數據表 32 public virtual DbSet<Author> Authors { set; get; } 33 }

?

CodeFirst方式會根據配置文件中的配置生成數據庫,這里小編使用的是MYSQL數據庫,配置文件如下:

 1 <!--EF for MYSQL-->
 2  <entityFramework codeConfigurationType="MySql.Data.Entity.MySqlEFConfiguration, MySql.Data.Entity.EF6">
 3     <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
 4     <providers>
 5       <provider invariantName="MySql.Data.MySqlClient" type="MySql.Data.MySqlClient.MySqlProviderServices, MySql.Data.Entity.EF6" />
 6     </providers>
 7   </entityFramework>
 8   <connectionStrings>
 9     <add name="MyDbContext" connectionString="server=localhost;port=3306;database=EF;uid=root;password=root" providerName="System.Data.MySqlClient" />
10   </connectionStrings>

PS:小編使用的是EF6和MYSQL數據庫,所以要在項目中添加對Mysql.Data.Entity.EF6以及EntityFrameword 6.0的引用。

到此,我們已經完成生成數據庫的工作,接下來在Main方法中寫兩行代碼:

1 using (var db = new MyDbContext())
2 {
3     db.Authors.Add(new Author() { Name = "xfh" });
4     db.SaveChanges();
5 }

?運行程序,我們會發現EF已經為我們建立了數據庫,數據庫名稱為EF(在配置文件中指定)以及數據表T_Authors。

雖然我們沒有為DbContext添加Blog類型的屬性,但依然創建了數據表T_Blogs,這是因為在Author類中定義了Blog類型的屬性,若我們注釋掉

?public virtual ICollection<Blog> Blogs { set; get; }?,刪除數據庫重新生成就會發現不在生成T_Blogs表。在生成T_Authors表的同時,會生成一張名為_migrationhistory表,這張表用于記錄我們對于數據庫的更新日志,表中的MigrationId字段的值是我們每次執行Migration時所生成的文件名,根據該字段的值我們可以使用命令?Update-Database -TargetMigration:MigrationIdValue?來將數據庫恢復到MigrationIdValue所對應的Migration狀態,和Git版本控制有點兒像,但這里若將數據庫回滾到以前的版本會導致數據的丟失,并且_migrationhistory表也會刪除所記錄的當前Migration信息。

2. 更新數據庫(Code Fist Migration)

現在,我們給Author類增加字屬性Email,代碼如下:

    [Table("T_Authors")]public class Author{public int Id { set; get; }public string Name { set; get; }public string Email { set; get; }public virtual ICollection<Blog> Blogs { set; get; }}

此時,再次運行該應用程序,則將拋出異常

An unhandled exception of type 'System.InvalidOperationException' occurred in EntityFramework.dll
The model backing the 'MyDbContext' context has changed since the database was created. Consider using Code First Migrations to 
update the database (http://go.microsoft.com/fwlink/?LinkId=238269).

異常信息中提示我們數據庫創建之后model發生了變化,所以我們需要對數據庫進行更新使二者保持一致才能運行程序。

2.1 啟用遷移

對于首次遷移需要啟用遷移,具體方法是在Packge Manager Console中輸入Enable-Migrations命令即可。


命令運行完畢之后我們會看到命令行中的提示信息

這里我們只是啟用了遷移,但不是自動遷移。從提示信息中我們可以看到若要啟用自動遷移則要刪除Migrations文件夾并在Packge Manager Console中輸入

Enable-Migrations –EnableAutomaticMigrations命令或者在Migrations文件夾的Configuration.cs文件中設置AutomaticMigrationsEnabled屬性為true即可。

Enable-Migrations命令運行完畢之后會在項目中生成如下文件:

Configuration文件?我們可以在此文件中針對上下文配置遷移行為。

InitialCreate文件 ??因為我們事先讓 Code First 自動創建了一個數據庫,這個遷移文件中的代碼表示數據庫中已創建的對象。該文件文件名包含時間戳,這對于排序十分有幫助。如果尚未創建數據庫,則不會將此 InitialCreate 遷移添加到項目中。而是,首次調用 Add-Migration 時,用于創建這些表的代碼將為新遷移搭建基架。

2.2 更新數據庫

啟用遷移之后,在Packge Manager Console中繼續輸入Update-Database命令來更新數據庫,但會發現更新失敗。

通過上面的提示信息我們可以知道,要想更新數據庫需要啟用自動遷移或者使用Add-Migration命令來創建遷移文件。

2.2.2 基于代碼的遷移

我們在Packge Manager Console中輸入命令Add-Migration AddEmail,命令運行完畢后我們會發現Migrations文件夾下已經創建了_AddEmail文件,文件內容如下:

 1 public partial class AddEmail : DbMigration
 2 {
 3     public override void Up()
 4     {
 5         //注意,這里數據表的名稱是dbo.T_Blogs和dbo.T_Authors而不是我們指定的
 6         //T_Blogs和T_Authors,我們可以把數據表名稱改為T_Blogs和T_Authors
 7         //數據表以dbo開頭貌似是SQL SERVER中的命名方式,這里小編使用的是MYSQL
 8         CreateTable(
 9             "dbo.T_Blogs",
10             c => new
11                 {
12                     Id = c.Int(nullable: false, identity: true),
13                     Author_Id = c.Int(),
14                 })
15             .PrimaryKey(t => t.Id)
16             .ForeignKey("dbo.T_Authors", t => t.Author_Id)
17             .Index(t => t.Author_Id);
18         
19         AddColumn("dbo.T_Authors", "Email", c => c.String(unicode: false));
20     }
21     
22     public override void Down()
23     {
24         DropForeignKey("dbo.T_Blogs", "Author_Id", "dbo.T_Authors");
25         DropIndex("dbo.T_Blogs", new[] { "Author_Id" });
26         DropColumn("dbo.T_Authors", "Email");
27         DropTable("dbo.T_Blogs");
28     }
29 }
30     

?

我們可以看到Up方法中調用了AddColumn方法來向數據庫中添加Email字段。這時我們在Packge Manager Console中輸入命令Update-Database命令(也可以使用Update-Database -Verbose命令,該命令可以使我們看到SQL語句的執行過程,注意-Verbose和-Database之間有個空格)并運行,可以看到命令成功執行,然后到數據庫中查看數據表T_Authors發現表中已經添加字段Email,同時數據表__migrationhistory中對于我們的此次更新進行了記錄。

對于上述代碼我們可以進行簡化:

public partial class AddEmail : DbMigration
{public override void Up(){AddColumn("T_Authors", "Email", c => c.String(unicode: false));}public override void Down(){DropColumn("T_Authors", "Email");}
}

我們也可以直接通過創建遷移文件來更新數據庫而不修改Model。如:

通過命令Add-Migration addAge來創建一個新的遷移文件,代碼如下:

public partial class AddAge : DbMigration
{public override void Up(){AddColumn("T_Authors", "Age", c => c.Int(nullable: false,defaultValue:18));}public override void Down(){DropColumn("T_Authors", "Age");}
}

然后運行命令Update-Database,我們會發現數據庫T_Authors表中創建了字段Age。雖然成功的更新了數據庫,但會導致程序中的Model和數據表不匹配。

2.2.2 ?自動遷移?

啟用自動遷移的方法前文已經陳述。在啟用自動遷移之后,我們再修改Model文件,只需執行Update-Database命令即可完成對數據庫的更新。

?

最后再補充一點,在創建數據庫之后若修改TableAttribute和ColumnAttribute的值,那么在執行程序時EF會按照TabelAttribute和ColumnAttribute中指定的值和數據庫進行匹配,但數據庫中并不存在我們新指定的數據表和字段,這會導致程序報錯。若我們修改了TableAttribute和ColumnAttribute的值,然后再使用Update-Database命令來更新數據庫,數據庫會新建一張有TableAttribute指定名稱的數據表。

參考文章:

自動化 Code First 遷移

What is Code-First

Code First 遷移

版權聲明

本文為作者原創,版權歸作者雪飛鴻所有。 轉載必須保留文章的完整性,且在頁面明顯位置處標明原文鏈接。

如有問題, 請發送郵件和作者聯系。

轉載于:https://www.cnblogs.com/Cwj-XFH/p/5613544.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/255027.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/255027.shtml
英文地址,請注明出處:http://en.pswp.cn/news/255027.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

fedora 15怎么修改運行級別?

inittab改了已經在fedora15中&#xff0c;你vim它就可以看到更改說明&#xff0c;就是說都改到/etc/systemd/system/default.target這里了&#xff0c;就是缺省的設置。如果你要改變缺省值就把對應的runlevel移動過去覆蓋了。 To 3 字符 [root15 system]# rm -rf /etc/systemd…

淺析人臉檢測之Haar分類器方法

由于工作需要&#xff0c;我開始研究人臉檢測部分的算法&#xff0c;這期間斷斷續續地學習Haar分類器的訓練以及檢測過程&#xff0c;在這里根據各種論文、網絡資源的查閱和對代碼的理解做一個簡單的總結。我試圖概括性的給出算法的起源、全貌以及細節的來龍去脈&#xff0c;但…

利用微軟平臺生成報表,線性圖,柱形圖

說來慚愧,以前的工作中一直借助第三方dll進行報表制作,比如線性圖,柱形圖. 因為現在工作的這家公司不允許隨便引入第三方dll,聽同事說起可以建rdl類型文件進行引入到winform窗體中,窗體上使用reportViewer控件進行關聯展示.下面是我今天摸索3個小時的結果分享. 第一步. 首先找到…

Linux ffmpeg的安裝編譯過程

Linux ffmpeg的安裝編譯過程 1、下載ffmpeg。    在網上搜索一下,或者到官方網站下載2、解壓   tar命令解壓3、配置  ./configure --enable-shared --prefix/usr/local/ffmpeg  其中&#xff1a;--enable-shared 是允許其編譯產生動態庫&#xff0c;在以后的編程中…

opencv 模板匹配(cvMatchTemplate)

opencv 模板匹配(cvMatchTemplate) 模板匹配是通過在輸入圖像上滑動模板圖像塊對實際的圖像塊和輸入圖像進行匹配&#xff0c;并且可以利用函數cvMinMaxLoc()找到最佳匹配的位置。例如在工業應用中&#xff0c;可以鎖定圖像中零部件的位置&#xff0c;并根據具體的位置&…

爬蟲系統Lucene分詞

思路&#xff1a;查詢數據庫中信息&#xff0c;查詢出id和name把那么進行分詞存入文件 package com.open1111.index; import java.io.IOException;import java.nio.file.Paths;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet; impor…

[BZOJ1880] [Sdoi2009] Elaxia的路線 (SPFA 拓撲排序)

Description 最近&#xff0c;Elaxia和w**的關系特別好&#xff0c;他們很想整天在一起&#xff0c;但是大學的學習太緊張了&#xff0c;他們 必須合理地安排兩個人在一起的時間。Elaxia和w**每天都要奔波于宿舍和實驗室之間&#xff0c;他們 希望在節約時間的前提下&#xff0…

ffmpeg的編譯大全

ffmpeg的編譯大全 最近互聯網視頻共享的網站很火&#xff0c;公司也想搞類似的網站&#xff0c;初步是用fmsffmpeg形式 fms負責在線錄制&#xff0c;播放&#xff0c;ffmpeg則在后臺處理上傳的資源轉換成一定的格式。 為了讓ffmpeg支持的格式盡量多&#xff0c;所以特把我的編譯…

用OPENCV視覺解數獨

用OPENCV視覺解數獨 2010-06-29 看到增強視覺網站上介紹老外用視覺解SUDOKU(http://www.cvchina.info/2011/05/29/video-sudoku-solver/)&#xff0c;覺得應該不難&#xff0c;于是用OPENCV和訓練好的數字分類器&#xff0c;也試著做一個&#xff0c;純屬娛樂 基本思路如下&…

集成ffmpeg/x264:ERROR: libx264 not found的問題

集成ffmpeg/x264:ERROR: libx264 not found的問題--拔劍集成ffmpeg/x264碰到如下問題&#xff1a; ERROR: libx264 not found察看config.log,詳細信息如下&#xff1a;check_lib x264.h x264_encoder_encode -lx264check_header x264.hcheck_cppBEGIN/tmp/ffconf.isuazGlg.c1 …

[ActionScript 3.0] AS3.0 下雨及漣漪效果

幀代碼&#xff1a; stage.frameRate 80;function init(x1:Number,y1:Number) {var mc:MovieClipnew MovieClip();addChild(mc);mc.x x1;mc.y y1;mc.graphics.lineStyle(0.5,0xbbffff,0.6);mc.graphics.drawEllipse(-1,-0.3,2,0.6);mc.addEventListener(Event.ENTER_FRAME,f…

JS Math.round()方法原理

請先測試代碼&#xff1a; 1 <!doctype html>2 <html lang"en">3 4 <head>5 <meta charset"UTF-8" />6 <title>Math.round方法</title>7 <style type"text/css">8 …

一個通用Makefile的編寫

我們在 LinuxLinux Linux是一套免費使用和自由傳播的操作系統&#xff0c;它主要用于基于Intel系列CPU的計算機上。這個系統是由全世界各地的成千上萬的程序員設計和實現的&#xff0c;其目的是建立不受任何商品化軟件的版權制約的、全世界都能自由使用的Unix兼容產品。 環境下…

Cache替換算法:LRU與LFU的區別

LFU&#xff08;Least Frequently Used&#xff09;最近最少使用算法。它是基于“如果一個數據在最近一段時間內使用次數很少&#xff0c;那么在將來一段時間內被使用的可能性也很小”的思路。LRU&#xff08;Least Recently Used&#xff09;. 注意LFU和LRU算法的不同之處&…

001-Ansible-參考http://www.ansible.com.cn/docs/playbooks_intro.html#about-playbooks

1. Patterns 在Ansible中,Patterns 是指我們怎樣確定由哪一臺主機來管理. 意思就是與哪臺主機進行交互. ansible <pattern_goes_here> -m <module_name> -a <arguments>ansible webservers -m service -a "namehttpd staterestarted"同時讓我們提前…

linux下通用Makefile寫法

linux編譯多個源文件的程序比較麻煩&#xff0c;這下就需要通用的Makefile了&#xff0c;編譯的時候執行一下make命令就OK&#xff0c;下面介紹通用makfile的寫法。 假設現在有以下源文件&#xff1a;file1.h file1.c file2.h file2.c mainproc.c&#xff0c;程序的主函數在mai…

客服彈出框

html代碼&#xff1a; <head><meta http-equiv"Content-Type" content"text/html; charsetutf-8" /><title>QQ在線客服jquery特效</title><link rel"stylesheet" type"text/css" href"common/css/lay…

第三次畢業設計任務書

一. 進度計劃 時間 計劃進度 3.24-3.30 嘗試將kdd數據預處理用代碼實現 3.31-4.6 將kdd數據預處理用代碼實現以及與aprior算法的結合 二. 課題需求 2.1 數據預處理的功能和主要方法 在現實中,由于數據的來源、組織、存儲等的多樣性,海量的原始數據中一般都很難避免“臟數據…

電商第一季函數筆記(1)

1、isset (PHP 4, PHP 5, PHP 7) isset — 檢測變量是否設置 說明 bool isset ( mixed $var [, mixed $... ] ) 檢測變量是否設置&#xff0c;并且不是 NULL。 如果已經使用 unset() 釋放了一個變量之后&#xff0c;它將不再是 isset()。若使用 isset() 測試一個被設置成 NULL …

壓縮xvid ffmpeg x264 對比

壓縮xvid ffmpeg x264 對比 Xvid是基于MPEG4協議的編解碼器&#xff0c;x264是基于H.264協議的編碼器&#xff0c;ffmpeg集合了各種音頻&#xff0c;視頻編解碼協議&#xff0c;通過設置參數可以完成基于MPEG4,H.264等協議的編解碼&#xff0c;現在將其對比結果羅列如下&#…