2015-03-23 2 views
2

мое приложение в ASP.NET MVC 4.Entity Framework контекст для каждого запроса в ASP.NET и многопоточной

Я использую BDContext по желанию, как рекомендовано во многих вопросах здесь.

у меня есть:

public static class ContextPerRequest { 
    private const string myDbPerRequestContext = "dbGeTraining_"; 

    public static DbGesForma_v2 db { 
     get { 
      if (!HttpContext.Current.Items.Contains(myDbPerRequestContext + HttpContext.Current.GetHashCode().ToString("x") + Thread.CurrentContext.ContextID.ToString())) { 
       HttpContext.Current.Items.Add(myDbPerRequestContext + HttpContext.Current.GetHashCode().ToString("x") + Thread.CurrentContext.ContextID.ToString(), new DbGesForma_v2()); 
      } 

      return HttpContext.Current.Items[myDbPerRequestContext + HttpContext.Current.GetHashCode().ToString("x") + Thread.CurrentContext.ContextID.ToString()] as DbGesForma_v2; 
     } 
    } 

    /// <summary> 
    /// Called automatically on Application_EndRequest() 
    /// </summary> 
    public static void DisposeDbContextPerRequest() { 
     // Getting dbContext directly to avoid creating it in case it was not already created. 
     var entityContext = HttpContext.Current.Items[myDbPerRequestContext + HttpContext.Current.GetHashCode().ToString("x") + Thread.CurrentContext.ContextID.ToString()] as DbGesForma_v2; 
     if (entityContext != null) { 
      entityContext.Dispose(); 
      HttpContext.Current.Items.Remove(myDbPerRequestContext + HttpContext.Current.GetHashCode().ToString("x") + Thread.CurrentContext.ContextID.ToString()); 
     } 
    } 
} 

И я распоряжаюсь его в Application_EndRequest() метод. Такой подход долго работал.

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

Task.Factory.StartNew(() => { 
       DoSomething(); 
      }); 

Это приносит некоторые проблемы.

  1. HttpContext имеет значение null в subthreads и используется в ключе контекста.
  2. Даже если я смогу передать httpcontext или null проверить его, если подпроцесс займет больше времени, чем сам запрос, он будет удален до завершения потока, что будет проблематично.

Любые решения?

ответ

2

Я не уверен, какую версию ASP.NET вы используете. Во всяком случае, ASP.NET MVC (также WebAPI) имеет DependencyResolver, который поддерживает этот экземпляр для каждого запроса.

http://www.asp.net/mvc/overview/older-versions/hands-on-labs/aspnet-mvc-4-dependency-injection

Кроме того, я рекомендую вам использовать рамки DI с DependencyResolver, а не реализации каждого запроса экземпляра фабрики (или что-то подобное). Большинство известных инфраструктур DI поддерживают интеграцию с ASP.NET.

Например,

+0

Я даже не знал об этом. Я прочту больше об этом. Но проект уже очень большой (2 года, 2 разработчики, работающие полный рабочий день). Было бы массовым изменением, чтобы использовать это, или вы думаете, что это выполнимо? – Batista

+0

Как избавиться от контекста? – Batista

+0

Это зависит от структуры DI, но, насколько я знаю, прежде всего фреймворки поддерживают функцию автоматического удаления, когда область (HttpRequest в этом случае) завершена.Вы также можете написать неявный код утилизации. Вот, например, документы SimpleInjector; https://simpleinjector.readthedocs.org/en/latest/lifetimes.html#per-web-request –

0

Я нашел менее навязчивым решение. (Я знаю, решение Gongdo Gong намного лучше, но требует больших изменений в текущем проекте)

Когда я вызываю задачу async, я проходил через HttpContext, а в конце я располагаю контекстом.

Как это:

 System.Web.HttpContext htcont = System.Web.HttpContext.Current; 
     Task.Factory.StartNew(() => { 
       System.Web.HttpContext.Current = htcont; 
       DoSomething(); 
       ContextPerRequest.DisposeDbContextPerRequest(); 
     }); 

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