深入浅出EF之ModelFirst和DBFirst
在上篇博文中,小编主要简单的介绍了一下EF的一些基础知识,其中,小编蜻蜓点水的提了一下ModelFirst和DBFirst,ModelFirst先设计实体,然后根据模型生成数据库,DBFirst根据数据库生成模型,两个方向都是可以了,两个方向可以相互更新,比如新添加了实体,可以根据模型生成数据库,如果在数据库里面新添加了字段,我们可以从数据库更新模型。在介绍ModelFirst和DBFirst之前,我们先来解决两个问题,EF与linq
to sql的关系以及为什么使用linq to sql和EF。
EF与linq to sql的关系
linq to sql 是微软ORM思想的一个具体化,EF也是它的一个具体化,那么,这两个产品有什么区别呢?Linq to Sql是ORM思想实现的一个轻量级的框架,EF是一个重量级框架;Linq to Sql和EF的一个重要的区别就是,Linq to Sql只能针对于SQL Server数据库,而EF可以针对于很多的数据库(Oracle,SQL Server等),也就是说EF是跨数据库的,不要小看这一点,在实际的开发中,非常的实用,举个简单的小例子,还记我们敲的VB.NET版本的机房收费系统么,其中涉及到了数据访问层,如果出于某种原因,我们换了数据库,那么,我们就需要重新编写数据访问层,如果我们在创机房收费系统这个项目的时候,使用了linq
to sql,更换了数据库linq to sql框架就需要重新进行大量的改动,如果使用了EF框架,那么我们只需要改动其中的配置文件就可以了,不需要修改程序中的代码。
为什么使用linq to sql和EF
这个问题,也关乎我们的D层,还记得敲机房收费系统的时候,我们会抽出来一个sqlhelper类,这个类实现了对数据库的增删改查,然后,我们的再创建相应的D层类,这些类方法的功能,其实都差不多,唯一不同的就是sql,从这里我们可以看到,我们的D层的问题,那就是,我们重复性的书写一些不必要的类或者方法,解决这个方法就需要慢慢的抽象,抽象出共有的东西,像:DataTable装换为实体集,操作数据库的几类方法(注意其参数),然后将其一整合,这个大致就是我们所属的ORM思想实现的雏形了,当然,上面所说的那些东西,Linq
to Sql或EF这些框架已经帮助我们实现了,我们只需要使用它们提供的方法就行了,从这里我们也可以看到,如果我们使用这些框架,我们程序员在编程的时候,几乎不需要管理D层的东西,只需要关注业务的实现就可以了。
接下来,小编就来简单的介绍一下ModelFirst,ModelFirst先设计实体,然后根据模型生成数据库,如下图所示,
我们可以再图中空白处右击添加实体,还可以新增标量属性,以及添加关联。接着,我们可以根据上面的实体生成数据库,如下图所示:
生成的代码如下所示:
<span style="font-size:18px;"><span style="font-size:18px;">-- -------------------------------------------------- -- Entity Designer DDL Script for SQL Server 2005, 2008, 2012 and Azure -- -------------------------------------------------- -- Date Created: 01/28/2015 15:43:19 -- Generated from EDMX file: C:\Users\Flower\Desktop\EFDemo\ModelFirstDemo\DataModel.edmx -- -------------------------------------------------- SET QUOTED_IDENTIFIER OFF; GO USE [ModelFirstDemoDb2]; GO IF SCHEMA_ID(N'dbo') IS NULL EXECUTE(N'CREATE SCHEMA [dbo]'); GO -- -------------------------------------------------- -- Dropping existing FOREIGN KEY constraints -- -------------------------------------------------- IF OBJECT_ID(N'[dbo].[FK_CustomerOrder]', 'F') IS NOT NULL ALTER TABLE [dbo].[Order] DROP CONSTRAINT [FK_CustomerOrder]; GO -- -------------------------------------------------- -- Dropping existing tables -- -------------------------------------------------- IF OBJECT_ID(N'[dbo].[Customer]', 'U') IS NOT NULL DROP TABLE [dbo].[Customer]; GO IF OBJECT_ID(N'[dbo].[Order]', 'U') IS NOT NULL DROP TABLE [dbo].[Order]; GO -- -------------------------------------------------- -- Creating all tables -- -------------------------------------------------- -- Creating table 'Customer' CREATE TABLE [dbo].[Customer] ( [Id] int IDENTITY(1,1) NOT NULL, [CusName] nvarchar(32) NULL, [SubTime] datetime NOT NULL, [DelFlag] smallint NULL ); GO -- Creating table 'Order' CREATE TABLE [dbo].[Order] ( [Id] int IDENTITY(1,1) NOT NULL, [OrderContent] nvarchar(max) NOT NULL, [CustomerId] int NOT NULL ); GO -- Creating table 'UserInfo' CREATE TABLE [dbo].[UserInfo] ( [Id] int IDENTITY(1,1) NOT NULL ); GO -- -------------------------------------------------- -- Creating all PRIMARY KEY constraints -- -------------------------------------------------- -- Creating primary key on [Id] in table 'Customer' ALTER TABLE [dbo].[Customer] ADD CONSTRAINT [PK_Customer] PRIMARY KEY CLUSTERED ([Id] ASC); GO -- Creating primary key on [Id] in table 'Order' ALTER TABLE [dbo].[Order] ADD CONSTRAINT [PK_Order] PRIMARY KEY CLUSTERED ([Id] ASC); GO -- Creating primary key on [Id] in table 'UserInfo' ALTER TABLE [dbo].[UserInfo] ADD CONSTRAINT [PK_UserInfo] PRIMARY KEY CLUSTERED ([Id] ASC); GO -- -------------------------------------------------- -- Creating all FOREIGN KEY constraints -- -------------------------------------------------- -- Creating foreign key on [CustomerId] in table 'Order' ALTER TABLE [dbo].[Order] ADD CONSTRAINT [FK_CustomerOrder] FOREIGN KEY ([CustomerId]) REFERENCES [dbo].[Customer] ([Id]) ON DELETE NO ACTION ON UPDATE NO ACTION; -- Creating non-clustered index for FOREIGN KEY 'FK_CustomerOrder' CREATE INDEX [IX_FK_CustomerOrder] ON [dbo].[Order] ([CustomerId]); GO -- -------------------------------------------------- -- Script has ended -- --------------------------------------------------</span></span>
接着我们来看一个具体的例子,ModelFirst关联实体的插入操作代码如下所示:
<span style="font-size:18px;"><span style="font-size:18px;">using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ModelFirstDemo { class Program { static void Main(string[] args) { DataModelContainer db = new DataModelContainer(); #region Model First 关联实体的插入操作 Customer customer = new Customer(); customer.CusName = "呵呵"; customer.DelFlag = 0; customer.SubTime = DateTime.Now; Order order = new Order(); order.OrderContent = "Flower"; //给导航属性赋值 //order.CustomerID= customer.ID; order.Customer = customer; Order order2 = new Order(); order2.OrderContent= "Flower2"; order.CustomerID= customer.ID; order2.Customer = customer; db.Customer.Add(customer); db.Order.Add(order); db.Order.Add(order2); db.SaveChanges(); #endregion } } }</span></span>
接着,我们来看一下DBFirst,根据数据库生成模型,我们具体来看下面一段代码:
<span style="font-size:18px;"><span style="font-size:18px;">using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data; namespace EF.EntityFrameworkDemo { class Program { static void Main(string[] args) { #region 添加实体 ////创建上下文对象 //DBFirstEntities dbFirst = new DBFirstEntities(); ////操作实体 //T_Customer customer = new T_Customer(); //customer.CusName = "新添用户"; ////附加在上下文 //dbFirst.T_Customer.AddObject(customer); ////保存 //dbFirst.SaveChanges(); #endregion #region 删除实体 ////1、创建上下文对象 //DBFirstEntities dbFirst = new DBFirstEntities(); ////2、创建实体 //T_Customer customer = new T_Customer(); //customer.ID = 9; ////3、将实体附加到上下文里面来进行管理 //dbFirst.T_Customer.Attach(customer); ////修改实体的状态 //dbFirst.ObjectStateManager.ChangeObjectState(customer, EntityState.Deleted); ////4、上下文操作数据库 //dbFirst.SaveChanges(); #endregion #region 修改实体 ////1、创建访问数据库的上下文对象 //DBFirstEntities dbFirst = new DBFirstEntities(); ////2、修改对象 //T_Customer customer = new T_Customer(); //customer.ID = 4; //customer.CusName = "用户4_修改后2"; ////3、附加到数据库 //dbFirst.T_Customer.AddObject(customer); ////修改对象状态 //dbFirst.ObjectStateManager.ChangeObjectState(customer, EntityState.Modified); ////4、上下文更新数据库 //dbFirst.SaveChanges(); #endregion #region 查询 DBFirstEntities dbFirst = new DBFirstEntities(); foreach (var item in dbFirst.T_Customer) { Console.WriteLine(string.Format("ID:{0} Name:{1}",item.ID,item.CusName)); } #region linq表达式 T_Customer cs = (from customer in dbFirst.T_Customer where customer.ID == 2 select customer).SingleOrDefault(); Console.WriteLine("ID:{0} Name:{1}",cs.ID,cs.CusName); #endregion #endregion Console.ReadKey(); } } } </span></span>
ModelFirst和DBFirst两种方式,都可以达到我们想要的效果,实现同样的目的,两个方法可以相互更新,最后小编简单的来介绍一下延迟加载,延迟加载也可以叫做按需加载,可以分两方面来理解,一方面指暂时不需要该数据,不用在当前马上加载,而可以推迟到使用它时再加载;另一方面指不确定是否将会需要该数据,所以暂时请不要加载,待确定需要后再加载它。延迟加载是一种很重要的数据访问特性,可以有效地减少与数据源的交互(注意,这里所提的交互不是指交互次数,而是指交互的数据量),从而提升程序性能。在EF中有两种延迟加载,具体代码如下所示:
<span style="font-size:18px;"><span style="font-size:18px;">using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ModelFirstDemo { class Program { static void Main(string[] args) { DataModelContainer db = new DataModelContainer(); #region Model First 关联实体的插入操作 Customer customer = new Customer(); customer.CusName = "呵呵"; customer.DelFlag = 0; customer.SubTime = DateTime.Now; Order order = new Order(); order.OrderContent = "Flower"; //给导航属性赋值 order.CustomerID= customer.ID; order.Customer = customer; Order order2 = new Order(); order2.OrderContent= "Flower2"; order.CustomerID= customer.ID; order2.Customer = customer; db.Customer.Add(customer); db.Order.Add(order); db.Order.Add(order2); db.SaveChanges(); #endregion #region 补充另外一个汇总查询方式:Lambda表达式 Lambda表达式和linq表达式在编译阶段之后生成的IL代码是一样的 var item = (from c in db.Customer where c.Id == 2 select c).FirstOrDefault(); List<string> list = new List<string>(); list.FindAll() Function<Customer,bool> lambda的方式 var itemLambda = db.Customer.Where<Customer>(c=>c.Id==1).FirstOrDefault(); Console.WriteLine(itemLambda.CusName); #endregion #region 延迟第一种 使用linq或者lambda表达式查出来的数据,只有使用的时候才回去真正的查询数据 var items = from c in db.Customer where c.Id < 10 select c; foreach (var customer in items) { Console.WriteLine(customer.Id); } IQueryable foreach (var customer in items) { Console.WriteLine(customer.Id); } #endregion #region 第二种延迟加载 var customers = from c in db.Customer select c; foreach(var cus in customers) { Console.WriteLine(cus.Id + "------"); foreach (var order in cus.Order) { Console.WriteLine(order.Id); } Console.WriteLine("------"); } #endregion #region 查询部分列的数据 只查询表中的部分列的数据 var items = from c in Customer where c.Id < 100 select new { id = c.Id, CusName = c.CusName, count = 0, orderCount = c.Order.Count() }; foreach (var item in items) { Console.WriteLine(item.CusName + "------" + item.orderCount); } #endregion #region IQuerable接口跟其他集合的区别 var items = (from c in db.Order where c.Id < 2 select c).ToList(); foreach (var order in items) { Console.WriteLine(order.Id); } #endregion Console.ReadKey(); } } } </span></span>
小编寄语:该博文,小编主要介绍了一些EF的基础知识,分别从三个大方面对EF进行详细介绍,第一个方面:EF与linq to sql的关系以及为什么要使用EF与linq to sql,第二方面,介绍了一下ModelFirst和DBFirst,最后介绍了一下延迟加载,对于EF的相关知识,小编刚刚接触,理解的还是很浅,有不同意见的小伙伴可以一起讨论交流哦,常常想,如果不是因为缘分,如果不是因为接受了项目什么mvc、EF、linq等,小编也没有这么快就开始接触,在接项目的过程中学习,再把学习到的知识运用到项目中,赶脚棒棒哒,档案管理项目,未完待续......
深入浅出EF之ModelFirst和DBFirst的更多相关文章
- EF下CodeFirst、DBFirst与ModelFirst分析
EF4.1有三种方式来进行数据操作及持久化.分别是Database-First,Model-First,Code-first:1.Database First是基于已存在的数据库,利用某些工具(如Vs ...
- 饮一盏Bug留香,唱一曲项目飞扬
沿途的风景 牵挂的项目 两情迢迢 学生档案管理项目在2月的末尾从稍带寒意的季节里完成了第一次迭代,验收的结果不尽善尽美,演示的功能也惨不忍睹,各种"关爱"的点评充斥耳旁 ...
- ASP.NET MVC深入浅出系列(持续更新) ORM系列之Entity FrameWork详解(持续更新) 第十六节:语法总结(3)(C#6.0和C#7.0新语法) 第三节:深度剖析各类数据结构(Array、List、Queue、Stack)及线程安全问题和yeild关键字 各种通讯连接方式 设计模式篇 第十二节: 总结Quartz.Net几种部署模式(IIS、Exe、服务部署【借
ASP.NET MVC深入浅出系列(持续更新) 一. ASP.NET体系 从事.Net开发以来,最先接触的Web开发框架是Asp.Net WebForm,该框架高度封装,为了隐藏Http的无状态模 ...
- .Net Core建站(2):EF Core+CodeFirst数据库迁移
上一篇的话,说了下怎么使用EF7 实现 CodeFirst去生成数据库, 其实还有好多问题的,这次一点一点的解决吧,都挺简单,不过零零散散的,, 1.读取配置文件,获得链接字符串 2.使用数据库进行增 ...
- 跟我一起学.NetCore之EF Core 实战入门,一看就会
前言 还记得当初学习数据库操作时,用ADO.NET一步一步地进行数据操作及查询,对于查询到的数据还得对其进行解析,然后封装返回给应用层:遇到这种重复而繁琐的工作,总有一些大神或团队对其进行封装,从而出 ...
- 使用.Net Core+EF7 CodeFirst(2)
上一篇的话,说了下怎么使用EF7 实现 CodeFirst去生成数据库, 其实还有好多问题的,这次一点一点的解决吧,都挺简单,不过零零散散的,, 1.读取配置文件,获得链接字符串 2.使用数据库进行增 ...
- ORM系列之Entity FrameWork详解
一. 谈情怀 从第一次接触开发到现在(2018年),大约有六年时间了,最初阶段连接数据库,使用的是[SQL语句+ADO.NET],那时候,什么存储过程.什么事务 统统不理解,生硬的将SQL语句传入SQ ...
- C# Note3:大话Ninject
前言 之所以研究Ninject,是因为初入职在开发XX项目的ComponentService部分时用到了它,一下子发现了它的强大.渐渐地发现在项目中,有时会用到优秀的第三方开源库,这些都是前人智慧的结 ...
- 细说ORM之Entity FrameWork系列(被替换)
一. 谈情怀 从第一次接触开发到现在(2018年),接近五年时间了,最初阶段连接数据库,使用的是[SQL语句+ADO.NET],那时候,什么存储过程.什么事务 统统不理解,生硬的将SQL语句传入SQL ...
随机推荐
- VC++6.0的使用方法
VC++6.0的最基本使用方法,创建一个c++项目工程可参考:https://jingyan.baidu.com/article/8ebacdf0cbdb5749f75cd54a.html 这里面的操 ...
- async/await,了解一下?
上一篇博客我们在现实使用和面试角度讲解了Promise(原文可参考<面向面试题和实际使用谈promise>),但是Promise 的方式虽然解决了 callback hell,但是这种方式 ...
- 毕业回馈-89C51之GPIO使用(流水灯)
今天分享一个89c51制作的8位流水灯案例.使用Proteus仿真. 同上一遍文章不同.上一篇文章中对于GPIO操作主要是位操作,即sbit led1=P0^0;其中P0^0代表p0.0这个引脚,然后 ...
- Server-U FTP与AD完美集成方案详解
最近咱有个任务,那就是把公司的文件服务器.FTP服务器.邮件服务器进行迁移并作相应的整合.登陆后台查看了,公司目前正在使用的方案.FTP服务器使用的是Server-u FTP,验证方式选择的windo ...
- SQL注入原理及绕过安全狗
1.什么是SQL注入攻击 SQL注入攻击指的是通过构造特殊的输入作为参数插入到Web表单的输入域或页面请求的查询字符串,欺骗服务器执行恶意的SQL命令 http://www.xxx.com/list. ...
- Ubuntu 搭建 GlusterFS 过程笔记
https://download.gluster.org/pub/gluster/ #要安装的东西 ---- ``` apt install -y build-essential gcc make c ...
- ftp传二进制文件时一定要用二进制模式,否则内容会有变化,造成后处理莫名其妙的错误,还以为传输前后内容一致,其实已变化。
ftp传二进制文件时一定要用二进制模式,否则内容会有变化,造成后处理莫名其妙的错误,还以为传输前后内容一致,其实已变化.
- Node.js 控制台
稳定性: 4 - 冻结 {Object} 用于打印输出字符到 stdout 和 stderr.和多数浏览器提供的 console 对象函数一样,Node 也是输出到 stdout 和 stderr. ...
- Android Support库——support annotations
Android Support库是官方出的支持扩展库,包含了丰富的组件.工具类等,通过在Android SDK Manager中勾选以下两项来获取到. 其中,Android Support Libra ...
- SimpleDateFormat中parse和format的区别
parse()返回的是一个Date类型数据,format返回的是一个StringBuffer类型的数据 //SimpleDateFormat中的parse方法可以 //把String型的字符串转换成特 ...