MVC数据库学习(一)-----使用实体框架自动更新数据库
在任何框架中,对于数据库的使用都是一个重点,因为我们使用的数据大部分都是存储在数据库中。ASP.NET MVC对数据库提供了非常好的支持,尤其是当我们在开发中,可以使用实体框架(Entity Framework)进行代码优先(Code-First)的开发工作。
所谓的代码优先,需要和模型优先或数据库优先一起讨论。简单点讲,模型优先就是我们必须先设计model,然后通过模型生成数据库的结构,数据库优先就是我们在已有的数据库上设计model。这样的理解是很粗鄙的,但有关数据库的讨论需要很深厚的基础知识作为储备,鉴于本人的水平,这里不便展开。代码优先是MVC"约定优于配置"的表现。所谓的"约定优于配置"是Ruby中扩散开来的概念,本质意义是我们可以将以前积累的经验应用于框架中,使得我们以后开发没有必要再配置每一项。使用代码优先的方式,即使我们还没有创建我们的数据库,还是可以先创建我们的对象,也就是model,在创建的过程中,不用考虑数据库中对象之间复杂的关系,不用添加任何有关数据持久层的标签,这在实体框架识别主键的行为中发挥非常重要的作用。
要想使用这种开发方式,我们需要了解ASP.NET MVC提供的基架。基架是一个非常强大的工具,它可以为应用程序的CRUD(Create,Read,Update,Delete)生成所需要的样板代码。基架会根据model的定义,生成控制器以及该控制器的关联视图。简而言之,基架可以为我们生成默认的模板,然后我们可以根据自己的需要进行修改。
因为基架,所以实体框架的使用更加强大。实体框架,顾名思义,就是一个对象关系映射框架。实体框架真的非常聪明,它知道我们的model中那个属性是键值,即使我们没有特意提醒。好吧,其实我们已经提醒了,就是我们的键值一般都是这样的命名:XXID,其中XX为该model的名字,实体框架会自己假设该属性为键值,并且赋给SQL Server对应的自动递增键列。这些假设就是约定,只要我们在该框架下属性的命名都遵从这种约定,那么,我们就可以享受这种便利。当然,EF对于外键,数据库名称等都有它的约定。
即使我们的数据库是模拟的,但是我们也要创建它。创建一个模拟的数据库,需要我们从EF的DbContext类中派生出一个类来访问数据库:
public class StoreContext : DbContext { public DbSet<User> Users { get; set; } public DbSet<Category> Categories { get; set; } public DbSet<Comment> Comments { get; set; } public DbSet<Log> Logs { get; set; } }
该派生类具有一个或多个DbSet<T>类型的字段,T是泛型,表示我们想要持久保存的对象。
接着我们只要将它new出来,结合LINQ就可以进行数据库的各种操作,像是下面这样的查询:
User user = (from u in storeDb.Users where u.Name.ToLower() == User.Identity.Name.ToLower() select u).FirstOrDefault();
DbContext,顾名思义,就是数据上下文,在实际编程中,model有时候也会被修改,但是数据库怎么办呢?数据库并不会自己自动更新,所以这时候就会有这样的错误:
支持“StoreContext”上下文的模型已在数据库创建后发生更改。请考虑使用 Code First 迁移更新数据库
解决这样的问题有两种方案:重新创建数据库和修改数据库。
修改数据库需要手动操作,重新创建数据库可以通过某种方式让它自动执行。一般我们在正式发布的时候,是不会修改我们的model,只有在测试的时候才会发生这种事情,所以,在开发的时候,采取第一种方法是最好的。
要想让数据库能够自动创建,我们需要一个新的类:
public class UserIntializer : DropCreateDatabaseIfModelChanges<StoreContext> { protected override void Seed(StoreContext context) { base.Seed(context); } }
重新创建数据库,会使得我们之前的数据全部消失,但如果我们想要在重新创建数据库的时候,在某张表中保留原先的数值,而不是重新手动输入,可以在Seed中这样写:
var Users = new List<Users> { new User{ UserID = 123, Name = "习骏", }; Users.ForEach(u => context.Users.Add(u));
创建完该类后,我们接下来要做的就是在我们的应用程序开始运行的时候能够自动重建数据库。要想实现该功能,我们必须到工程根目录下的Global.ascx文件中进行配置。
Global.ascx文件中定义了当前工程所使用到的Application主类,它包含了一个Application_Start()事件处理器,在我们的应用程序第一次运行的时候就会触发它里面的事件。
我们必须在该文件中添加以下的代码:
System.Data.Entity.Database.SetInitializer<StoreContext>(new UserIntializer());
这里必须指定Database的命名空间全称,就算我们正确的导入了它的命名空间也依然起不了作用,因为该方法是静态方法。