Чрезвычайно низкая производительность при использовании Code-First с выпуском Entity Framework 4.1 - PullRequest
13 голосов
/ 09 августа 2011

Наша компания разрабатывает новое приложение, в основе которого лежит довольно большой объект бизнес-данных.Мы решили сначала опробовать Entity Framework с кодом, чтобы абстрагировать базу данных от приложения, но все пошло не так.Бизнес-объект состоит из приблизительно 60 классов и в общей сложности около 600 объектов;однако это древовидная структура, и указатели перекрестного / обратного отслеживания отсутствуют.

Наш тест заключался в добавлении одного неинициализированного экземпляра класса в базу данных.Использование DbContext.Add в нашей структуре данных заняло 8 минут на моей машине для разработки.Это ожидаемая производительность объекта такого размера?Есть ли список распространенных проблем, которые вызывают низкую производительность Entity Framework?Я чувствую, что мне нужна помощь с этим.

Еще несколько точек данных: на первом уровне под корнем бизнес-объекта 27 элементов.При наличии 3 элементов (остальные закомментированы) время добавления составляет 4,5 секунды.При наличии 5 элементов это составляет 11,8 секунды.При наличии 8 элементов это 1 минута 12,5 секунд.Очевидно, что размер этих элементов значительно различается, но, похоже, они указывают на какую-то систематическую проблему.

Ответы [ 2 ]

4 голосов
/ 09 августа 2011

... Нашим тестом было добавление одного неинициализированного экземпляра класса в базу данных.Использование DbContext.Add ...

Удалось ли вам убедиться, что ваша модель Code-First создана и загружена в память до , которую вы называли Add?Я имею в виду следующее: если вы используете такой тестовый код ...

using (var context = new MyContext())
{
    var myHugeBusinessObject = CreateItSomeHow();

    context.HugeBusinessObjects.Add(myHugeBusinessObject);

    context.SaveChanges();
}

... и вы впервые используете контекст в своем тестовом приложении Add фактически потратит некотороевремя построить модель EF в памяти, прежде чем она начнет добавлять объект в контекст.

Вы можете разделить эти два шага, просто добавив фиктивный метод перед вызовом Add, например, что-то вроде:

context.HugeBusinessObjects.Count();

Я построил тест:

public class MyClass
{
    public int Id { get; set; }
    public string P1 { get; set; }
    // ... P2 to P49
    public string P50 { get; set; }
    public MyClass Child1 { get; set; }
    // ... Child1 to Child26
    public MyClass Child27 { get; set; }
}

С этим я создал объект:

var my = new MyClass();
MyClass child = my;
for (int i = 0; i < 100; i++)
{
    child.Child1 = new MyClass();
    child = child.Child1;
}
child = my;
for (int i = 0; i < 100; i++)
{
    child.Child2 = new MyClass();
    child = child.Child2;
}
// and so on up to Child27

Таким образом, этот граф объектов имеет 2700 дочерних объектов с 50 скалярамисвойства каждого.Затем я проверил этот код:

using (var context = new MyContext())
{
    var my = CreateWithTheCodeAbove();

    context.MyClassSet.Count();
    context.MyClassSet.Add(my);

    context.SaveChanges();
}

...Count() (= построение модели EF) требует примерно 25 секунд .Add нужно 1 секунда .(Изменение от 100 до 1000 в вышеприведенных циклах (имея затем 27000 объектов на графике) увеличивает время для Add почти линейно до 9-10 секунд.) Этот результат не зависит от установки AutoDetectChangesEnabled в true или false.)

Следующий интересный результат: если я добавлю еще 20 свойств навигации (от Child28 до Child47) к MyClass времени, потраченному на построение модели (Count() в примере кода)взрывается до 140 секунд .Продолжительность Add увеличивается только линейно с дополнительными свойствами.

Итак, моя гипотеза такова: вы на самом деле не измеряете время для добавления вашего бизнес-объекта в контекст, а время, которое необходимо EF дляпостроить модель EF в памяти.Время построения модели, по-видимому, растет в геометрической прогрессии в зависимости от сложности модели: количества свойств навигации в классе и, возможно, также числа различных участвующих классов.

Чтобы разделить эти этапы, проведите тестирование с некоторымификтивный звонок, как предложено выше.Если у вас уже есть это разделение ... о боже, забудьте этот пост.

3 голосов
/ 17 августа 2011

Итак, разобрался с проблемой. При работе с NHibernate мы столкнулись со структурной ошибкой, которая представляла собой некоторый экспериментальный код. Категория подписывалась на события PropertyChanged своих дочерних элементов, что вызвало сбой NHibernate.

Что ХОРОШО! Это сказало нам, что на самом деле была проблема. Entity Framework просто работал вечно без каких-либо указаний на то, что это проблема, с которой мы могли бы что-то сделать.

Так или иначе, мы собираемся продолжать использовать NHibernate в настоящее время. Нам нравится контроль над структурой базы данных, которую мы получаем, используя ее.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...