zoukankan      html  css  js  c++  java
  • 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/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
    如果文中有什么错误,欢迎指出。以免更多的人被误导。
  • 相关阅读:
    预备作业03 20162308马平川
    预备作业02 20162308 马平川
    预备作业01
    采用dlopen、dlsym、dlclose加载动态链接库
    FastCGI协议分析
    Fastcgi协议定义解释与说明
    linux exec函数族
    进程通信---FIFO
    FTP协议及工作原理详解
    HTTP协议详解
  • 原文地址:https://www.cnblogs.com/NotEnough/p/6842484.html
Copyright © 2011-2022 走看看