ASP.NET和多线程中每个请求的实体框架上下文



我的应用程序在ASP.NET MVC 4中。

我在每个请求中使用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,用于上下文的键
  2. 即使我能够传递httpcontext或对其进行null检查,如果子线程的运行时间比请求本身长,它也会在线程完成之前被处理掉,这将是有问题的

有什么解决方案吗?

我不确定您使用的是哪个版本的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的集成。

例如;

  • Unity
  • Autofac
  • SimpleInjector
  • 以及许多其他

我找到了一个侵入性较小的解决方案。(我知道,Gongdo-Gong解决方案要好得多,但需要在正在进行的项目中进行大量更改)

当我调用异步任务时,我通过HttpContext,最后我处理Context。

像这样:

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

这样HttpContext就可以在子线程中使用,并且上下文在作业结束时被处理。

最新更新