EF实体框架之CodeFirst三
前两篇博客学习了数据库映射和表映射,今天学习下数据库初始化、种子数据、EF执行sql以及执行存储过程这几个知识。
一、数据库初始化策略
数据库初始化有4种策略
策略一:数据库不存在时重新创建数据库
Database.SetInitializer<EFCodeFirstDbContext>(new CreateDatabaseIfNotExists<EFCodeFirstDbContext>());
策略二:每次启动应用程序时创建数据库
Database.SetInitializer<EFCodeFirstDbContext>(new DropCreateDatabaseAlways<EFCodeFirstDbContext>());
策略三:模型更改时重新创建数据库
Database.SetInitializer<EFCodeFirstDbContext>(new DropCreateDatabaseIfModelChanges<EFCodeFirstDbContext>());
策略四:从不创建数据库
Database.SetInitializer<EFCodeFirstDbContext>(null);
其中,在使用每次启动应用程序时创建数据库DropCreateDatabaseAlways时,总是报错:无法删除数据库XXX,因为该数据库当前正在使用,这个错误找了半天,在一篇帖子上写让选中数据库,右键删除,只选关闭连接复选框,之后就可以了,我也试了下,是可以的。
二、种子数据
对于新建的数据库,可能会有一些默认的数据来做测试或默认配置,这时可以使用种子类来初始化数据库数据。加入使用的是DropCreateDatabaseAlways策略,那么初始化器类就要从该泛型类继承,并传入数据库上下文作为类型参数。接下来,要种子化数据库就要重写DropCreateDatabaseAlways
类的Seed
方法,而Seed方法拿到了数据库上下文,因此我们可以使用它来将数据插入数据库:
using System; using System.Collections.Generic; using System.Data.Entity; using System.Linq; using System.Text; using System.Threading.Tasks; using EFCodeFirstModels; namespace EFCodeFirstDataAccess { public class SeedingDataInitializer: DropCreateDatabaseAlways<EFCodeFirstDbContext> { protected override void Seed(EFCodeFirstDbContext context) { Person person = new Person("0002","cuiyanwei",SexType.Female,26); Person person1 = new Person("0003", "cuiyanwei1", SexType.Female, 25); context.Persons.Add(person); context.Persons.Add(person1); base.Seed(context); } } }
上面的代码中并没有SaveChanges(),然后将将数据库初始化器类用于数据库上下文类
public EFCodeFirstDbContext() : base("MyStrConn") { Database.SetInitializer<EFCodeFirstDbContext>(new SeedingDataInitializer()); }
此时初始化种子,就不能在OnModelCreating中执行数据库初始化策略了。
Database.SetInitializer<EFCodeFirstDbContext>(new DropCreateDatabaseAlways<EFCodeFirstDbContext>());
三、执行SQL语句
有时候在code first中也会执行sql来做查询,或者是查询视图。
//using能及时释放资源,例如数据库连接异常,可以即使将上下文释放 using (var db=new EFCodeFirstDbContext()) { List<Person> persons= db.Database.SqlQuery<Person>("select * from Person where personId=@id",new SqlParameter("@id","0002")).ToList(); foreach (var person in persons) { Console.WriteLine("{0} {1} {2} {3}",person.PersonId,person.Name,person.Age,person.Sex); } } Console.ReadLine();
然后在数据库中建一个视图TestView,不过查询的还是Person,其实也可以查询部分字段,那样还要再创建Model,因为懒所以还是使用Person。此时我们就不能使用DropCreateDatabaseAlways策略模式了,这样的话数据的视图这些都会不存在。我们可以使用CreateDatabaseIfNotExists策略模式,初始化数据时只需把SeedingDataInitializer类继承自CreateDatabaseIfNotExists就OK了。
//using能及时释放资源,例如数据库连接异常,可以即使将上下文释放 using (var db=new EFCodeFirstDbContext()) { List<Person> persons= db.Database.SqlQuery<Person>("select * from TestView where personId=@id", new SqlParameter("@id","0002")).ToList(); foreach (var person in persons) { Console.WriteLine("{0} {1} {2} {3}",person.PersonId,person.Name,person.Age,person.Sex); } } Console.ReadLine();
四、执行存储过程
有时候使用sql能解决的问题使用ef就不那么简单,比如查找树的某个节点的所有父节点或所有子节点。如果使用存储过程那就会很容易,不过存储过程也有弊端,例如只能返回一个表,不能同时返回多个表,可能是有我没找到吧。
CREATE PROCEDURE TestProcedure @personId nvarchar(100) AS BEGIN select * from Person where PersonId=@personId; END GO
上面创建一个有一个参数的存储过程,来查询person。
List<Person> persons = db.Database.SqlQuery<Person>("TestProcedure @personId", new SqlParameter("@personId", "0003")).ToList(); foreach (var person in persons) { Console.WriteLine("{0} {1} {2} {3}",person.PersonId,person.Name,person.Age,person.Sex); }
上面的都是查询使用的都是SqlQuery,如果需要更新操作可以使用ExecuteSqlCommand方法。
int count= db.Database.ExecuteSqlCommand("update Person set Name=@name where PersonId=@personId",new[] { new SqlParameter("@name", "CYW"), new SqlParameter("@personId", "0003") }); Console.WriteLine(count);
从上面截图可以看到已经将personId=0003的Name改为CYW,之前都是cuiyanwei。
【本博客里有关于 EF实体框架之CodeFirs 系列的随笔都是摘自 作者:社会主义接班人 的博客 只作为学习笔记使用】
作者:社会主义接班人
出处:http://www.cnblogs.com/5ishare/
作者:社会主义接班人
出处:http://www.cnblogs.com/5ishare/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
如果文中有什么错误,欢迎指出。以免更多的人被误导。