如何避免私有属性null检查做延迟加载?

时间:2012-03-23 04:29:41

标签: c# design-patterns

我有一个类似于20个字段的类,它们在加载时从SQL数据库中填充。目前我正在构造函数之后调用load数据方法,它调用SQL proc并填充所有必需的字段。有时,我可能根本不访问这20个字段,即使不需要,我也会增加SQL调用的额外费用。所以我将所有属性更改为具有关联的私有属性,并且当程序调用公共属性时,首先检查私有属性,如果它为null,则表示我们需要从sql加载数据,因此我调用了load方法。它工作得很好,但是当我看到代码时,有一个重复的null检查模式并加载sql查询。有没有更好的方法呢?

private string _name;
public string Name 
{
   get {
      if (_name == null)
         LoadData(); //this popultes not just but all the properties
      return _name;
   }
}

6 个答案:

答案 0 :(得分:5)

Btw C#现在有默认的lazy-loaders实现。为什么不使用它,而不是提供isSomethingLoaded标志? :)

public class Bar
{
    private Lazy<string> _name = new Lazy<string>(() => LoadString());

    public string Name
    {
        get { return _name.Value; }
    }
}

在非静态LoadString方法的情况下,lazy-loader应该在构造函数中初始化;

答案 1 :(得分:4)

不,这是对的。 Here is the wikipedia article。与不必要的数据库调用相比,空检查的开销非常小。现在,如果程序的用户实际上99%的时间都使用了这个值,那么我会说不需要这种模式。

只需注意一点:如果您的任何值可能为null,那么您将进行不必要的数据库调用。做这样的事情可能会更好(这将是一个更快的检查,因为它只是一点检查):

//Constructor default to not loaded
bool isLoaded = false;

private string _name;
public string Name 
{
   get {
      if (!isLoaded)
         LoadData(); //this popultes not just but all the properties
      return _name;
   }
}   

private LoadData()
{
    //Load Data
    isLoaded = true;
}

答案 2 :(得分:0)

你可以把它改成:

if (!initialized)
    LoadData();

并在你的LoadData集初始化为true,但这确实不会改变它的语义。

答案 3 :(得分:0)

您可以做的一件事是将if提取到单独的方法中,以便每个属性只包含一个额外的调用:

void EnsureData()
{
      if (!dataLoaded) 
         LoadData(); //this populates all the properties 
}

public string Name {
   get { 
      EnsureData();
      return _name; 
   } 
}

答案 4 :(得分:0)

我认为你应该考虑你的应用程序结构。如果您不打算使用这些属性,为什么还要实例化该类?我相信你在构造函数代码之后调用SQL实际上更干净,但是如果要使用它,只创建类的对象。另一个更灵活的解决方案是将LoadData公开,并根据需要从对象实例中根据需要调用它。

答案 5 :(得分:0)

我正处于设计模式的学习过程中。如果您只尝试使用单件设计模式加载数据,我有一个建议。

public class Singleton123
{
    private static readonly string _property1 = ClassLoadData.LoadData();

    public static string MyProperty1
    {
        get
        {
            return _property1;
        }
    }

}

public class ClassLoadData
{
    public static string LoadData()
    {
        // any logic to load data
        return "test";
    }
}

如下所示调用属性

Singleton123 obj = new Singleton123();
        string stra = Singleton123.MyProperty1;
        string strb = Singleton123.MyProperty1;

此属性只会加载一次。