第八节: EF的性能篇(一) 之 EF自有方法的性能测试

一. 开发中常见的性能问题

   我们在日常开发过程中,由于一些不好的习惯,经常会导致所写的代码性能低下,却毫无发觉,下面就总结一下常见的一些性能问题。

1. 真假分页

  ① 假分页: db.xxx.toList().Skip(2).take(4) 。

   ② 真分页:db.xxx.Skip(2).take(3).toList() 。

2. 合理的使用EF的数据加载方式

   EF的加载方式有:立即加载、延迟加载、显示加载。

  详见:

    ①: 第五节: EF高级属性(一) 之 本地缓存、立即加载、延迟加载(不含导航属性)

    ②: 第六节: EF高级属性(二) 之延迟加载、立即加载、显示加载(含导航属性)

3. NoTracking的使用

   EF查询出来的实体,默认是跟踪状态的,如果查询出来的实体不需要修改或者删除,查询的时候可以删除状态跟踪,变为Detached状态,来提高性能。

    关于EF状态的跟踪,详见后面章节,敬请期待!!

1     using (DbContext context = new MyDbContext())
2     { 
3          var people = context.Student.Where(p => p.Id > 2).AsNoTracking().ToList();
4     }

4. 合理的使用SQL事务

  将与事务无关的一些SQL语句放到事务外,如果一个事务中的SQL语句过长,很容易出现死锁问题,压力测试时,出现资源被锁的错误。

二. 关于EF数据操作的性能问题

   EF自诞生以来,大批量的操作增加、删除、修改操作数据效率一直很低,1000条数据以内,效率尚且可以接受(10s内),但随着数据量逐渐增大,很容易在执行的过程中就宕机了,相当尴尬。在本章节,我们一起来测试一下,EF在不进行任何优化的情况下,几种写法的效率问题。

  我们这里的测试是以增加数据为例,先把测试的三种写法的结论贴上。

1. 每添加1条数据,savechange一下(小白常犯的错误,坚决抵制这种做法!!)

 1      private static void NewMethod1(DbContext db)
 2         {
 3             Console.WriteLine("-------------1. 每添加1条数据,savechange一下(小白常犯的错误,坚决抵制这种做法!!)-------------------");
 4             Stopwatch watch = Stopwatch.StartNew();
 5             for (int i = 0; i < 1000; i++)
 6             {
 7                 TestOne t = new TestOne();
 8                 t.id = Guid.NewGuid().ToString("N");
 9                 t.t1 = "t1+" + i;
10                 t.t1 = "t2+" + i;
11                 db.Set<TestOne>().Add(t);
12                 db.SaveChanges();
13             }
14             watch.Stop();
15             Console.WriteLine("1000条数据耗时:{0}", watch.ElapsedMilliseconds);
16         }

2. 先将所有数据添加到内存里,最后再savechange

 1  private static void NewMethod2(DbContext db, int count)
 2         {
 3             Console.WriteLine("-------------2. 先将所有数据添加到内存里,最后再savechange-------------------");
 4             Stopwatch watch = Stopwatch.StartNew();
 5             for (int i = 0; i < count; i++)
 6             {
 7                 TestOne t = new TestOne();
 8                 t.id = Guid.NewGuid().ToString("N");
 9                 t.t1 = "t1+" + i;
10                 t.t1 = "t2+" + i;
11                 db.Set<TestOne>().Add(t);
12             }
13             db.SaveChanges();
14             watch.Stop();
15             Console.WriteLine("{0}条数据耗时:{1}", count, watch.ElapsedMilliseconds);
16         }

3. 使用addRange方法,先将数据加到list集合中,然后一次性通过addRange加到内存里

 1      private static void NewMethod3(DbContext db, int count)
 2         {
 3             Console.WriteLine("-------------3. 使用addRange方法,先将数据加到list集合中,然后一次性通过addRange加到内存里-------------------");
 4             Stopwatch watch = Stopwatch.StartNew();
 5             List<TestOne> tList = new List<TestOne>();
 6             for (int i = 0; i < count; i++)
 7             {
 8                 TestOne t = new TestOne();
 9                 t.id = Guid.NewGuid().ToString("N");
10                 t.t1 = "t1+" + i;
11                 t.t1 = "t2+" + i;
12                 tList.Add(t);
13             }
14             db.Set<TestOne>().AddRange(tList);
15             db.SaveChanges();
16             watch.Stop();
17             Console.WriteLine("{0}条数据耗时:{1}", count, watch.ElapsedMilliseconds);
18         }

   总结:EF自有的方法,三个阶段如上,数据超过1000条,性能直线下降,那么怎么来解决EF处理大数据量的性能问题呢?敬请期待下一个章节:   第九节: EF的性能篇(二) 之 Z.EntityFramework.Extensions程序集解决EF的性能问题

原文地址:https://www.cnblogs.com/yaopengfei/p/7751346.html