我应该在网络应用程序中担心延迟加载吗?
-
06-07-2019 - |
题
我已经知道要使用单例延迟加载,这是要使用的模式:
private MyObject()
{
}
public static MyObject Instance
{
get { return SingletonCreator.CreatorInstance; }
}
private static class SingletonCreator
{
private static readonly MyObject _instance = new MyObject();
public static MyObject CreatorInstance
{
get { return _instance; }
}
}
但更简单的模式是:
private static readonly MyObject _instance = new MyObject();
private MyObject()
{
}
public static MyObject Instance
{
get { return _instance; }
}
这不会是延迟加载。但这真的是我应该在网络应用程序中烦恼的事情吗?
解决方案
除非你有不需要单例的静态方法,否则只需要包含一个静态构造函数就可以使类变得懒惰。如果没有静态构造函数,它仍然主要是懒惰。
有关更多详细信息和选项,请参阅我的单身实施页面。
我通常会在问题的底部给出你的代码 - 它很懒,除非你真的不想初始化单例,除非它将被使用。 (基本上使用 beforefieldinit
设置,JIT通常会确保方法中使用的每个类型都已初始化;没有 beforefieldinit
它必须等到第一次实际使用该类执行期间。有关详细信息,请参阅我的 beforefieldinit
页 - 但重要的一点是,装配完成后,它仍然不会初始化所有单例,或类似的东西。)
其他提示
这一切都很好,但延迟加载的重点是避免加载(通常是非托管的)资源(命中数据库,文件系统等),直到你需要,这样可以避免在你需要时先加载它们真的需要。单独使用单例模式本身并不一定意味着延迟加载,因为您可以在任何时候正确地创建托管实例。
如果只在进行适当的方法调用时访问您加载的任何资源,则延迟加载方面会起作用;如果,当创建单例实例时,它会执行一大堆数据库查询并保存结果,那么就我而言,它并不是延迟加载。
对于ORM场景,延迟加载通常直接指向关系中的另一个对象的加载,直到第一次访问为止,这避免了执行第二次可能不必要的查询。
然后再次,如果你知道你将在使用对象的过程中导航这种关系(即如果你已经检索了 User
以列出他们的帖子
或者什么),然后你可能想要指示你的ORM同时加载相关的对象,这通常会提示它用连接执行单个查询,而不是循环执行多个稍后查询;在这种情况下,你真的不想要延迟加载。
请确保不要混淆页面加载,会话和应用程序生命周期。那就是说,你确定要使用静态单例实例吗?一旦创建,它将一直存在,直到应用程序(网络服务器)关闭或您运行 iisreset 。
考虑在 HttpContext.Current.Items
中缓存它,如果你想要每页加载一个延迟加载的实例,或者在 HttpContext.Current.Session
中,如果你想要一个每个用户。