Подтвердить что ты не робот

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

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

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

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

4b9b3361

Ответ 1

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

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

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

Ответ 2

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

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