Как минимизировать снижение производительности при обновлении до EF 4.1 с LINQ до SQL? - PullRequest
3 голосов
/ 04 апреля 2011

Недавно я обновил приложение с LINQ to SQL и SQL Server CE 3.5 до Entity Framework 4.1 Code First и SQL Server CE 4.0, и теперь оно работает заметно медленнее.Я делал некоторые до и после тестирования секундомера, и большинство основных операций моего приложения в среднем работают примерно на 40% медленнее.

Я использую все стратегии и конфигурации по умолчанию для EF Code First, за исключением отключениякаскадное удаление.

Когда я первоначально разместил этот вопрос, я сосредоточился на одном запросе, который, казалось, занимал особенно много времени, но с тех пор я понял, что он был особенно медленным при первом запуске (см. ветку комментариев).ниже).

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

Это приложение имеет очень маленькую базу данных.Файл SQL CE (.sdf) занимает всего 458 КБ, а в самой большой таблице содержится менее 250 записей.

Вот пример класса POCO:

public class Target
{
    public int Id { get; set; }
    public int TrialDefinitionId { get; set; }
    public int Number { get; set; }
    public int X { get; set; }
    public int Y { get; set; }
    public string Phase { get; set; }
    public virtual TrialDefinition TrialDefinition { get; set; }
}

Все мои классы следуют этому основномушаблон (простые типы + виртуальные свойства для получения объектов, связанных внешними ключами).У меня есть один класс, который использует ICollection для получения списка для отношения многие-к-одному.

Последнее замечание: я использую шаблон репозитория в качестве посредника, и каждое использование репозитория являетсяпомещен в блок using.Для операций «get» это приводит к отсоединению сущностей после получения необходимых данных из базы данных.

У кого-нибудь есть какие-либо конкретные стратегии для повышения производительности моего приложения EF Code First?? Пожалуйста, имейте в виду, что у меня еще не было возможности подробно ознакомиться с EF.В основном я просто пытаюсь максимально быстро и безболезненно перейти с LINQ на SQL на EF.Самый полезный ответ для меня будет один, который состоит в изменении конкретных стратегий или конфигураций или других параметров.

Ответы [ 4 ]

5 голосов
/ 12 апреля 2011

Последнее замечание: я использую шаблон хранилища в качестве посредника, и каждое использование хранилища помещается в блок использования. Для операций «get» это приводит к отсоединению сущностей после получения необходимых данных из базы данных.

Ну, это не обязательно ...

  1. В архитектуре Entity Framework по умолчанию уже реализован шаблон хранилища.
  2. Поддержание ObjectContext в активе не означает, что вы поддерживаете соединение с базой данных.
  3. Только когда вы загружаете или сохраняете изменения в базе данных, захватывается новое соединение из пула соединений и выполняется операция.

Конечно, использование блока будет замедляться, потому что каждый использующий блок будет делать следующее,

  1. Инициализировать контекст (требуется загрузка метаданных из ресурсов)
  2. Проверить несколько вещей
  3. Открытое соединение с БД
  4. Выполняй свои задачи
  5. Очистить и закрыть DB

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

Entity Framework уже реализует Identity Map, что означает, что он будет поддерживать живой объект и только одну копию объекта для того же первичного ключа в течение всего времени существования контекста, что не только сэкономит память, но и будет работать быстрее.

Я бы посоветовал не использовать Использование блоков для каждого запроса или более мелких шагов, но вы должны поддерживать ObjectContext в течение всей жизни вашего приложения. И вам вообще не нужно внедрять кэширование или репозиторий.

1 голос
/ 04 апреля 2011
0 голосов
/ 10 апреля 2011

Когда вы перешли на подход Code First, это изменило структуру базы данных?

Мне кажется, да, и это является причиной изменения производительности.

Iтакже заметили, что в вашем классе у вас есть:

public int TrialDefinitionId { get; set; }

и:

public virtual TrialDefinition TrialDefinition { get; set; }

Требуются ли оба из них?

0 голосов
/ 04 апреля 2011

Читайте здесь и здесь о внутренней работе Entity Framework. Он связан с EFv4 и ObjectContext API, но EFv4.1 с DbContext API - просто оболочка для EFv4.

Если вы чувствуете, что ваш запрос медленный, попробуйте выполнить его дважды в одном и том же контексте и дважды в разных экземплярах контекста. Первый тест проверит, заключается ли проблема в материализации объекта, потому что объекты будут материализованы только для первого запроса, а второй тест проверит, есть ли какие-либо проблемы с инициализацией контекста (этого не должно быть, если вы используете стандартное создание контекста с соединением строка).

Было бы также интересно сравнить выполнение с скомпилированным запросом, но у меня есть ощущение, что скомпилированные запросы не являются частью API DbContext.

...