title: Insert huge number of rows into database using Entity Framework
body: <p><strong>@EDIT
  I followed steps from <a href="https://stackoverflow.com/questions/5940225/fastest-way-of-inserting-in-entity-framework">Fastest Way of Inserting in Entity Framework</a> and got even worse results, so it's not a duplicate.</strong></p>
  
  <p>My goal is to create a seed method to fill one of the tables of LocalDb. The method will add 182500 rows (to mimic yearly activity data for 500 devices) for further test. I might want to run it few more times to change the number of devices, so even more rows will be generated. That is why I need to insert rows as efficient as possible.</p>
  
  <pre><code>    protected void SeedReportDataTable(int numberOfTerminals)
      {
          var rand = new Random();
          var tidsList = new List&lt;string&gt;();
  
          // generuj liste losowych numerow tid
          for (int i = 0; i &lt; numberOfTerminals; i++)
          {
              var randomTid = rand.Next(100000, 1000000).ToString(); // generuj 6-cyfrowy numer tid
              while (tidsList.Contains(randomTid)) { randomTid = rand.Next(100000, 1000000).ToString(); } // elminuj powtorzenia
              tidsList.Add(randomTid);
          }
  
          // dla kazdego z numerow tid generuj roczna historie aktywnosci
          var recordsList = new BlockingCollection&lt;ReportData&gt;();
          int year = Convert.ToInt32(DateTime.Now.Year);
  
          Parallel.ForEach(tidsList, tid =&gt;
          {
              // dla kazdego miesiaca
              for (int month = 1; month &lt;= 12; month++)
              {
                  // dla kazdego dnia
                  for (int day = 1; day &lt;= DateTime.DaysInMonth(year, month); day++)
                  {
                      var record = new ReportData
                      {
                          Tid = tid,
                          Active = Convert.ToBoolean(
                              rand.Next(0, 11)), // generuj losowy stan aktywnosci z prawdopodbienstwem 1/10 na bycie nieaktywnym
                          Date = new DateTime(year, month, day)
                      };
                      recordsList.Add(record);
                  }
              }
          });
          // dodaj unikalne klucze glowne rekordom przed dodaniem do kontekstu bazy
          var keyValue = 1;
  
          foreach (var record in recordsList)
          {
              record.Id = keyValue++;
          }
  
          // podziel liste na czesci
          int chunkSize = 1000;
  
          for (int recordsSkipped = 0; recordsSkipped &lt; recordsList.Count; recordsSkipped += chunkSize)
          {
              // wymieniaj kontekst
              using (var db = new dbEntities())
              {
                  db.Configuration.AutoDetectChangesEnabled = false;
                  db.Configuration.ValidateOnSaveEnabled = false;
                  // dodawaj do bazy po kawalku
                  db.ReportData.AddRange(recordsList.Skip(recordsSkipped).Take(chunkSize));
                  db.SaveChanges();
              }
          }
      }
  </code></pre>
  
  <p>Running this code took 30 minutes to complete. Before that I ran a version ending with:</p>
  
  <pre><code>using (var db = new dbEntities())
  {
      db.ReportData.AddRange(recordsList);
      db.SaveChanges();
  }
  </code></pre>
  
  <p>and it took 15 minutes, which is still slower than I expected.</p>
  
  <p>Why did my "improvements" fail?</p>
  
  <p>What can I do to make it insert rows faster?</p>