Entity Framework: Singletonish ObjectContext - хорошо, плохо или переосмысление? - PullRequest
9 голосов
/ 12 февраля 2009

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

На данный момент вот что у меня есть:

public class EntityContext
{

    private static String MAIN_CONTEXT_KEY = "MainContext";
    private static TISQLEntities _context;

    public static void RemoveContext()
    {
        if (
            HttpContext.Current != null 
            && 
            HttpContext.Current.Items[MAIN_CONTEXT_KEY] != null
           )
        {
            ((TISQLEntities)HttpContext.Current.Items[MAIN_CONTEXT_KEY]).Dispose();
            HttpContext.Current.Items[MAIN_CONTEXT_KEY] = null;
        }

        if (_context != null)
        {
            _context.Dispose();
            _context = null;
        }
    }

    public static TISQLEntities Context
    {
        get
        {
            if (HttpContext.Current == null)
            {
                if (_context == null)
                {
                    _context = new TISQLEntities();
                }

                return _context;
            }

            if (HttpContext.Current.Items[MAIN_CONTEXT_KEY] == null)
            {
                HttpContext.Current.Items[MAIN_CONTEXT_KEY] = new TISQLEntities();
            }

            return (TISQLEntities)HttpContext.Current.Items[MAIN_CONTEXT_KEY];
        }
    }
}

А затем в файле Global.asax:

protected void Application_EndRequest(object sender, EventArgs e)
{
    EntityContext.RemoveContext();
}

Идея состоит в том, что, если это выполняется с веб-приложением, контекст создается при первой необходимости (и сохраняется в текущем HttpContext) и уничтожается при завершении запроса.

Если это ситуация с UnitTest, она не создается при первой необходимости и удаляется в TestCleanup (не так важно, как в этом посте, но просто хотелось пояснить объект _context).

Теперь идея этого заключается в том, чтобы не делать это:

using(TISQLEntities context = new TISQLEntities())
{
  ....
}

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

EntityContext.Context.User.Select(...)

И избегает «использования», которого я стараюсь избегать в большинстве случаев. Кроме того, я не создаю 9001 контекстов для обратной передачи.

Теперь, что меня интересует, так это то, что я слишком обдумываю это? Должен ли я просто продолжать создавать контекст для каждого метода, который нужен? Сказать по сообщению назад я должен:

  • Получить пользователя с идентификатором
  • Получить сайт с идентификатором
  • Добавление сайта к пользователю (user.Site = foundSite)
  • Сохранить пользователя

Это может повлечь как минимум 3 контекста. Является ли структура сущностей достаточно умной, чтобы можно было продолжать создавать контексты всякий раз, когда?

Ответы [ 3 ]

6 голосов
/ 12 февраля 2009

Вы реализуете эквивалент сеанса NHibernate для каждого шаблона запроса, который является хорошей конструкцией в NHibernate. Хотя я не могу сказать на 100%, что это применимо к EF, скорее всего, так оно и есть. Дальнейшее расширение других шаблонов управления сеансами - это сеанс для бизнес-диалога, который позволяет NHibernate расширять удержание сеанса в течение всего сеанса HttpSession, отключая и повторно подключая сеанс, а не разрушая и создавая. Если EF допускает аналогичную возможность в отличие от сохранения статического открытого соединения, вы можете посмотреть, как я реализовал этот шаблон с помощью AOP в своем блоге через мой профиль.

4 голосов
/ 26 мая 2009

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

1 голос
/ 13 февраля 2009

Если вы пытаетесь реализовать что-то, что NHibernate делает со своей сессией, я думаю, что это хорошая идея, чтобы иметь такую ​​модель Я точно знаю, что в LinqToSql реализация объекта контекста больше похожа на класс точки входа, который действует как фасад. Я хотел бы думать, что LinqToEntities похожи. У вас может быть заводская реализация, чтобы получить текст данных для вашей модели, где вы можете переработать текст данных. Если вы идете одиночным путем, учтите узкое место, доступность и ответственность одноэлементного объекта.

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