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