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

Инициализация платформы Entity - SLOW - что я могу сделать, чтобы быстрее запустить ее?

Моя модель EF 4.3.1 имеет 200-нечетные таблицы. Начальный запуск ужасен, несколько минут. Профиль, захваченный DotTrace, подразумевает некоторые ужасные варианты алгоритма/масштабируемости в глубине структуры, о чем свидетельствуют миллионы вызовов ряда методов и 36 миллионов вызовов IEnumerable.Contains(). Вот фрагмент, все это вызвано первым запросом, сделанным в базе данных (будущие запросы этого не делают и все в порядке).

enter image description here

Что я могу сделать с моей моделью, чтобы сделать это менее болезненным? Могу ли я предварительно скомпоновать это? Лучше, может ли команда EF решить эти проблемы или открыть исходный код, чтобы я мог? Или, по крайней мере, исправить написание Warapper?:)

EDIT: Один конкретный вызов EF, который вызывает это, в основном var db = new MyDbContext(); db.Personnel.Where(a => a.Login == login).SingleOrDefault();. Также EF Migrations Seed() AddOrUpdate эффективно генерирует один и тот же стек. Более полная трассировка стека, которая может дать немного больше контекста, находится здесь: Полная трассировка стека

EDIT: Некоторые релевантные ссылки:

EDIT2: теперь, когда они просто открыть исходный код, кажется, что эта строка:

//Filter the 1:1 foreign key associations to the ones relating the sets used in these cell wrappers.
oneToOneForeignKeyAssociationsForThisWrapper =
    oneToOneForeignKeyAssociationsForThisWrapper.Where(
        it => (it.AssociationEndMembers.All(endMember => entityTypes.Contains(endMember.GetEntityType()))));

- это тот, который нуждается в некоторой работе. Он использует алгоритм O (n ^ 2), когда он, вероятно, не нужен, но я еще не пристально смотрел.

EDIT3: К счастью, похоже, что работа в EF6 фиксирует этот код: http://entityframework.codeplex.com/discussions/396130

4b9b3361

Ответ 1

В режиме предварительного EF6 генерация, как известно, медленна для больших моделей. На данный момент решение состоит в использовании прегенерированных представлений. Таким образом вы генерируете представления во время разработки и избегаете этой работы во время выполнения. Для этого загрузите инструменты электропитания EF и выберите "Оптимизировать модель данных сущностей". Он добавит в ваш проект файл С#, содержащий представления. Нижняя сторона - это то, что вам нужно будет делать это каждый раз, когда ваша модель меняется. Примечание: для создания представлений с помощью инструмента потребуется примерно столько же времени, сколько требуется для создания представлений во время выполнения (поэтому иногда вам нужно быть терпеливым). Вот сообщение об EF Power Tools, которое может быть полезно: http://blogs.msdn.com/b/adonet/archive/2011/05/18/ef-power-tools-ctp1-released.aspx

Edit

Недавно я создал другое решение, которое гораздо удобнее использовать (обратите внимание, что он работает только на EF6) - http://blog.3d-logic.com/2013/12/14/using-pre-generated-views-without-having-to-pre-generate-views-ef6/

Ответ 2

Вот еще один способ сделать это. Это требует немного ручной работы, но на самом деле может быть более подходящим для вашего сценария, где вы хотели бы использовать MsBuild. Вместо создания представлений с помощью Power Tools (извините, что они не сработали для вас) вы можете создать их вручную - вот шаги:

  • Сначала вам нужно получить артефакты для вашего контекста. Вам нужны все - csdl, ssdl и msl файлы. Вы можете использовать EdmxWriter для их получения. Обратите внимание, что EdmxWriter возвращает файл edmx, который объединяет все три файла, поэтому вам нужно их разделить. Вот код для этого шага (обратите внимание, что пространства имен специфичны для EF4, если вы думаете об использовании EF5 и .NET Framework 4.5, вам необходимо соответствующим образом изменить их или выбрать элементы только по локальному имени, а не по полному имени):

    var ms = new MemoryStream();
    using (var writer = XmlWriter.Create(ms))
    {
        EdmxWriter.WriteEdmx(new Context(), writer);
    }

    ms.Position = 0;

    var xDoc = XDocument.Load(ms);

    var ssdl = xDoc.Descendants("{http://schemas.microsoft.com/ado/2009/02/edm/ssdl}Schema").Single();
    var csdl = xDoc.Descendants("{http://schemas.microsoft.com/ado/2008/09/edm}Schema").Single();
    var msl = xDoc.Descendants("{http://schemas.microsoft.com/ado/2008/09/mapping/cs}Mapping").Single();

    ssdl.Save("Context.ssdl");
    csdl.Save("Context.csdl");
    msl.Save("Context.msl");
  • Если у вас есть артефакты, вы можете создавать представления с помощью инструмента EdmGen. Поскольку здесь мы делаем это вручную, вам нужно сделать это из командной строки VS. Вот команда, которую вы используете для генерации представлений:
EdmGen /mode:ViewGeneration /incsdl:Context.csdl  /inmsl:Context.msl /inssdl:Context.ssdl /outviews:Context.Views.cs
  • Добавьте сгенерированный файл в ваш проект.

Если вы хотите интегрировать создание представлений с вашей системой сборки, есть еще один интересный вариант - использование шаблона T4. Шаблон позаботится о вышеуказанных шагах. Подробнее об этом подходе можно найти здесь http://blogs.msdn.com/b/adonet/archive/2008/06/20/how-to-use-a-t4-template-for-view-generation.aspx. Единственная проблема заключается в том, что пример не для подхода CodeFirst, поэтому его нужно немного изменить, что не должно быть трудным.

Я создал T4-шаблоны для Code First. Вы можете найти ссылку для загрузки в моем сообщении в блоге: http://blog.3d-logic.com/2012/05/28/entity-framework-code-first-and-pre-generated-views/

Шаблоны теперь доступны в Visual Studio Code Gallery. Вот ссылка на сообщение со всеми подробностями: http://blog.3d-logic.com/2012/06/13/entity-framework-codefirst-view-generation-templates-on-visual-studio-code-gallery/

Ответ 3

Представленная генерация на самом деле довольно быстро в текущей версии Entity Framework. (6.1) В процессе подготовки существует еще одно, более широкое решение для кэширования: https://entityframework.codeplex.com/workitem/1876. Вы можете дождаться, когда этот патч будет принят, или, если вы достаточно храбры, вы можете применить его для себя.