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("","cuiyanwei",SexType.Female,);
Person person1 = new Person("", "cuiyanwei1", SexType.Female, );
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","")).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","")).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()
AS
BEGIN
select * from Person where PersonId=@personId;
END
GO
上面创建一个有一个参数的存储过程,来查询person。
List<Person> persons = db.Database.SqlQuery<Person>("TestProcedure @personId", new SqlParameter("@personId", "")).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", "") });
Console.WriteLine(count);

从上面截图可以看到已经将personId=0003的Name改为CYW,之前都是cuiyanwei。
EF实体框架之CodeFirst三的更多相关文章
- EF实体框架之CodeFirst四
在EF实体框架之CodeFirst二中也提到数据库里面一般包括表.列.约束.主外键.级联操作.实体关系(E-R图).存储过程.视图.锁.事务.数据库结构更新等.前面几篇博客把表.存储过程.视图这些算是 ...
- EF实体框架之CodeFirst一
对于SQL Server.MySql.Oracle等这些传统的数据库,基本都是关系型数据库,都是体现实体与实体之间的联系,在以前开发时,可能先根据需求设计数据库,然后在写Model和业务逻辑,对于Mo ...
- EF实体框架之CodeFirst五
上一博客学习了下基本的约定配置,留下几个遗漏的,这篇就是学习下遗漏一复杂类型. 一.什么是复杂类型? 书中说道:“复杂类型也可视作值类型(?)可以作为附加属性添加到其他类.复杂类型与实体类型的区别在于 ...
- EF实体框架之CodeFirst二
在codefirst一中也说了Mapping是实体与数据库的纽带,model通过Mapping映射到数据库,我们可以从数据库的角度来分析?首先是映射到数据库,这个是必须的.数据库里面一般包括表.列.约 ...
- EF实体框架之CodeFirst七
前面的6篇博客基本把Code First学习的差不多了,今天这篇学习下code first中的并发控制和事务,基本也快学完了,顶多就差数据迁移. 在数据库中也是有锁和事务的概念,在C#中也是存在,当然 ...
- EF实体框架之CodeFirst六
上午的时候把复杂类型学习了一下,想着趁着周六日把Code First学习完,所以下午还是把Code First中的关系学习下.在数据库中最重要的恐怕就是E-R图了,E-R体现了表与表直接的关系.使用C ...
- EF实体框架之CodeFirst八
前面七篇基本把Code First学习了一下,不过code first中会出现一个问题,就是数据迁移的问题. 一.数据准备 还是在前面的demo上修改,这次使用Province和City类. publ ...
- 【MVC 1】MVC+EF实体框架—原理解析
导读:在之前,我们学过了三层框架,即:UI.BLL.DAL.我们将页面显示.逻辑处理和数据访问进行分层,避免了一层.两层的混乱.而后,我们又在经典三层的基础上,应用设计模式:外观.抽象工厂+反射,使得 ...
- 【EF 1】EF实体框架 原理+实例
一.知识回顾 到目前为止,自己学到的链接数据库操作已经经历了几个阶段,分别是:学生信息管理和(第一次)机房收费时的直接连接数据库操作表格,然后是机房个人重构中应用的操作实体,在其中还利用了一个很重要的 ...
随机推荐
- 使用culr
使用curl在采集有语言要求的网站时,首先需要发送带有语言设置的请求,再发送你要的请求如: 注:vget(); 这里没提供: $url='http://www.hotels.com/?locale=e ...
- MyCat 学习笔记 第十一篇.数据分片 之 分片数据查询 ( select * from table_name limit 100000,100 )
1 环境说明 VM 模拟3台MYSQL 5.6 服务器 VM1 192.168.31.187:3307 VM2 192.168.31.212:3307 VM3 192.168.31.150: 330 ...
- Javascript中length属性的总结
Javascript中length属性的总结 一.StringObject中的length length属性是返回字符串的字符数目. 例如: // 普通字符串 var str = " ...
- 设计模式C#实现(三)——外观模式
外观模式——提供了一个统一的接口,用来访问子系统中的一群接口.外观定义了一个高层接口让子系统更容易使用. 一个外观包含了为许多对象和对他们的操作,使得重复这些操作更方便. 假如客厅里有灯(Lights ...
- ubuntu自带的gedit编辑器添加Markdown预览插件
gedit安装Markdown Preview Ubuntu自带的gedit编辑器也是有很强大的功能的,且支持插件的安装.对于喜欢用Markdown的我来说,这当然是很好的了,gedit本身 就支持M ...
- 技巧:利用 Workflow 显示附近的免费 Wi-Fi
得益于 Workflow 自 1.5.3 版本起更新的 Get Content of URL 动作,该 App 的潜力得到了极大的提升.本文分享一种有趣的用法,搜寻附近的免费 Wi-Fi 并择一显示在 ...
- runc的detach, console, tty等相关问题
runc 端解析: 1. runc/utils_linux.go func (r *runner) run(config *specs.Process) (int , error) 在该函数中第一次对 ...
- HDU 4445 Crazy Tank --枚举
题意: n个物体从高H处以相同角度抛下,有各自的初速度,下面[L1,R1]是敌方坦克的范围,[L2,R2]是友方坦克,问从某个角度抛出,在没有一个炮弹碰到友方坦克的情况下,最多的碰到敌方坦克的炮弹数. ...
- TopCoder SRM 633 Div.2 500 Jumping
题意:给一个点(x,y),给一些步长delta1,delta2...deltaN,问从(0,0)严格按照步长走完N步后能否正好到达(x,y)点. 解法:其实就是判断这些线段和(0,0)-(x,y)这条 ...
- ZOJ 1111 Poker Hands --复杂模拟
昨天晚上写的,写了一个多小时,9000+B,居然1A了,爽. 题意:玩扑克,比大小.规则如下: 题意很简单,看过赌神的人都知道,每人手中5张排,比牌面大小,牌面由大到小分别是(这里花色无大小),级别从 ...