Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/322.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

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# 静态委托如何访问非静态、服务器端、基于会话的信息?_C#_Asp.net_Session_Data Access Layer - Fatal编程技术网

C# 静态委托如何访问非静态、服务器端、基于会话的信息?

C# 静态委托如何访问非静态、服务器端、基于会话的信息?,c#,asp.net,session,data-access-layer,C#,Asp.net,Session,Data Access Layer,关于标题,我很抱歉。这相当复杂。我将尝试用一种简化、抽象的方式(尽可能多地)对其进行总结 在web表单应用程序中,DAL将在两种不同的上下文中使用: 从代码隐藏 来自Web API控制器 在每次调用中,需要让DAL知道当前用户Id,以便它可以根据数据库事务存储此Id。我已经向DAL添加了一个Func类型的静态属性,这样当使用DAL时,可以为它提供一个方法(通过调用代码),允许它获取用户id 从代码隐藏进行的调用将提供一个GetUserId方法,该方法从会话中获取用户id,而Web API控制器调

关于标题,我很抱歉。这相当复杂。我将尝试用一种简化、抽象的方式(尽可能多地)对其进行总结

在web表单应用程序中,DAL将在两种不同的上下文中使用:

  • 从代码隐藏
  • 来自Web API控制器
  • 在每次调用中,需要让DAL知道当前用户Id,以便它可以根据数据库事务存储此Id。我已经向DAL添加了一个Func类型的静态属性,这样当使用DAL时,可以为它提供一个方法(通过调用代码),允许它获取用户id

    从代码隐藏进行的调用将提供一个GetUserId方法,该方法从会话中获取用户id,而Web API控制器调用(无状态)将用户id作为参数并能够返回该值

    我关心的是,web环境中的静态信息是跨会话共享的。所以

  • 当用户A运行一个会话,该会话将GetUserId方法设置为返回会话[“UserId”],而用户B运行一个会话,该会话同时执行相同的操作时,每个事务是否都会收到正确的用户id?我在想,因为HttpContext.Current本身就是一个静态的,这应该没问题
  • 当用户A通过Web API控制器进行调用并将GetUserId方法设置为返回参数值(假设id为1),然后用户B同时进行相同的调用,但用户id参数为2。。。一个会取代另一个,还是会保持不同?我想他们可能会发生冲突
  • 如果它们发生冲突,那么我将找到另一种方法,但我希望避免将用户id传递到每个对象Save()

    解决方案

    根据Steven的回答,我有一个play CallContext,只是为了向自己证明它将保留特定线程的上下文,尽管它是通过静态调用的。下面是一个带有重叠线程的非常简单的测试。接下来,我将在WebAPI环境中尝试它,应该是相同的

    class Program
    {
        static void Main(string[] args)
        {
            for (var i = 0; i < 10; i++)
                StartTestThread(i);
    
            Console.ReadKey();
        }
    
        private static void StartTestThread(int i)
        {
            Thread.Sleep(2000);
    
            ThreadPool.QueueUserWorkItem(delegate {
    
                Console.WriteLine(string.Format("[{0}] Setting context...", i));
                SetCallContext(i);
                Console.WriteLine(string.Format("[{0}] Waiting...", i));
                Thread.Sleep(5000);
                Console.WriteLine(string.Format("[{0}] Context is {1}", i, GetCallContext()));
            });
        }
    
        private static void SetCallContext(int i)
        {
            CallContext.LogicalSetData("Test", i);
        }
    
        private static int GetCallContext()
        {
            return (int) CallContext.LogicalGetData("Test");
        }
    }
    
    类程序
    {
    静态void Main(字符串[]参数)
    {
    对于(变量i=0;i<10;i++)
    starttsethread(i);
    Console.ReadKey();
    }
    私有静态void starttesthread(int i)
    {
    《睡眠》(2000年);
    ThreadPool.QueueUserWorkItem(委托{
    WriteLine(string.Format(“[{0}]设置上下文…”,i));
    SetCallContext(i);
    WriteLine(string.Format(“[{0}]Waiting…”,i));
    睡眠(5000);
    WriteLine(string.Format(“[{0}]上下文为{1}”,i,GetCallContext());
    });
    }
    私有静态void SetCallContext(int i)
    {
    CallContext.LogicalSetData(“测试”,i);
    }
    私有静态int GetCallContext()
    {
    return(int)CallContext.LogicalGetData(“Test”);
    }
    }
    
    读取
    HttpContext.Current.Session
    显然是安全的,因为
    HttpContext.Current
    为每个请求返回不同的
    HttpContext
    实例。但是由于您的
    Func
    字段是静态的,因此替换
    Func
    当然会导致代码错误,因为每个应用程序域只有一个静态字段实例。所以你应该采取不同的方法

    例如,与其替换Func,不如只初始化它一次,并让它处理Web API情况。例如:

    GetUserId = () =>
    {
        var context = HttpContext.Current;
    
        // MVC / Web Forms
        if (context.Session != null && context.Session["UserId"] != null) {
            return (int)context.Session["UserId"];
        }
    
        // Web API
        return (int)CallContext.LogicalGetData("__userId");
    };
    
    public static void RegisterWebApiUserId(int userId) {
        CallContext.LogicalSetData("__userId", userId);
    }
    

    我认为您应该完全回避这个问题,并向DAL构造函数或方法调用传递一个值。我明白你想要实现什么,我只是觉得不值得。顺便说一句:HttpContext。Current是由
    全局.asax
    会话按请求填充的。因此每个用户会话在CallContext中都有自己的GUID键,这会导致用户id。但是DAL对象如何获得该GUID?我以前没有用过CallContext,所以请原谅我的慢。或者,DAL的每个实例化都会为该实例生成一个键,然后生成静态方法。。坚持静态方法将无法看到非静态密钥,对吗?@MattWinward:不,您在应用程序域中生成一次密钥。我更新了我的问题,让这更明显。啊,好的。因此,密钥可以是一个静态值(示例中为“_userId”),CallContext为每个“调用”存储一个值,有效地提供与会话相同的功能,但对于Web API调用?@MattWinward:“调用”将具有单个Web API请求的生存期,使用异步方法调用流,甚至,与请求中跨越的并行任务一起流动。谢谢。这太棒了。我要试一试,看看会发生什么!