【问题标题】:Entity Framework Context per request in ASP.NET and Multi ThreadingASP.NET 和多线程中每个请求的实体框架上下文
【发布时间】:2015-03-23 09:53:34
【问题描述】:

我的应用程序在 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,用于上下文的key中。
  2. 即使我能够通过 httpcontext 或对它进行空检查,如果子线程的运行时间比请求本身更长,它也会在线程完成之前被释放,这将是有问题的。

有什么解决办法吗?

【问题讨论】:

    标签: c# asp.net multithreading entity-framework httpcontext


    【解决方案1】:

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

    例如;

    【讨论】:

    • 我什至不知道。我会详细阅读更多内容。但是这个项目已经非常大了(2年,2个开发者全职开发),使用它会是一个巨大的变化,或者你认为它是可行的吗?
    • 上下文的 dispose 是如何处理的?
    • 它依赖于DI框架,但据我所知,以上所有框架都支持在范围(本例中为HttpRequest)完成时自动处理功能。您也可以编写隐式处理代码。例如,这里是 SimpleInjector 文档; simpleinjector.readthedocs.org/en/latest/…
    【解决方案2】:

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

    当我调用异步任务时,我会通过 HttpContext,最后我会释放 Context。

    像这样:

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

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

    【讨论】:

      猜你喜欢
      • 2013-05-08
      • 2012-12-08
      • 2020-06-10
      • 1970-01-01
      • 2011-04-04
      • 2011-09-28
      • 1970-01-01
      • 2015-11-19
      相关资源
      最近更新 更多