EF的性能改善和思考
EF是个工具,用的好了性能就会很好,用的不好性能就会有很大损失。
先从EF的设计思想来讲解
EF的初衷是根据缓存中的实体对象,以及实体对象的状态(删除、更新、添加)来对数据库进行操作,这些实体对象、以及对象的状态都是在一个对象上下文ObjectContext中进行维护的,数据上下文DbContext显式实现了IObjectContextAdapter接口。DbContext在最后SaveChanges提交的时候,会调用ObjectContext的SaveChanges, 将所有更新保存到数据库并重置对象上下文中的更改跟踪。所以DbContext是对ObjectContext进行的二次封装和完善。
1.EF的初衷是好的,避免对数据库频繁的提交,先操作实体对象,直到实体对象不需要再更改了,最后提交的时候再将所有更新保存到数据库。但是凡事都是相对的,如果维护了大量的实体会使内存消耗很大,所以怎么办呢,应该尽量避免不必要的缓存实体,譬如纯粹的查询,EF在查询的时候可以使用AsNoTracking()避免将查询的实体或者实体序列放在缓存中,这在很大程度可以节省了内存。
2.EF鼓励将多个操作放在一个数据上下文中,所以有人说采用EF不需要DAL层了,可以直接在业务层包装using(DbContext=new DbContext()){},然后对数据库做各种表的操作,这个是没问题的,但是在开发中,这样做效率会很低,会写很多重复代码,举个简单的例子,假如一个条件查询,如果有DAL层的封装方法,我就可以在业务层方便的调用,避免每次都去想着怎么去组装条件进行查询,所以DAL层对于开发效率来说还是必要的,如果需要DAL层就要考虑数据仓储类的实现,数据仓储类该如何实现呢?
3.数据仓储类,数据仓储类封装了通用的针对数据库的单元操作方法,封装这些方法中应该避免使用using(DbContext=new DbContext()){}包装单元操作,EF的设计初衷是什么?避免频繁的与数据库进行交互,如果采用这种方式封装单元操作,一个单元操作使用一个数据上下文,那么EF的性能优势在哪里?另外采用这种方式封装,EF的“本地事务”也被破坏了,已经毫无”事务”可言,所以数据仓储类可以采用一个临时公用的数据上下文,比如你将数据上下文放在线程对象中,这里的事务我加了一个引号,因为EF在提交的时候根据对象上下文来更新数据库的,所以最后一次提交之前,实际上并没有和数据库交互,数据上下文提交的时候,会进行事务的封装,如果失败了,本次提交的所有操作回滚。
4.EF的初衷是想维护一个完整性的对象上下文,但是实际生产中很难做到,比如执行了一个sqlcommand更新了一个字段,但是对象上下文中的该属性没有被更新,所以也许会说,采用EF就避免使用sql进行操作了,但是Dbcontext留下了DataBase口子,public int ExecuteSqlCommand(string sql, params object[] parameters);留下了口子,就避免不了会被采用,所以更稳妥的做法是采用DbContextTransaction来控制事务,而不是单纯地依靠SaveChanges,另外如果采用了ExecuteSqlCommand,一旦破坏了数据对象的完整性,再进行更新操作的时候很可能会覆盖掉之前执行的操作,那么怎么办呢,解决办法有两个,1.根据字段进行更新,而不是更新整个实体2.将数据对象分离,重新附加,然后更新,很明显1的方法性能更好
5.如何Dispose掉Dbcontext?首先要清楚Dispose是干什么的,Dispose是为了释放资源,不是销毁对象,销毁对象是谁干的,销毁对象是GC干的,GC准备销毁对象的时候,会检查对象有么有析构函数,如果有会将这些对象升级暂不销毁,直到全部执行完析构,在下次回收的时候再销毁掉,可是Dbcontext没有析构函数,但是Dbcontext是对ObjectContext的二次封装和完善,ObjectContext实现了析构,所以如果Dbcontext没有显示的去Dispose,GC回收数据上下文对象的时候,会升级该对象,直到所有的析构执行完毕,在下次回收的时候再一并销毁掉。我们不知道垃圾回收的具体时间,但是显示的Dispose可以减少Dbcontext对象的生命周期。所以在应用程序中,我们可以在请求结束的最后,执行显示的Dispose,譬如对于mvc、webapi程序,可以在过滤器中,请求结束的时候执行Dispose操作,对于asp.net可以在basepage中进行Dispose操作。
//
// 摘要:
// 由可提供 System.Data.Entity.Infrastructure.IObjectContextAdapter.ObjectContext 实例的对象实现的接口。System.Data.Entity.DbContext
// 类实现此接口以提供对基础 ObjectContext 的访问。
public interface IObjectContextAdapter
{
//
// 摘要:
// 获取对象上下文。
//
// 返回结果:
// 对象上下文。
ObjectContext ObjectContext { get; }
}
//
// 摘要:
// DbContext 实例表示工作单元和存储库模式的组合,可用来查询数据库并将更改组合在一起,这些更改稍后将作为一个单元写回存储区中。DbContext 在概念上与
// ObjectContext 类似。
public class DbContext : IDisposable, IObjectContextAdapter
{
//
// 摘要:
// 将在此上下文中所做的所有更改保存到基础数据库。
//
// 返回结果:
// 已写入基础数据库的对象的数目。
public virtual int SaveChanges();
EF的性能改善和思考的更多相关文章
- 你是否还在质疑EF的性能
1. 写在前面的话 一直没有写博客的习惯,感觉太浪费时间,没有那么多精力,其实仔细一想,写博客是一种习惯,也是一种心境,同时也是对自己所掌握的知识结构的一个梳理过程,对自己知识体系的一个巩固,同时也是 ...
- C#实用杂记-EF全性能优化技巧
原文链接:http://www.makmong.com/947.html#comment-31 EntityFramework 优化建议 2016年1月15日 下午4:54 LEILINKANG ...
- 第八节: EF的性能篇(一) 之 EF自有方法的性能测试
一. 开发中常见的性能问题 我们在日常开发过程中,由于一些不好的习惯,经常会导致所写的代码性能低下,却毫无发觉,下面就总结一下常见的一些性能问题. 1. 真假分页 ① 假分页: db.xxx.toLi ...
- 第九节: EF的性能篇(二) 之 Z.EntityFramework.Extensions程序集解决EF的性能问题
一. 综述 该模块主要介绍:EF的性能优化插件Z.EntityFramework.Extensions,该插件收费. (一). 简介 1. 相关网站:http://www.zzzprojects.co ...
- MVC教程--MiniProfiler.EF监控调试MVC和EF的性能
上一篇谈到mvc中ef输出执行sql日志:来谈用mvc开发项目的调试和性能监控.EF框架自动给我生成sql语句,当我们的程序遇到性能问题的时候我们可以用MiniProfiler.EF来监控调试MVC和 ...
- try catch引发的性能优化深度思考
关键代码拆解成如下图所示(无关部分已省略): 起初我认为可能是这个 getRowDataItemNumberFormat 函数里面某些方法执行太慢,从 formatData.replace 到 une ...
- 讨论过后而引发对EF 6.x和EF Core查询缓存的思考
前言 最近将RabbitMQ正式封装引入到.NET Core 2.0项目当中,之前从未接触过是个高大上的东东跟着老大学习中,其中收获不少,本打算再看看RabbitMQ有时间写写,回来后和何镇汐大哥探讨 ...
- EF提高性能
实体框架 5 性能注意事项 作者:David Obando.Eric Dettinger 等 发布时间:2012 年 4 月 1.简介 对象关系映射框架是一种在面向对象的应用程序中提供数据访问抽象的便 ...
- 性能改善之For与Foreach
关于For与Foreach的区别,博客园里已经有好多这样文章了,都分析的挺好:http://www.cnblogs.com/jobs/archive/2004/07/17/25218.aspx 不过 ...
随机推荐
- dragdrop 修改版
<!DOCTYPE html> <html lang="en"> <head> <meta name="keywords&quo ...
- test for cvx library in matlab - windows
Download the zip file of cvx http://cvxr.com/cvx/download/ by downloading cvx-w64.zip Require a lice ...
- Java:对象的强、软、弱、虚引用
转自: http://zhangjunhd.blog.51cto.com/113473/53092 1.对象的强.软.弱和虚引用 在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无 ...
- iOS webView与H5的交互(返回页面的处理)
摘自:http://blog.csdn.net/qq_29284809/article/details/50548413 调用 H5页面的同名返回方法(必须保证名字一致)!!!
- java常见的开发工具
http://www.csdn.net/article/1970-01-01/2824723 http://zhidao.baidu.com/link?url=D8FdJxeFd-z-LV1OfZuZ ...
- anjularjs常用的内置方法
1.$apply anjularjs通过$apply方法去执行脏检查,及时告诉model绑定变量更新. 示例:定义一个date变量显示在页面上,它的控制器是firstCtrl,这个date变量有一个时 ...
- js 防止button频繁点击
<input type="button" class="test" title="Select" value="Select ...
- [转]SQL SERVER – Importance of Database Schemas in SQL Server
原文地址http://blog.sqlauthority.com/2009/09/07/sql-server-importance-of-database-schemas-in-sql-server/ ...
- lua unit test introduction
Unit Test Unit testing is about testing your code during development, not in production. Typically y ...
- 在html中引用分享的链接
怎么说呢,其实我自己本身也不是很懂,这些到网上一搜也是有很多详解的,我就是水水的来~~ 附带:smarty 的 tpl 里面 要直接写 javascript 或 style 要用 literal 标签 ...