对标题感到抱歉。这相当复杂。我将尝试以简化的抽象方式(尽我所能)总结它。
在Web表单应用程序中,DAL将在两个不同的上下文中使用:
在每次调用中,需要使DAL知道当前的用户ID,以便它可以将此id存储在数据库事务中。我已经为DAL添加了一个类型为Func的静态属性,这样当使用DAL时,可以为它提供一个允许它获取用户ID的方法(通过callng代码)。
从代码隐藏进行的调用将提供一个GetUserId方法,该方法从会话中获取用户ID,而Web API控制器调用(无状态)将具有用户id作为参数,并且能够返回该值
我担心的是,Web环境中的静态是跨会话共享的。所以..
如果他们发生冲突,那么我会找到另一种方法来做,但我想避免将用户ID传递给每个对象Save()。
解
史蒂文的回答提示,我有一个游戏CallContext只是为了向自己证明它将保留针对特定线程的上下文,尽管通过静态调用。以下是具有重叠线程的非常简单测试。接下来我将在Web API环境中尝试它,它应该是相同的。
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");
}
}
答案 0 :(得分:2)
从HttpContext.Current.Session
阅读显然是安全的,因为HttpContext.Current
会为每个请求返回不同的HttpContext
个实例。但由于您的Func
字段是静态的,因此替换Func
当然会使您的代码失败,因为每个App域只有一个静态字段实例。所以你应该采取不同的方法。
例如,不是替换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);
}