ado.net EF作为微软的一个ORM框架,通过实体、关系型数据库表之间的映射,使开发人员可以通过操作表实体而间接的操作数据库,大大的提高了开发效率。
这样一来,.net平台下,我们与底层数据库的交互就有两种选择了(这句话说得不是很准确,微软.net 框架下还是有其他的ORM框架的,,如Nhibernate):ado.net EF、ado.net 。

你可能以为我上面的内容写错了,ado.net EF 、ado.net 两者怎么都带有一个ado.net呢?

OK,如果你有这样的疑问的话,那么我们就有必要来了解一下.net的一些基本知识了

(1).net: 最核心的基础平台(可以看做运行环境和巨多类库),仅次于操作系统
(2)asp.net: .net平台下进行网站开发的框架
(3)asp.net MVC:asp.net 框架下开发网页的一种框架
(4)ado.net: .net平台下访问数据库的框架,他提供了一些列的访问数据库的类库
(5)ado.net EF: ado.net框架下访问数据库的最新最强大的ORM
(6)ORM: 把数据库映射为实体类的技术
(7)NHibemate: .net平台内访问数据库的一种可选ORM,从Java转换而来
以上仅仅是个人见解,不代表官方说法。

上面只是对ado.net 和ado.net EF两者进行了简单了解,下面我们再对两者进行一个具体的比较学习

(1)ado.net 做为原装的直接跟数据库打交道,直接操作数据库,没有进行额外的封装。比如我们可以直接执行sql语句,直接调用存储过程。直接操作DataSet数据集等等数据。
(2)EF 是ORM思想的付诸于实践,它对ado.net进行了封装,对数据表进行了映射处理,以对象的形式展现在开发人员面前。开发人员可以利用Linq语句的优势来执行增、改、查。但是最终的操作都是要转换成SQL语句来执行。比如:

From a in Context.Student
Where a.id =
Select a;

真正执行的时候会转换成 SQL " Select * from Student Where id=1"。
 EF让我们可以用面向对象的思想来编写程序,把注意力集中在系统中的业务环节。但是由于他要进行一次SQL语句的转换,所以相对于原始的ADO.NET来说,EF由于进行了封装,所以性能相对ADO.NET来说差一点点。不过EF也在不断的优化和改进中。 当然,EF也可以直接执行SQL语句和存储过程。有人会问,那为什么不直接执行SQL语句呢,回答是,直接执行的话要EF有什么用呢,EF就是在推行以面向对象编程的思想来处理业务。

OK,上面对两者进行了简单的比较,既然微软对ado.net 进行封装推出EF,那说明EF相对于原始的ado.net还是有优势的呢,那具体有哪些呢?

EF相对于ado.net 的优点
(1)开发效率高,开发人员完全可以根据面向对象的思维进行软件的开发
(2)可以使用三种设计模式中的ModelFirst来设计数据库,而且比较直观
(3)可以跨数据库,只需要在配置文件中修改连接字符串
(4)与vs结合的比较好
缺点:性能上赶不上原生的ado.net (因为他中间还有一个生成sql脚本的过程)

上面的缺点也暴露了一个问题:ado.net EF替代ado.net 。

那有没有折中一点的方案,两者都使用呢?

答案是肯定的,我们可以在EF中使用sql语句,参数化查询和存储过程。那具体如何使用?

ExecuteSqlCommand与SqlQuery

在数据上下文DBModel的实例中有个Database属性,其中有两组方法.ExecuteSqlCommand()和.SqlQuery()。它们都可以执行SQL语句,只不过.ExecuteSqlCommand()是不返回结果的,只返回受影响的行数,所以.ExecuteSqlCommand()更适合执行创建、更新、删除操作。.SqlQuery()则会返回查询到的结果,并将结果保存在数据实体中,所以更适合执行查询操作。

使用.ExecuteSqlCommand()实现创建、更新、删除

.ExecuteSqlCommand()的使用方法也很简单,直接传入SQL语句就可以了,执行完成后会返回受影响的行数。

using (var db = new DBModel()) //创建数据库上下文
{
//同步的方式执行SQL,并返回受影响的行数
int result = db.Database.ExecuteSqlCommand(@"CREATE TABLE `test`.`test` (
`id` INT NOT NULL,
PRIMARY KEY(`id`)); ");
//使用SqlParameter传值可以避免SQL注入
var p_name = new SqlParameter("@name", "萝莉");
var p_age = new SqlParameter("@age", );
//如果使用的是MySql数据库 需要SqlParameter把替换为MySqlParameter
//var p_name = new MySqlParameter("@name", "萝莉");
//var p_age = new MySqlParameter("@age", 13);
//更改学生年龄
result = db.Database.ExecuteSqlCommand(@"UPDATE `test`.`student`
SET `age` = @age
WHERE `name` = @name;", p_age, p_name);
//异步的方式执行SQL,并返回受影响的行数
Task<int> result2 = db.Database.ExecuteSqlCommandAsync("DROP TABLE `test`.`test`;");
}

PS:如果需要创建或删除当前数据库,Database属性中还存在.Create() 和.Delete()方法,它们不接受参数,返回一个bool值表示执行成功或失败。

使用.SqlQuery()查询数据

从名字就看的出来.SqlQuery()是用来执行查询的。.SqlQuery()使用前需指定返回值的数据类型,比如我查询寻一条学生的完整信息,类型就可以指定为student类型。如果是统计有多少个学生,返回值是个整数,就以设置为int。

注意:不仅返回值的个数必须与传入类型中属性值的个数相同,而且名称还必须一样,不然会出错。那么如果我只想获取姓名和年龄,那就得单独定义一个类(其中包含一个string类型的name和int类型的age),来保存数据了。

 
class temp
{
public string name { get; set; }
public int age { get; set; }
}
static void Main(string[] args)
{
using (var db = new DBModel()) //创建数据库上下文
{
//查询叫萝莉的学生信息,并指定返回值类型为student
DbRawSqlQuery<student> result1 = db.Database.SqlQuery<student>("SELECT * FROM test.student WHERE name = '萝莉'");
//也可以这样指定返回值类型
//DbRawSqlQuery result1 = db.Database.SqlQuery(typeof(student), "SELECT * FROM test.student WHERE name = '萝莉'");
Console.WriteLine(result1.FirstOrDefault().name); //打印姓名
DbRawSqlQuery<int> result2 = db.Database.SqlQuery<int>("SELECT count(*) FROM test.student");
Console.WriteLine(result2.FirstOrDefault()); //打印有多少学生
//只查询学生的年龄与姓名
var result3 = db.Database.SqlQuery<temp>("SELECT `name`,`age` FROM test.student;");
foreach (temp item in result3)
{
Console.WriteLine(item.name + ":" + item.age);
}
}

使用DbSet<T>下的.SqlQuery()

在每个数据实体集合DbSet<T>下也有一个.SqlQuery(),功能与上面介绍的一样,只不过DbSet<T>下的.SqlQuery()只能返回DbSet<T>中包含的类型。但DbSet<T>下的.SqlQuery()在返回数据的同时还会让数据库上下文(DBModel)跟踪返回数据的状态,如果返回的数据发生了修改,就可以使用.SaveChanges()将结果直接保存回数据库。而.Database.SqlQuery()查出的结果则是做不到的。

using (var db = new DBModel()) //创建数据库上下文
{
//查询叫萝莉的学生信息,并修改她的年龄
student result1 = db.students.SqlQuery("SELECT * FROM test.student WHERE name = '萝莉'").FirstOrDefault();
result1.age = ; //通过实体集合下.SqlQuery查询到的数据,修改之后是可以保存到数据库的
student result2 = db.Database.SqlQuery<student>("SELECT * FROM test.student WHERE name = '旺财'").FirstOrDefault();
result2.age = ; //因为使用的是.Database.SqlQuery查询到的,所以这里的修改不会保存到数据库
//如果希望.Database.SqlQuery下查出的数据在修改后也能保存到数据库
student result3 = db.Database.SqlQuery<student>("SELECT * FROM test.student WHERE name = '小明'").FirstOrDefault();
result3.age = ;
db.Entry<student>(result3).State = System.Data.Entity.EntityState.Modified; //通知数据上下文,这条记录也被修改了
db.SaveChanges();
}

Ado.net和EF的区别的更多相关文章

  1. ADO,OLEDB,ODBC,DAO的区别【转】

    转载:http://blog.csdn.net/sunboy_2050/article/details/6624684 ODBC(Open Database Connectivity,开放数据库互连) ...

  2. 【转载】ADO,OLEDB,ODBC,DAO的区别

    原文:ADO,OLEDB,ODBC,DAO的区别 ODBC(Open Database Connectivity,开放数据库互连) 1992年,微软公司开放服务结构(WOSA,Windows Open ...

  3. ADO,OLEDB,ODBC,DAO的区别

    ADO NET OLEDB ODBC连接数据库的区别 http://www.doc88.com/p-976312043296.html http://blog.csdn.net/ithomer/art ...

  4. 转:ADO,OLEDB,ODBC,DAO的区别

    ODBC(Open Database Connectivity,开放数据库互连) 1992年,微软公司开放服务结构(WOSA,Windows Open Services Architecture)中有 ...

  5. 数据库连接 ADO,OLEDB,ODBC,DAO的区别 转载

    http://blog.csdn.net/ithomer/article/details/6624684 ODBC(Open Database Connectivity,开放数据库互连) 1992年, ...

  6. ps -aux ,ps aux ,ps -ef 的区别

    Linux中的ps命令是Process Status的缩写.ps命令用来列出系统中当前运行的那些进程.ps命令列出的是当前那些进程的快照,就是执行ps命令的那个时刻的那些进程,如果想要动态的显示进程信 ...

  7. 有关linqtosql和EF的区别

    LINQ to SQL和Entity Framework都是一种包含LINQ功能的对象关系映射技术.他们之间的本质区别在于EF对数据库架构和我们查询的类型实行了更好的解耦.使用EF,我们查询的对象不再 ...

  8. 存储过程分页 Ado.Net分页 EF分页 满足90%以上

    存储过程分页: create proc PR_PagerDataByTop @pageIndex int, @pageSize int, @count int out as select top(@p ...

  9. ps aux和ps -ef命令区别

      ps aux 是用BSD的格式来显示 java这个进程 显示的项目有:USER,PID,%CPU,%MEM,VSZ,RSS,TTY,STAT,START,TIME,COMMAND   ps -ef ...

随机推荐

  1. springboot 初始化 web 项目 启动报错。。。一直解决不了

    1. 一个简单的SpringBoot项目,启动时报错信息: ERROR 18688 --- [cat-startStop-1] org.apache.catalina.core.ContainerBa ...

  2. 学习Acegi应用到实际项目中(4)

    此节介绍:ConcurrentSessionFilter. 在Acegi 1.x版本中,控制并发HttpSession和Remember-Me认证服务不能够同时启用,它们之间存在冲突问题. 在一些应用 ...

  3. 前端vue框架 父组件与子组件之间的相互调用

    子组件调用父组件东西: 1.在父组件与子组件契合的标签的的template模板中绑定 v-bind:自定义一个名字=“要调用的名字” 2.在子组件的script中props:["自定义的名字 ...

  4. 带权单源最短路发[稠密图](Dijkstra)

    对于稠密图,采用邻接矩阵较为合适 所以我们先构建一个邻接矩阵 typedef int Vertex; typedef int WeightType; //图 typedef struct MyGrap ...

  5. rand_1tom 产生 rand_1ton

    给定一个等概率随机产生1~M的随机函数rand1ToM如下: public int rand1ToM(int m) { return (int) (Math.random() * m) + 1; } ...

  6. 第二十三节:Java语言基础-详细讲解函数与数组

    函数 函数在Java中称为方法,在其他语言中可能称为函数,函数,方法就是定义在类中具有特定功能的程序.函数,在Java中可称为方法. 函数的格式: 修饰符 返回值类型 函数名(参数类型 参数1, 参数 ...

  7. Java学习笔记35(异常)

    代码在运行中发生的问题就是异常 java中把多种异常封装多个类,当程序出现问题时候,就会创建异常类对象并且抛出相关信息 异常体系: Throwable类是Java中所有错误或异常的父类 Throwab ...

  8. 1,rocketmq 的原理与安装教程

    参考文档 http://blog.csdn.net/a19881029/article/details/34446629 https://github.com/alibaba/RocketMQ htt ...

  9. 用vue-cli脚手架搭建一个仿网易云音乐的全家桶vue项目

    一,vue-cli环境搭建 1,全局安装webpack npm install webpack -g 2,安装vue脚手架 npm install vue-cli -g 3,新建一个新的project ...

  10. 程序性能调优工具之gprob

    1 简介改进应用程序的性能是一项非常耗时耗力的工作,但是究竟程序中是哪些函数消耗掉了大部分执行时间,这通常都不是非常明显的.GNU 编译器工具包所提供了一种剖析工具 GNU profiler(gpro ...