Entity Framework и пул соединений - PullRequest
       75

Entity Framework и пул соединений

260 голосов
/ 06 сентября 2010

Я недавно начал использовать Entity Framework 4.0 в своем приложении .NET 4.0, и мне любопытно узнать о нескольких моментах, связанных с пулированием.

  1. Пул соединений, как я знаю, управляется поставщиком данных ADO.NET, в моем случае это сервер MS SQL. Применимо ли это при создании экземпляра нового контекста сущностей (ObjectContext), то есть без параметров new MyDatabaseModelEntities()?

  2. Каковы преимущества и недостатки а) создания глобального контекста сущностей для приложения (т. Е. Одного статического экземпляра) или б) создания и раскрытия контекста сущностей для каждой данной операции / метода с помощью using блок.

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

Ответы [ 4 ]

361 голосов
/ 06 сентября 2010
  1. Пул соединений обрабатывается как в любом другом приложении ADO.NET. При подключении объекта все еще используется традиционное подключение к базе данных с традиционной строкой подключения. Я считаю, что вы можете отключить пул подключений в строке подключения, если вы не хотите его использовать. (подробнее о Пул соединений с SQL Server (ADO.NET) )
  2. Никогда не используйте глобальный контекст. ObjectContext внутренне реализует несколько шаблонов, включая Identity Map и Unit of Work. Влияние использования глобального контекста зависит от типа приложения.
  3. Для веб-приложений используйте один контекст для каждого запроса. Для веб-сервисов используйте один контекст на вызов. В приложении WinForms или WPF используйте один контекст для формы или для докладчика. Могут быть особые требования, которые не позволят использовать этот подход, но в большинстве случаев этого достаточно.

Если вы хотите знать, какое влияние оказывает один объектный контекст для приложения WPF / WinForm, проверьте эту статью . Это о NHibernate Session, но идея та же.

Edit:

Когда вы используете EF, он по умолчанию загружает каждую сущность только один раз для контекста. Первый запрос создает объект сущности и сохраняет его внутри. Любой последующий запрос, для которого требуется объект с тем же ключом, возвращает этот сохраненный экземпляр. Если значения в хранилище данных изменились, вы все равно получите объект со значениями из исходного запроса. Это называется Шаблон карты личности . Вы можете заставить контекст объекта перезагружать сущность, но он будет перезагружать один общий экземпляр.

Любые изменения, внесенные в объект, не сохраняются до тех пор, пока вы не вызовете SaveChanges в контексте. Вы можете вносить изменения в несколько объектов и сохранять их одновременно. Это называется Единица работы . Вы не можете выборочно сказать, какую модифицированную присоединенную сущность вы хотите сохранить.

Объедините эти две модели, и вы увидите некоторые интересные эффекты. У вас есть только один экземпляр объекта для всего приложения. Любые изменения в сущности влияют на все приложение, даже если изменения еще не сохранены (зафиксированы). В большинстве случаев это не то, что вы хотите. Предположим, что у вас есть форма редактирования в приложении WPF. Вы работаете с сущностью и решаете отменить сложное редактирование (изменение значений, добавление связанных сущностей, удаление других связанных сущностей и т. Д.). Но сущность уже изменена в общем контексте. Что вы будете делать? Подсказка: я не знаю ни о каких CancelChanges или UndoChanges на ObjectContext.

Я думаю, нам не нужно обсуждать сценарий сервера. Простое совместное использование одной сущности между несколькими HTTP-запросами или вызовами веб-службы делает ваше приложение бесполезным. Любой запрос может просто вызвать SaveChanges и сохранить частичные данные из другого запроса, потому что вы разделяете одну единицу работы между всеми ними. Это также будет иметь другую проблему - контекст и любые манипуляции с объектами в контексте или соединение с базой данных, используемое контекстом, не является потокобезопасным.

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

64 голосов
/ 06 сентября 2010

Согласно Даниэлю Симмонсу:

Создать новый экземпляр ObjectContext в Использование оператора для каждой услуги метод, чтобы он был утилизирован перед возвратом метода. Этот шаг очень важен для масштабируемости вашего сервиса. Это гарантирует, что соединения с базой данных не будут оставаться открытыми при вызовах службы, и что временное состояние, используемое конкретной операцией, будет собираться мусором после завершения этой операции. Entity Framework автоматически кэширует метаданные и другую информацию, необходимую для домена приложения, и ADO.NET объединяет пулы соединений с базами данных, поэтому повторное создание контекста каждый раз является быстрой операцией.

Это из его полной статьи здесь:

http://msdn.microsoft.com/en-us/magazine/ee335715.aspx

Я полагаю, что этот совет распространяется на HTTP-запросы, поэтому он действителен для ASP.NET. Приложение с полным состоянием клиента, такое как приложение WPF, может быть единственным случаем для «общего» контекста.

10 голосов
/ 10 сентября 2016

В соответствии с документацией EF6 (4,5 также): https://msdn.microsoft.com/en-us/data/hh949853#9

9.3 Контекст для запроса

Контексты Entity Framework предназначены для использованияв качестве кратковременных экземпляров, чтобы обеспечить наиболее оптимальную производительность .Ожидается, что контексты будут недолговечными и отбрасываются, и поэтому были реализованы так, чтобы быть очень легкими и повторно использовать метаданные, когда это возможно.В веб-сценариях важно помнить об этом и не иметь контекста для более чем продолжительности одного запроса.Аналогично, в не-веб-сценариях контекст должен быть отброшен на основе вашего понимания различных уровней кэширования в Entity Framework. Вообще говоря, следует избегать наличия экземпляра контекста на протяжении всей жизни приложения, а также контекстов для потока и статических контекстов.

1 голос
/ 13 марта 2014

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

GM_MEMBERS member = DatabaseObjectContext.GM_MEMBERS.FirstOrDefault(p => p.Username == username && p.ApplicationName == this.ApplicationName);
DatabaseObjectContext.Entry(member).Reload();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...