C# EF优化
原文:https://www.cnblogs.com/wangyuliang/p/10338902.html
https://www.cnblogs.com/simadi/p/6879366.html
现在工作中很少使用原生的sql了,大多数的时候都在使用EF。刚开始的时候,只是在注重功能的实现,最近一段时间在做服务端接口开发。开发的时候也是像之前一样,键盘噼里啪啦的一顿敲,接口秒秒钟上线,但是到联调测试的时候就悲剧了。。。。那叫一个慢啊,客户端有种“千年等一回的赶脚” 。由于访问量和数量都提升了一个数量级,之前没有 考虑过的问题,都在此时暴露了,根据自己百度、google的经历实践,整理了这一些优化点。欢迎各位大神批评指正!
1.使用AsNoTracking(),无跟踪查询,查询出的数据不可以修改,但是可以提高查询速度
对于只读操作,强烈建议使用AsNoTracking进行数据获取,这样省去了访问EF Context的时间,会大大降低数据获取所需的时间。
同时由于没有受到上下文的跟踪缓存,因此取得的数据也是及时最新的,更利于某些对数据及时性要求高的数据查询。
db.Person.Where(a => a.IsDeleted == false).AsNoTracking().ToList();
2.合理使用延迟加载。
如果用不到导航属性中的数据,那么使用懒加载就行了,不会加载不需要的数据到内存中。但是,如果会在 foreach 中使用导航属性中的数据,那么最好是禁用懒加载,通过Include()方法,一次加载全部数据,防止在 foreach 多次和数据库进行交互。当然,一般情况下是这样的,具体的还是要根据当时的业务情况而定。
3.判断List中是否含有数据的时候,最好使用Any(),避免使用Count()>0,这么Low的方式,真是慢的一逼啊。
4.在where子句中进行中文字符模糊匹配值的时候,记得加上使用DbFunctions.AsNonUnicode("要匹配的字符")。
var query = db.User.Where(a=>a.Name=="makmong").ToList();
修改后:var query = db.User.Where(a=>a.Name== DbFunctions.AsNonUnicode("makmong")).ToList();
5.错误的使用OrderBy() 导致的错误排序。
要对多个字段进行先后组合排序的时候,正确的是Orderby().ThenBy();切记不要这样啊:OrderBy().OrderBy(),这样达不到你想要的效果,只会按照最后的那个排序字段进行排序。
6.真假分页的问题
line1:query.ToList().Skip((PageIndex - 1) * PageSize).Take(PageSize); line2: query.Skip((PageIndex - 1) * PageSize).Take(PageSize).ToList();
line1就是加分页,直接从DB中取出全部的数据,然后在内存中进行分页;line2才是真正分页。没有ToList()的时候,返回值类型还是IQueryable<T> ,执行了ToList(),之后直接查询数据库了,返回值类型直接是IEnumerable<T>。
7.按需加载部分列。
建议使用ViewModel代替实体Model
接着新建ViewModel
public class UserViewModel
{
public int Id { get; set; }
public string Name { get; set; }
}
开始查询:
var query = db.User.Select(a=>new UserViewModel()
{
Id = a.Id,
Name = a.Name
}).ToList();
Model实体中枚举使用byte类型
我们先来了解下Sqlserver中tinyint, smallint, int, bigint的区别
bigint:从-263(-9223372036854775808)到263-1(9223372036854775807)的整型数据,存储大小为 8 个字节。一个字节就是8位,那么bigint就有64位
int:从-231(-2,147,483,648)到231-1(2,147,483,647)的整型数据,存储大小为 4 个字节。int类型,最大可以存储32位的数据
smallint:从-215(-32,768)到215-1(32,767)的整数数据,存储大小为 2 个字节。smallint就是有16位
tinyint:从0到255的整数数据,存储大小为 1 字节。tinyint就有8位。
所以对于有些范围比较短的数值长度,例如枚举类型值,完全可以使用byte类型替换int类型,对应生成数据库tinyint类型以节省数据存储。
如:
public CouponType CouponType { get; set; }
public enum CouponType : byte
{
RedBag = 0,
Experience = 1,
Cash = 2,
JiaXiQuan = 3
}
8.使用扩展库Entity Framework Extendeds 进行批量Insert和delete操作,避免生成大量的sql语句和数据库进行多次交互。
Nuget****安装 PM> Install-Package EntityFramework.Extended
9.这些做了,性能还是不行?那SqlQuery(),或者通过储存过程,将多条sql语句作为一个提交单元,也可以减少与数据库的交互次数,从而提高性能。
对于EF首次启动慢的问题,可通过下面的措施进行优化:
1.EF的预热问题,在应用程序进行初始化的时候就事先进行预热。比如,mvc应用程序可在global文件中添加如下操作。

protected void Application_Start()
{
using (var ctx = new mcccEntities())
{
var objectContext = ((IObjectContextAdapter)ctx).ObjectContext;
var mappingCollection = (StorageMappingItemCollection)objectContext.MetadataWorkspace.GetItemCollection(DataSpace.CSSpace);
mappingCollection.GenerateViews(new List<EdmSchemaError>());
} //记得,连接了几个DB就要写几个using啦。 }

EF使用SQL分库操作
当数据库的表及数据达到一定规模后我们想到的优化就有分库,分表之类的优化操作。
对于之前的ADO.NET来说分库是一件很普通的操作。
比如下面的非跨数据库查询语句:
SELECT Name FROM dbo.User WHERE ID=1
跨数据库查询语句:
SELECT Name FROM MaiMangAdb.dbo.blog_PostBody WHERE ID=1
我们知道EF的DbContext中已经指定了连接字符串
public EntityDB() : base("DefaultConnection")
<connectionStrings>
<add name="DefaultConnection" connectionString="Data Source=.;Initial Catalog=EFStudy;Integrated Security=True;" providerName="System.Data.SqlClient" />
</connectionStrings>
也就是说所有的上下文操作都是基于这个数据库来操作的,那我们就不能用ADO.NET那套,多个查询配多个链接去操作数据库。
当然大神们也给出了一套方法,而且也是简单明了。那我也就直接将其移植过来记录一下吧。
方法就是给数据库添加SYNONYM 同义词,我在此演示下
创建2张Model表User和Role
public class User
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public bool IsDeleted { get; set; }
[DateTime2Precision]
public DateTime CreateDateTime { get; set; }
}
public class Role
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
}
并添加一条语句:
EntityDB db = new EntityDB();
db.User.Add(new User { Id = 1, Name = "ddd" ,CreateDateTime = DateTime.Now});
db.Role.Add(new Role() {Id = 1, Name = "admin"});
db.SaveChanges();
运行查看数据库:
现在数据库表及内容都有了。然后我要把User表及内容移植到另一个数据库中,且不影响当前的EF操作。
创建新的数据库EFSYNONYM并添加User表,表结构和EFStudy中的User一致。
然后在EFStudy中删除表User且创建同义词
CREATE SYNONYM [dbo].[Users] FOR [EFSYNONYM].[dbo].[Users]
此时的User和Role已经分别存在于不同的数据库里面,我们来插入查询数据操作下
至此分库成功。当然此方法也有个缺点就是分库表和主表间由同义词关联而无法建立主外键关系(其实当数据量达到一定级别后联合join查询反而不如分开多次查询来得快,
且由于在同一个上下文中,不用太过于关心由数据多次连接开关而产生影响,凡事有利弊总得有个最优是吧),因此我们可以把一些独立的容易过期的数据表给移植到单独的数据库,利于管理同时也利于优化查询。
C# EF优化的更多相关文章
- 记录一次EF优化
问题描述:1.第一次加载过慢(EntityFramework 6 code-first).2.一段时间间不访问页面同样变慢. 原因分析:1.第一次启动(Code First)会对比程序中的Model与 ...
- EF优化之启动预热
为什么Entity Framework的初始化速度慢如蜗牛呢? 对于在应用程序中定义的每个DbContext类型,在首次使用时,Entity Framework都会根据数据库中的信息在内存生成一个映射 ...
- SQL&EF优化第一篇 各种情况下的性能测试之count函数篇
测试环境 mssql 08 +win7 数据 30W条 二〇一六年十月二十九日 09:04:43 结论:1>主键> *>可空列 推测未论证: 根据情况优先选择 顺便提 ...
- 优化EF Code First第一次请求速度
由于EF Code First模式没有模型文件,所以很多一次请求的时候速度比较慢,EF需要将对应的数据库映射关系加载到内存里面,往后请求就比较快.可以通过在程序初始化的时候增加一段代码来优化EF第一次 ...
- EntityFramework使用及优化
1. 简介 ORM框架:Object Relation Mapping,用操作对象的方式来操作数据库 其它框架:Dapper.NHibernate,首推EF,微软官方的. EF底层还是ADO.NET实 ...
- EntityFramework中对象的状态管理(笔记)
刚开始接触EF框架的时候总是不明白: 为什么查询出来的对象 Remove().再 SaveChanges()就会把数据删除.而自己 new 一个Person()对象,然后 Remove()不行? 为什 ...
- 如鹏网学习笔记(十五)ASP.NET MVC核心基础笔记
一.ASP.Net MVC简介 1,什么是ASP.NET MVC? HttpHandler是ASP.net的底层机制,如果直接使用HttpHandler进行开发难度比较大.工作量大.因此提供了ASP. ...
- 数据迁移最快方式,多线程并行执行 Sql插入
前言: 由于系统升级,新开发的系统对数据验证,及数据关联做了很多优化,现需要将原历史版本的数据迁移到新系统中:原数据库大约有 1千多万数据,大约 50个表. 历史数据库命名为:A. 新系统库暂命名为 ...
- EntityFramework介绍
首先我们说明一下ORM是什么. 微软官方提供的ORM工具,ORM让开发人员节省数据库访问的代码时间,将更多的时间放到业务逻辑层代码上.开发人员使用Linq语言,对数据库操作如同操作Object对象 一 ...
随机推荐
- TweenMax的GSAP(GreenSock动画平台)GSAP,专业的Web动画库
很好奇红框框里面的内容是什么,于是点了进去,又百度了下这个英文缩写具体指的什么东西. GSAP的全名是GreenSock Animation Platform,是一个从flash时代一直发展到今天的专 ...
- Java使用google身份验证器实现动态口令验证
参考: 1)https://www.jb51.net/article/121243.htm 2)https://www.cnblogs.com/wuaili/p/9810661.html
- PHP超大文件上传与下载
前段时间做视频上传业务,通过网页上传视频到服务器. 视频大小 小则几十M,大则 1G+,以一般的HTTP请求发送数据的方式的话,会遇到的问题:1,文件过大,超出服务端的请求大小限制:2,请求时间过长, ...
- JSP XML数据处理
JSP XML数据处理 当通过HTTP发送XML数据时,就有必要使用JSP来处理传入和流出的XML文档了,比如RSS文档.作为一个XML文档,它仅仅只是一堆文本而已,使用JSP创建XML文档并不比创建 ...
- All men are brothers
All men are brothers 牛客多校第九场E 给定n个人,起初互不认识 然后m各阶段 每个阶段有两个人x.y认识 求每个阶段选出四个人互不认识的方式 并查集 #include<bi ...
- 2018-2019-2 20175214 实验三《敏捷开发与XP实践》实验报告
一.实验内容 1.编码标准:在IDEA中使用工具(Code->Reformate Code)把下面代码重新格式化,再研究一下Code菜单,找出一项让自己感觉最好用的功能.提交截图,加上自己学号水 ...
- HTML To Word
一.源码特点 1.在一些实际的应用场景中,有用户需要将一批规范的资料网页保存为WORD文档以便离线传阅或用于其它需求.在此之前,使用了OFFICE组件来尝试完成此功能需求,但是效果都不尽如 ...
- Hypermesh中弹簧单元设置
1D >> springs 单元类型 CBUSH1D 单元属性 PBUSH1D
- mysql 无法存储表情字符 java.sql.SQLException: Incorrect string value: '\xF0\x9F\x90\xBE",...' for column 'XXXX' at row 1
1.变更字段类型 ALTER TABLE api_log MODIFY COLUMN remark longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_uni ...
- js常用的几种类型检测方式
类型检测方式 平时数据类型都是清晰明了的,但有些功能函数还是需要用到类型检测,现总结一下几种常见的类型检测方式: typeof instanceof Object.prototype.toString ...