园友莱布尼茨写了一篇《Entity Framework数据插入性能追踪》的文章,我感觉不错,至少他提出了问题,写了出来,引起了大家的讨论,这就是一个氛围。读完文章+评论,于是我自己也写了个简单的程序试了试。

先晒一下代码:

两个简单的类:

   1:      /// <summary>
   2:      /// 消费者
   3:      /// </summary>
   4:      public class Consumer
   5:      {
   6:          public int CId { get; set; }
   7:          public string CName { get; set; }
   8:          public List<Order> Orders { get; set; }
   9:      }
  10:   
  11:      /// <summary>
  12:      /// 订单
  13:      /// </summary>
  14:      public class Order
  15:      {
  16:          public int OrderNo { get; set; }
  17:          public DateTime OrderDate { get; set; }
  18:          public decimal TotalMoney { get; set; }
  19:          public int CId { get; set; }
  20:   
  21:          public Consumer Consumer { get; set; }
  22:      }

映射配置:

   1:      public class ConsumerConfiguration : EntityTypeConfiguration<Consumer>
   2:      {
   3:          public ConsumerConfiguration()
   4:          {
   5:              HasKey(t => t.CId).Property(t => t.CId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
   6:              Property(t => t.CName).IsRequired().HasMaxLength(50);
   7:          }
   8:      }
   9:   
  10:      public class OrderConfiguration : EntityTypeConfiguration<Order>
  11:      {
  12:          public OrderConfiguration()
  13:          {
  14:              HasKey(t => t.OrderNo);
  15:              HasRequired(t => t.Consumer).WithMany(t => t.Orders).HasForeignKey(t => t.CId);
  16:          }
  17:      }

Context:

   1:      public class TestContext : DbContext
   2:      {
   3:          public DbSet<Consumer> Consumers { get; set; }
   4:          public DbSet<Order> Orders { get; set; }
   5:   
   6:          protected override void OnModelCreating(DbModelBuilder modelBuilder)
   7:          {
   8:              modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
   9:   
  10:              modelBuilder.Configurations.Add(new ConsumerConfiguration());
  11:              modelBuilder.Configurations.Add(new OrderConfiguration());
  12:   
  13:              base.OnModelCreating(modelBuilder);
  14:          }
  15:      }

测试代码:

   1:          static void Main(string[] args)
   2:          {
   3:              using (var ctx = new TestContext())
   4:              {
   5:                  ctx.Consumers.Add(new Consumer()
   6:                  {
   7:                      CName = "张三"
   8:                  });
   9:                  ctx.SaveChanges();
  10:   
  11:                  Stopwatch sw = new Stopwatch();
  12:                  sw.Start();
  13:                  Console.WriteLine("订单开始:\n");
  14:   
  15:                  for (int outer = 0; outer < 20000; outer++)
  16:                  {
  17:                      ctx.Orders.Add(new Order()
  18:                            {
  19:                                OrderDate = DateTime.Now,
  20:                                TotalMoney = 100,
  21:                                CId = 1,
  22:                            });
  23:                  }
  24:                  ctx.SaveChanges();
  25:                  sw.Stop();
  26:                  Console.WriteLine(sw.Elapsed.Minutes + "分" + sw.Elapsed.Seconds + "秒" + sw.Elapsed.Milliseconds + "毫秒");
  27:              }
  28:          }

上面的代码是最平常的代码了,没有什么可解释的,将内容放到重点上。

运行以上代码的环境是VS2012+SQL SERVER 2008 R2,机器配置:4G,N年以前的CPU。

运行上面的代码非常的慢,正如莱布尼茨说的,在数据Add到上下文这个阶段比较耗时。出现这个问题的原因是:每次调用ctx.Orders.Add(order)之前,EF都会调用DetectChanges,在StackOverFlow上有解释,地址是:http://stackoverflow.com/questions/9439430/improving-performance-of-initializing-dbset-in-seed,另外在Programming Entity Framework DbContext这本书的60也有DetectChange的介绍。

解决上面速度慢的问题的办法就是设置

   1:  ctx.Configuration.AutoDetectChangesEnabled = false;

下面来看看禁用以后的执行速度:

另外一个解决办法就是使用DbSet<T>.AddRange方法,这个方法是在6.0 beta1中加入的。

   1:                  List<Order> orderList = new List<Order>();
   2:                  for (int outer = 0; outer < 20000; outer++)
   3:                  {
   4:                      orderList.Add(new Order()
   5:                             {
   6:                                 OrderDate = DateTime.Now,
   7:                                 TotalMoney = 100,
   8:                                 CId = 1
   9:                             });
  10:                  }
  11:                  ctx.Orders.AddRange(orderList);
  12:                  ctx.SaveChanges();

AddRange方法在System.Data.Entity 泛型DbSet类中,下图是我通过Reflector截的图

从上面两幅图中可以看到,Add和AddRange都是添加到_internalSet中,但是如果AutoDetectChangesEnabled设置为true的话,添加任何实体之前都会调用DetectChanges,注意看Remarks中的解释。

测试源码下载地址:http://www.ef-community.com/forum.php?mod=viewthread&tid=437&extra=page%3D1

"Entity Framework数据插入性能追踪"读后总结的更多相关文章

  1. Lazy<T>在Entity Framework中的性能优化实践

    Lazy<T>在Entity Framework中的性能优化实践(附源码) 2013-10-27 18:12 by JustRun, 328 阅读, 4 评论, 收藏, 编辑 在使用EF的 ...

  2. 大数据应用之HBase数据插入性能优化实测教程

    引言: 大家在使用HBase的过程中,总是面临性能优化的问题,本文从HBase客户端参数设置的角度,研究HBase客户端数据批量插入性能优化的问题.事实胜于雄辩,数据比理论更有说服力,基于此,作者设计 ...

  3. Entity Framework 数据并发访问错误原因分析与系统架构优化

    博客地址 http://blog.csdn.net/foxdave 本文主要记录近两天针对项目发生的数据访问问题的分析研究过程与系统架构优化,我喜欢说通俗的白话,高手轻拍 1. 发现问题 系统新模块上 ...

  4. 关于Entity Framework采用DB First模式创建后的实体批量修改相关属性技巧

    Entity Framework采用DB First模式创建实体是比较容易与方便的,修改已创建的实体在个数不多的情况下也是没问题的,但如果已创建的实体比较多,比如10个实体以上,涉及修改的地方比较多的 ...

  5. .NET基础篇——Entity Framework 数据转换层通用类

    在实现基础的三层开发的时候,大家时常会在数据层对每个实体进行CRUD的操作,其中存在相当多的重复代码.为了减少重复代码的出现,通常都会定义一个共用类,实现相似的操作,下面为大家介绍一下Entity F ...

  6. asp.net mvc常用的数据注解和验证以及entity framework数据映射

    终于有时间整理一下asp.net mvc 和 entity framework 方面的素材了. 闲话少说,步入正题: 下面是model层的管理员信息表,也是大伙比较常用到的,看看下面的代码大伙应该不会 ...

  7. .NET批量大数据插入性能分析及比较

    数据插入使用了以下几种方式 1. 逐条数据插入2. 拼接sql语句批量插入3. 拼接sql语句并使用Transaction4. 拼接sql语句并使用SqlTransaction5. 使用DataAda ...

  8. 大数据应用之HBase数据插入性能优化之多线程并行插入测试案例

    一.引言: 上篇文章提起关于HBase插入性能优化设计到的五个参数,从参数配置的角度给大家提供了一个性能测试环境的实验代码.根据网友的反馈,基于单线程的模式实现的数据插入毕竟有限.通过个人实测,在我的 ...

  9. Lazy<T>在Entity Framework中的性能优化实践(附源码)

    在使用EF的过程中,导航属性的lazy load机制,能够减少对数据库的不必要的访问.只有当你使用到导航属性的时候,才会访问数据库.但是这个只是对于单个实体而言,而不适用于显示列表数据的情况. 这篇文 ...

随机推荐

  1. Let's encrypt申请泛域名证书以及报错处理

    申请泛域名证书的步骤请参考该链接地址: https://www.jianshu.com/p/df6d13187578 报错信息: No matching distribution found for ...

  2. Powered by Flink

    Apache Flink: Powered by Flink https://flink.apache.org/poweredby.html Powered by Flink Apache Flink ...

  3. soft deletion Google SRE 保障数据完整性的手段

    w http://www.infoq.com/cn/articles/GoogleSRE-BookChapter26 Google SRE 保障数据完整性的手段 就像我们假设Google 的底层系统经 ...

  4. IO流入门-第四章-FileReader

    FileReader基本用法和方法示例 /* java.io.Reader java.io.InputStreamReader 转换流(字节输入流---->字符输入流) java.io.File ...

  5. python基础之类的内置__setattr__,__delattr__,__getattr__和 二次加工标准类型(包装)

    一.内置attr:__setattr__,__delattr__,__getattr__ __setattr__ #添加/修改属性会触发它的执行 __delattr__ #删除属性的时候会触发 __g ...

  6. xml与java对象转换 -- XStreamAlias

    @XStreamAlias使用 一. 特点: 简化的API; 无映射文件; 高性能,低内存占用; 整洁的XML; 不需要修改对象;支持内部私有字段,不需要setter/getter方法 提供序列化接口 ...

  7. python引入同一目录下的py文件

    python引入同一目录下的py文件 注意:python2和python3的包内import语法有区别,下面介绍一下python3的包内import语法 例如在admin.py文件中要引入dealco ...

  8. 洛谷 P2216 [HAOI2007]理想正方形

    洛谷 巨说这是一道单调队列好题,但是我并不是用单调队列做的诶. 如果往最暴力的方向去想,肯定是\(n^3\)的\(dp\)了. \(f[i][j][k]\)代表当前正方形的左上角定点是\((i,j)\ ...

  9. 服务器(Ubuntu)远程访问ipython notebook(服务器运行ipython notebook 本地浏览器访问)

    准备工作 首先要安装 ipython 推荐直接 Anaconda 搞起(装在服务器). Anaconda 帮你集成N多python相关环境(包),省得你再手动咔咔一顿安装 服务器启动ipython n ...

  10. Angular学习笔记—HttpClient (转载)

    HttpClientModule 应用 导入新的 HTTP Module import {HttpClientModule} from '@angular/common/http'; @NgModul ...