В этой записи блога я продемонстрирую несколько улучшений для добавления множества сущностей в базу данных на основе 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