我有一个类似于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;
}
}
答案 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;
此属性只会加载一次。