Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/32.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# ASP.NET和多线程中每个请求的实体框架上下文_C#_Asp.net_Multithreading_Entity Framework_Httpcontext - Fatal编程技术网

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

C# ASP.NET和多线程中每个请求的实体框架上下文,c#,asp.net,multithreading,entity-framework,httpcontext,C#,Asp.net,Multithreading,Entity Framework,Httpcontext,我的应用程序是ASP.NETMVC4 我在每个请求中使用BDContext,正如这里的许多问题中所建议的那样 我有: public static class ContextPerRequest { private const string myDbPerRequestContext = "dbGeTraining_"; public static DbGesForma_v2 db { get { if (!HttpContext.Curr

我的应用程序是ASP.NETMVC4

我在每个请求中使用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());
        }
    }
}
这带来了一些问题

  • HttpContext在子线程中为null,并在上下文的键中使用
  • 即使我能够传递httpcontext或null检查它,如果子线程的运行时间比请求本身长,它也会在线程完成之前被释放,这将是一个问题

  • 有什么解决方案吗?

    我不确定您使用的是什么版本的ASP.NET。无论如何,ASP.NET MVC(也是WebAPI)有DependencyResolver,它支持那些“每个请求”实例

    另外,我建议您将DI框架与DependencyResolver一起使用,而不是实现每个请求实例工厂(或类似的东西)。大多数著名的DI框架都支持与ASP.NET的集成

    比如,

    • 还有很多其他的

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

    当我调用异步任务时,我通过HttpContext,并在最后处理上下文

    像这样:

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

    通过这种方式,HttpContext在子线程中可用,并且在作业结束时释放上下文。

    我甚至不知道这一点。我会在德普特读到更多关于这方面的内容。但是这个项目已经非常大了(2年,2个开发人员全职开发),使用它将是一个巨大的改变,或者你认为它是可行的吗?如何处理上下文的处置?这取决于DI框架,但据我所知,最重要的是,当作用域(本例中为HttpRequest)发生变化时,框架支持自动处置功能完成了。您也可以编写隐式处理代码。这里是SimpleInjector文档示例;
          System.Web.HttpContext htcont = System.Web.HttpContext.Current;
          Task.Factory.StartNew(() => {
                    System.Web.HttpContext.Current = htcont;
                    DoSomething();
                    ContextPerRequest.DisposeDbContextPerRequest();
           });