2.EF中 Code-First 方式的數據庫遷移


原文鏈接:http://www.c-sharpcorner.com/UploadFile/3d39b4/code-first-migrations-with-entity-framework/

或者:http://www.codeproject.com/Articles/801545/Code-First-Migrations-With-Entity-Framework

系列目錄:

 

 

前面的文章中,學習了EF 中的幾種關系,一對一,一對多,多對多。但是相信大家肯定會有疑問:

1.我難道每次都要創建數據庫么?

2.我怎么樣從已經存在的表中,添加字段和移除字段呢?

3.當我向表中,添加字段或者移除字段,我怎么來避免丟失數據呢?

4.當數據庫發生改變的時候,我怎么獲取到數據庫的腳本呢?

不用着急,這篇文章,我會向大家一一講到:

首先,說說我們為什么要使用數據庫遷移技術吧,因為我們的實體總是變動地很頻繁,在上篇文章中,我們使用了數據庫初始化策略來做,也就是每次當數據庫不存在的時候,就創建數據庫【類似還有幾種初始化策略】,然而,當你的實體改變的時候,在使用這個策略,EF就會報錯。而數據庫遷移技術就可以幫到我們,我們不用每次都創建數據庫。並且數據庫遷移技術還可以為我們設置初始化的數據。

先看看項目結構吧:

我們需要建2個類庫項目,還有一個控制台的程序:

Student類:

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace EF.Core { public class Student { public int ID { get; set; } public string Name { get; set; } public int Age { get; set; } public string Sex { get; set; } } }

StudentMap類:

using EF.Core; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; using System.Data.Entity.ModelConfiguration; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Ef.Data { public class StudentMap:EntityTypeConfiguration<Student> { public StudentMap() { this.HasKey(s => s.ID); this.Property(s => s.ID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); this.Property(s => s.Name).HasColumnType("nvarchar").HasMaxLength(50).IsRequired(); this.Property(s => s.Sex).HasColumnType("nvarchar").IsRequired(); this.Property(s => s.Age).IsRequired(); this.ToTable("Students"); } } }

EF上下文類:

using System; using System.Collections.Generic; using System.Data.Entity; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Ef.Data { public class EFDbContext:DbContext { public EFDbContext() : base("name=DbConnectionString") { } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Configurations.Add(new StudentMap()); //base.OnModelCreating(modelBuilder);
 } } }

數據庫連接字符串:【在EF.Data的配置文件和控制台的項目的配置文件中都要寫:】另外注意:這兩個項目需要引入EF

<connectionStrings>
    <add name="DbConnectionString" connectionString="Server=.;database=StudentEFDB;uid=sa;pwd=Password_1" providerName="System.Data.SqlClient" />
  </connectionStrings>

控制台中:

using Ef.Data; using EF.Core; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace EF.App { public class Program { static void Main(string[] args) { Console.WriteLine("你好,請輸入姓名:"); string name = Console.ReadLine().Trim(); Console.WriteLine("請輸入年齡:"); int result = 0; //轉換成功,result是正確的結果
            if (!int.TryParse(Console.ReadLine().Trim(), out result)) { Console.WriteLine("請輸入正確格式的年齡"); return; } Console.WriteLine("請輸入你的性別:"); string sex = Console.ReadLine(); using(var db=new EFDbContext()) { Student model = new Student() { Name = name, Sex = sex, Age = result }; //db.Set<Student>().Add(model);或者下面的
                db.Entry(model).State = System.Data.Entity.EntityState.Added; db.SaveChanges(); } Console.Write("Success!"); Console.ReadKey(); } } }

運行之后,寫入數據。

看下數據庫中的數據:

 

 好了,這就完成了第一階段的准備工作:現在我們需要在Student實體中加一個字段Email,項目做一下變動:

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace EF.Core { public class Student { public int ID { get; set; } public string Name { get; set; } public int Age { get; set; } public string Sex { get; set; } public string Email { get; set; } } }

 

using EF.Core; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; using System.Data.Entity.ModelConfiguration; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Ef.Data { public class StudentMap:EntityTypeConfiguration<Student> { public StudentMap() { this.HasKey(s => s.ID); this.Property(s => s.ID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); this.Property(s => s.Name).HasColumnType("nvarchar").HasMaxLength(50).IsRequired(); this.Property(s => s.Sex).HasColumnType("nvarchar").IsRequired(); this.Property(s => s.Age).IsRequired(); this.Property(s => s.Email).IsRequired(); this.ToTable("Students"); } } }
using Ef.Data; using EF.Core; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace EF.App { public class Program { static void Main(string[] args) { Console.WriteLine("你好,請輸入姓名:"); string name = Console.ReadLine().Trim(); Console.WriteLine("請輸入年齡:"); int result = 0; //轉換成功,result是正確的結果
            if (!int.TryParse(Console.ReadLine().Trim(), out result)) { Console.WriteLine("請輸入正確格式的年齡"); return; } Console.WriteLine("請輸入你的性別:"); string sex = Console.ReadLine();  Console.WriteLine("請輸入你的Email:"); string email = Console.ReadLine(); using(var db=new EFDbContext()) { Student model = new Student() { Name = name, Sex = sex, Age = result,  Email=email  }; //db.Set<Student>().Add(model);或者下面的
                db.Entry(model).State = System.Data.Entity.EntityState.Added; db.SaveChanges(); } Console.Write("Success!"); Console.ReadKey(); } } }

 

 運行之后:報錯,很正常嘛,這肯定報錯,因為我們的實體改了。。

 

 怎么辦呢??別着急,我們來啟用數據庫遷移技術:

在程序包控制台中輸入:

Enable-Migrations

接着按回車鍵,在項目中就會生成Migration文件夾,自己去看看里面有啥東東吧。

 

 

然后打開Configuration類:修改一下代碼:

接着在程序包管理器控制台中輸入:

Update-Database -Verbose

好了,現在運行一下項目吧:

看到了么,到這里就沒報錯了。運行完之后,我們看下數據庫中的數據:

 

 

可以看到之前的數據也在,也就是數據沒有丟失。是不是很神奇呢???

 

總結:這兩篇文章總結了EF的一些使用,希望你喜歡。

 

題外篇:這里是使用EF中的數據庫遷移技術。我們就可以隨時隨地的添加刪除字段。而不用手動去刪除數據庫,那樣會丟失數據。

現在,我就想不用數據庫遷移呢?

我刪掉之前生成的Migration文件夾【包括里面的類】,然后修改代碼【刪除剛才添加的Email字段】:

 

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace EF.Core { public class Student { public int ID { get; set; } public string Name { get; set; } public int Age { get; set; } public string Sex { get; set; } // public string Email { get; set; }
 } }

 

using EF.Core; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; using System.Data.Entity.ModelConfiguration; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Ef.Data { public class StudentMap:EntityTypeConfiguration<Student> { public StudentMap() { this.HasKey(s => s.ID); this.Property(s => s.ID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); this.Property(s => s.Name).HasColumnType("nvarchar").HasMaxLength(50).IsRequired(); this.Property(s => s.Sex).HasColumnType("nvarchar").IsRequired(); this.Property(s => s.Age).IsRequired(); // this.Property(s => s.Email).IsRequired();

            this.ToTable("Students"); } } }
using Ef.Data; using EF.Core; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace EF.App { public class Program { static void Main(string[] args) { Console.WriteLine("你好,請輸入姓名:"); string name = Console.ReadLine().Trim(); Console.WriteLine("請輸入年齡:"); int result = 0; //轉換成功,result是正確的結果
            if (!int.TryParse(Console.ReadLine().Trim(), out result)) { Console.WriteLine("請輸入正確格式的年齡"); return; } Console.WriteLine("請輸入你的性別:"); string sex = Console.ReadLine(); //Console.WriteLine("請輸入你的Email:"); //string email = Console.ReadLine();

           
            using(var db=new EFDbContext()) { Student model = new Student() { Name = name, Sex = sex, Age = result, // Email=email
 }; //db.Set<Student>().Add(model);或者下面的
                db.Entry(model).State = System.Data.Entity.EntityState.Added; db.SaveChanges(); } Console.Write("Success!"); Console.ReadKey(); } } }

 

 

 運行之后,還肯定會報錯的,因為已經沒有數據庫遷移了:

 

 我們做如下修改:

 

using System; using System.Collections.Generic; using System.Data.Entity; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Ef.Data { public class EFDbContext:DbContext { public EFDbContext() : base("name=DbConnectionString") { //把數據庫初始化策略設置為null
          Database.SetInitializer<EFDbContext>(null); } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Configurations.Add(new StudentMap()); //base.OnModelCreating(modelBuilder);
 } } }

 

 然后運行項目,就不錯報錯了,這是不使用數據庫遷移技術做到的。

 

 看下數據庫:

兩種方式都可以,不過還是推薦官方的方式,數據庫遷移技術。

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM