C# web应用中的单例模式

C# web应用中的单例模式,c#,.net,design-patterns,singleton,C#,.net,Design Patterns,Singleton,我在我的web应用程序中使用datacontext的单例模式,这样我就不必每次都实例化它,但是我不确定web应用程序是如何工作的,IIS是否为每个连接的用户打开一个线程?如果是这样的话,如果我的单例不是线程安全的,会发生什么?另外,对datacontext使用单例模式可以吗?谢谢。许多人通过将数据上下文保存在HttpContext.Current.Items中,从而在请求期间保留数据上下文,因此它对请求也是私有的 看一看,web服务器为每个请求创建一个新线程。我认为最好的方法是将datacont

我在我的web应用程序中使用datacontext的单例模式,这样我就不必每次都实例化它,但是我不确定web应用程序是如何工作的,IIS是否为每个连接的用户打开一个线程?如果是这样的话,如果我的单例不是线程安全的,会发生什么?另外,对datacontext使用单例模式可以吗?谢谢。

许多人通过将数据上下文保存在
HttpContext.Current.Items
中,从而在请求期间保留数据上下文,因此它对请求也是私有的


看一看,web服务器为每个请求创建一个新线程。我认为最好的方法是将datacontext绑定到每个请求,这意味着您应该在每次服务请求时创建一个新的datacontext。实现这一点的一个好方法是使用DI工具,例如。这类工具允许您设置所配置实例的生命周期,例如,在您的示例中,您可以将XDataContext类配置为HttpContext范围


注意。

每个应用程序域上的所有用户都可以看到静态变量,而不是每个会话。一旦创建,变量将在应用程序域的整个生命周期中都位于内存中,即使没有对该对象的活动引用

因此,如果您在web应用程序中有某种状态信息,其他用户不应该看到,那么它绝对不应该是静态的。将此类信息存储在用户会话中,或者将静态var转换为如下内容:

public static Data SomeData
{
    get
    {
        if (HttpContext.Session["SomeData"] == null)
            HttpContext.Session["SomeData"] = new Data();
        return (Data)HttpContext.Session["SomeData"];
    }
}
它看起来像一个静态变量,但它是特定于会话的,因此当会话结束时,数据会被垃圾收集,其他用户完全看不到它。没有安全保证


此外,如果静态变量中包含有状态信息,则需要某种形式的同步来修改它,否则将面临一场竞争条件的噩梦,需要解决。

以下是Microsoft关于如何使用LINQ to SQL实现多层的示例

我在web应用程序中对datacontext使用单例模式

在这种情况下,“单身”可能意味着许多不同的事情。是每个请求一个实例吗?每节课?每个线程?每个AppDomain(
静态
实例)?所有这些的含义截然不同

每个请求(存储在
HttpContext
中)一个“单例”就可以了。不鼓励每个会话使用单例,但可以使其正常工作。每个线程的单实例似乎可以工作,但可能会导致意外和难以调试的行为。每个应用程序或AppDomain的单例是一个等待发生的灾难

这样我就不必每次都实例化它

创建
DataContext
非常便宜。元数据是全局缓存的,在实际执行查询之前不会创建连接。没有理由试图优化掉
DataContext
实例的构造

但是,我不确定web应用程序是如何工作的,IIS是否为每个连接的用户打开了一个线程

IIS对每个请求使用不同的线程,但单个请求可能会使用多个线程,并且线程来自线程池,这意味着最终同一用户将在多个不同线程上有请求,相反,不同用户将在多个请求和延长的时间段内共享同一线程。这就是为什么我在上面提到,您不能依赖线程本地单例

如果是这样的话,如果我的单例不是线程安全的,会发生什么

非常糟糕的事情。在ASP.NET应用程序中全局缓存的任何内容都需要确保线程安全,或者在使用时需要锁定

另外,对datacontext使用单例模式可以吗?谢谢

DataContext
不是线程安全的,在这种情况下,即使您在使用
DataContext
时锁定了它(这已经是一个糟糕的想法),您仍然可能会遇到跨线程/跨请求争用情况。不要这样做

DataContext
实例应尽可能使用
using
子句限制在单个方法的范围内。下一个最好的方法是将它们存储在
HttpContext
中。如果必须,您可以在会话中存储一个,但是有许多事情需要注意(请参阅我最近在
ObjectContext
上的回答-几乎所有相同的原则都适用于
DataContext


但最重要的是,不要在ASP.NET应用程序中创建
DataContext
的“全局”单例实例。稍后您将对此深感遗憾。

为每个请求创建新的数据上下文到底有什么错?听起来你在过早地进行微优化,代价是增加耦合、降低可测试性和灵活性。我刚刚在某个地方读到,类实例化在性能方面很昂贵,所以我试图使用惰性单例来避免它,但是我想这并不是我在回答中读到的最好的方式。您最好只是执行一个智能实现,然后稍后再寻找瓶颈。作为旁注,请记住,每次用户访问您的站点时,都会有许许多多的类被创建和销毁(如果您能看到所有这些都发生了,您可能会感到非常惊讶!)我不知道人们一直在阅读的“某处”是哪里,类实例化是昂贵的。我真希望我能联系上这篇文章的原作者,告诉他去捣碎沙子。这个奇怪的坏主意似乎导致了比任何其他设计更糟糕的设计。请对你在互联网上读到的每一件事——包括这条评论——持健康的怀疑态度。@Aaronaught不要吹毛求疵——只是想澄清一点——web服务器肯定不会创建一个新的线程来处理这些问题