Статьи

ВСТАВЛЕНИЕ многих строк с помощью Entity Framework 6 beta 1 и SQL Server Compact

В этой записи блога я продемонстрирую несколько улучшений для добавления множества сущностей в базу данных на основе Entity Framework. Вы можете прочитать больше о выпуске бета 1 здесь , и Джули Лерман выделяет некоторые функции, которые были доступны в альфа-версии, здесь. Полный список функций EF 6 приведен здесь.

Здесь мы рассмотрим начало работы с Entity Framework 6 beta 1 и несколько улучшений, которые делают возможным добавление множества строк в базу данных SQL Server Compact через Entity Framework, а также рассмотрим использование моей библиотеки SqlCeBulkCopy для того же.

Я буду использовать консольное приложение для этого проекта, чтобы сосредоточиться на коде Entity Framework. Для начала запустите Visual Studio и создайте новое консольное приложение. Давайте назовем это EF6Test.

образ

Теперь давайте добавим пакет Entity Framework 6 beta 1 SQL Server Compact. Запустите консоль диспетчера пакетов NuGet (из Tools, Other Windows) и выполните эту команду:

PM> Install-Package EntityFramework.SqlServerCompact -Pre 

(Переключатель –Pre позволяет вам устанавливать предварительные пакеты)

Теперь вы должны увидеть несколько сообщений в окне, последнее из которых:

Успешно добавлено «EntityFramework.SqlServerCompact 6.0.0-beta1-20603» в EF6Test.

Этот процесс добавил ряд ссылок на DLL в проект и добавил в проект файл app.config с разделом entityFramework, в котором указана фабрика соединений SQL Server Compact по умолчанию:

<entityFramework>
  <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlCeConnectionFactory, EntityFramework">
    <parameters>
      <parameter value="System.Data.SqlServerCe.4.0" />
    </parameters>
  </defaultConnectionFactory>
  <providers>
    <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
    <provider invariantName="System.Data.SqlServerCe.4.0" type="System.Data.Entity.SqlServerCompact.SqlCeProviderServices, EntityFramework.SqlServerCompact" />
  </providers>
</entityFramework>

Теперь добавьте оператор использования:

using System.Data.Entity;

И добавьте следующие 2 класса перед «классом Program», они определяют нашу единственную тестовую таблицу и наш DbContext:

    public class Student
    {
        public int StudentId { get; set; }
        public string Name { get; set; }
    }

    public class StudentContext : DbContext
    {
        public DbSet<Student> Students { get; set; }
    }

Теперь добавьте следующий код в метод Main:

                 Stopwatch sw = new Stopwatch();
              bool useSqlCeBulkCopy = false;
              var students = CreateStudents();
   
              Database.SetInitializer(new DropCreateDatabaseAlways<StudentContext>());
              
              using (var db = new StudentContext())
              {
                  db.Database.Initialize(true);
                  if (!useSqlCeBulkCopy)
                  {
                      sw.Restart();
                      //AddRange rulez, no need for db.Configuration.AutoDetectChangesEnabled = false;
                      db.Students.AddRange(students);
                      sw.Stop();
                      
                      Console.WriteLine(
                          "Added 8000 entities in {0}", sw.Elapsed.ToString());
                    
                      sw.Restart();
                      int recordsAffected = db.SaveChanges();
                      sw.Stop();
   
                     Console.WriteLine(
                          "Saved {0} entities in {1}", recordsAffected, sw.Elapsed.ToString());
                      
                  }
                  Console.ReadKey();
              }
          }
   
          private static List<Student> CreateStudents()
          {
              var students = new List<Student>();
              for (int i = 0; i < 8000; i++)
              {
                  var student = new Student { Name = Guid.NewGuid().ToString() };
                  students.Add(student);
              }
              return students;
          }

Метод CreateStudents просто создает объект List с 8000 объектами Student. Новая база данных создается при каждом запуске (строка 5), и студенты добавляются в StudentContext DbContext, используя отличный новый метод AddRange, аналогичный методу LINQ to SQL InsertAllOnSubmit. В EF5 у вас был только метод Add, и для получения разумной производительности вам пришлось использовать загадочный оператор db.Configuration.AutoDetectChangesEnabled = false.

В SQL Server Compact и EF5 вставка 8000 строк на моем компьютере занимает около 58 секунд, а на вашем может даже истечь время ожидания… Благодаря тому, что Entity Framework теперь является открытым исходным кодом для CodePlex, я смог представить исправление ошибки , которое получил одобрение для EF6, поэтому процесс занимает на моем ПК около 8 секунд.

Для сравнения давайте добавим пакет SqlCeBulkCopy NuGet и выполним тот же процесс, используя его. В консоли диспетчера пакетов. тип

PM> Install-Package ErikEJ.SqlCeBulkCopy

Перед Console.ReadKey вставьте следующий код:

                else
                {
                    using (SqlCeBulkCopy bcp = new SqlCeBulkCopy(db.Database.Connection.ConnectionString))
                    {
                        bcp.DestinationTableName = "Students";
                        sw.Restart();
                        bcp.WriteToServer(students);
                        sw.Stop();

                        Console.WriteLine(
                            "Saved {0} entities using SqlCeBulkCopy in {1}", students.Count, sw.Elapsed.ToString());
                    }
                }

И установите useSqlCeBulkCopy = true. На моей машине это занимает около 150 мс! Поэтому, несмотря на улучшения, сделанные в EF6 beta 1, для больших нагрузок на данные я предлагаю вам использовать SqlCeBulkCopy , и, как видно из приведенного выше кода, его очень легко интегрировать в контекст Entity Framework.

Вы можете скачать готовый проект отсюда: http://sdrv.ms/18NaRmW