MVC中code first方式开发,数据库的生成与更新(Ef6)

时间:2022-09-05 20:29:09

一般首次建立数据库时,需要运行建立数据库的相关代码,如Database.SetInitializer<BaseContext>(new BaseInitializer());  但如果后续进行更改,为了保留数据,一般通过MIGRATION进行,且将建表的相关代码删除或注释了。而CODE FIRST的跨数据库,据此而言也不是仅仅的更改配置了。当然,如果添加CreateDatabaseIfNotExists估计影响不大,但如果是DropCreateDatabaseIfModelChanges或者DropCreateDatabaseAlways,则会丢失相关数据。



一,在models文件夹中,建立相应的model文件
        这里注意一点,这里建立的class名,就是数据库里表的名字。
        在这里面,可以建立表之间的关系。

        这里要说明一点的事,一般情况下,我们会把n:m的形式,变成两个1:n的模式

       

[csharp] view plain copy print ?
  1.    //学生信息  
  2.    namespace codefirst.Models  
  3. {  
  4.     public class Students  
  5.     {  
  6.     public int ID { getset; }  
  7.   
  8.     [Required]  
  9.     [MaxLength(10)]   
  10.     public string stu_Name { getset; }  
  11.   
  12.     public string stu_Pwd { getset; }  
  13.   
  14.     public string stu_sex { getset; }  
  15.   
  16.     public int stu_age { getset; }  
  17.   
  18.     public virtual ICollection<StuCousers> StuCousers { getset; }  
  19.     }  
  20. }  
  21.   
  22.    //课程信息  
  23.    namespace codefirst.Models  
  24. {  
  25.     public class Courses  
  26.     {  
  27.     public int ID { getset; }  
  28.   
  29.     public string course_Name { getset; }  
  30.   
  31.     public string course_code { getset; }  
  32.   
  33.     public virtual ICollection<StuCousers> StuCousers { getset; }  
  34.     }  
  35. }  
  36.   
  37.    //学生课程关联表  
  38.    namespace codefirst.Models  
  39. {  
  40.     public class StuCousers  
  41.     {  
  42.     public int ID { getset; }  
  43.   
  44.     public int StudentID { getset; }  
  45.   
  46.     public int CourseID { getset; }  
  47.   
  48.     public virtual Students Student { getset; }  
  49.   
  50.     public virtual Courses Course { getset; }  
  51.     }  
  52. }  
二,新建一个Dal文件夹,用来建立Database Context

[csharp] view plain copy print ?
  1. namespace codefirst.DAL  
  2.     {  
  3.         public class BaseContext : DbContext  
  4.         {  
  5.   
  6.         /// <summary>  
  7.         /// 构造函数中的 base("AccountContext") 。  
  8.         /// 默认情况下和类名一样,即AccountContext,我们显式的给他指定出来。  
  9.         /// </summary>  
  10.         public BaseContext()  
  11.             : base("BaseContext")  
  12.         {  
  13.   
  14.         }  
  15.   
  16.         public DbSet<Students> Students { getset; }  
  17.   
  18.         public DbSet<Courses> Courses { getset; }  
  19.   
  20.         public DbSet<StuCousers> StuCousers { getset; }  
  21.   
  22.         /// <summary>  
  23.         /// 指定单数形式的表名  
  24.         /// 默认情况下会生成复数形式的表,如SysUsers  
  25.         /// </summary>  
  26.         /// <param name="modelBuilder"></param>  
  27.         protected override void OnModelCreating(DbModelBuilder modelBuilder)  
  28.         {  
  29.             modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();  
  30.         }  
  31.         }  
  32.     }  

这里面DbSet对应着数据库里表

三,初始化数据库与表

        第一次运行程序时新建数据库,插入测试数据; model改变(和database不一致)时删除重建数据库,插入测试数据。
先不用管数据丢失的问题,直接drop and re-create比较方便。

      

[csharp] view plain copy print ?
  1.    namespace codefirst.DAL  
  2. {  
  3.     public class BaseInitializer : DropCreateDatabaseIfModelChanges<BaseContext>  
  4.     {  
  5.     protected override void Seed(BaseContext context)  
  6.     {  
  7.         var stu = new List<Students>  
  8.         {  
  9.         new Students{stu_Name="小明",stu_Pwd="123456",stu_sex="男"},  
  10.         new Students{stu_Name="小芳",stu_Pwd="654321",stu_sex="女"}  
  11.         };  
  12.   
  13.         stu.ForEach(s => context.Students.Add(s));  
  14.         context.SaveChanges();  
  15.   
  16.         var cou = new List<Courses>  
  17.         {  
  18.         new Courses{course_Name="语文",course_code="10001"},  
  19.         new Courses{course_Name="数学",course_code="10002"}  
  20.         };  
  21.   
  22.         cou.ForEach(c => context.Courses.Add(c));  
  23.         context.SaveChanges();  
  24.     }  
  25.     }  
  26. }  

四,修改根目录下面的Web.config文件,添加

       

  1. <connectionStrings>  
  2.     <add name="BaseContext" connectionString="Data Source=.;database=StuAndCourse;uid=sa;pwd=xxxxxxx;AttachDBFilename=|DataDirectory|\StuAndCourse.mdf" providerName="System.Data.SqlClient" />  
  3. </connectionStrings>  

        这样,会在App_Data文件夹下生成名为StuAndCourse的数据库

五,在Global.asax文件,添加创建语句

       

[csharp] view plain copy print ?
  1.   protected void Application_Start()  
  2.    {  
  3.        AreaRegistration.RegisterAllAreas();  
  4.        RouteConfig.RegisterRoutes(RouteTable.Routes);  
  5.   
  6. //添加建表  
  7.        Database.SetInitializer<BaseContext>(new BaseInitializer());  
  8.    }  
六,建立Controllers文件,向前台输出数据

      

[csharp] view plain copy print ?
  1.     namespace codefirst.Controllers  
  2.   
  3.   
  4.    public class StudentController : Controller  
  5.    {  
  6.   
  7. BaseContext db = new BaseContext();  
  8.   
  9. // GET: Student  
  10. public ActionResult Index()  
  11. {  
  12.     return View(db.Students.ToList());  
  13. }  
  14.    }  
七,建立Views文件,用来显示数据

  1. @model IEnumerable<codefirst.Models.Students>  
  2.     @{  
  3.         Layout = null;  
  4.     }  
  5.   
  6.     <!DOCTYPE html>  
  7.   
  8.     <html>  
  9.     <head>  
  10.         <meta name="viewport" content="width=device-width" />  
  11.         <title>Index</title>  
  12.     </head>  
  13.     <body>  
  14.         <div>   
  15.         <table>  
  16.             @foreach (var item in Model)  
  17.             {  
  18.             <tr>  
  19.                 <td>  
  20.                 @Html.DisplayFor(modelItem => item.stu_Name)  
  21.                 </td>  
  22.                 <td>  
  23.                 @foreach(var sc in item.StuCousers)  
  24.                 {  
  25.                     @Html.Label(sc.Course.course_Name)  
  26.                 }  
  27.                 </td>  
  28.             </tr>  
  29.             }  
  30.         </table>  
  31.         </div>  
  32.     </body>  
  33.     </html>  

好,现在运行程序,你会发现,数据显示出来了,而且数据库也建立成功了。这里为什么要有第六,七步呢,因为你要有一个操作数据库的代码,它才会去建数据库。

下面我们再来看一下,如果我修改了Models中的文件,使得SysUser与数据库中的SysUser表的字段不一样了,这样如果我再运行程序,你会发现数据库被重置了。
这为什么呢,还记得第三步吗,这里就是如果结构不一定,就会删除再生成表。
可是我们在开始的过程中,有一些数据,不希望丢怎么办呢。

工具 -> 库程序包管理器 -> 程序包管理器控制台
运行命令 Enable-Migrations
Checking if the context targets an existing database...
Detected database created with a database initializer. Scaffolded migration '201212090821166_InitialCreate' corresponding to existing database. To use an automatic migration instead, delete the Migrations folder and re-run Enable-Migrations specifying the -EnableAutomaticMigrations parameter.

会出现,上面这个错误。不用管它,这时候,你会发现在程序端多出一个文件夹叫Migrations
这里面有一个Configuration.cs文件
打开它,然后修改成如下样子,
public Configuration()
{
AutomaticMigrationsEnabled = true; //这里变成true
ContextKey = "codefirst.DAL.BaseContext";
}

修改完成后,运行
Update-Database -Force这个时候,你再看一下数据库里面的表结构是不是变了,而数据却没有丢呢.

以后再有更改,只要保证Configuration.cs文件中的AutomaticMigrationsEnabled = true;
只运行Update-Database -Force就可以了