zoukankan      html  css  js  c++  java
  • "Entity Framework数据插入性能追踪"读后总结

    园友莱布尼茨写了一篇《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;

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

    QQ截图20130607002820

    另外一个解决办法就是使用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();

    QQ截图20130607004003

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

    QQ截图20130607004407

    QQ截图20130607004652

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

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

    夜已深!

    天亮了,就要高考了,祝福所有的考生!

    Technorati 标签: EF,EntityFramework,DetectChanges
    作者:BobTian
    出处http://nianming.cnblogs.com/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
    欢迎访问我的个人博客:程序旅途
  • 相关阅读:
    Http的响应结构
    jQuery ajax
    什么是序列化和反序列化
    Ubuntu 安装 Anaconda3 步骤
    mysql 带换行符的字符串数据插入数据库异常
    Elasticsearch之Analysis(分析器)
    python 使用 xlrd、xlwd读写excel表格
    测试
    elasticsearch中的mapping简介
    Elasticsearch索引的操作,利用kibana 创建/删除一个es的索引及mapping映射
  • 原文地址:https://www.cnblogs.com/nianming/p/3123103.html
Copyright © 2011-2022 走看看