懒惰加载我的C#应用​​程序

时间:2009-08-11 20:40:03

标签: c# lazy-loading

我的DAL中有一个方法返回一个客户列表:

Collection<Customer> FindAllCustomers();

客户有以下列:ID,名称,地址,生物

我需要在我的ASPX表单(show-customers.aspx)的分页网格中显示它们,我将只显示这些列:ID,Name

现在,在我的DAL FindAllCustomers()中,我是否也从SP返回Bio字段(我正在使用阅读器填写集合)? Bio字段可以很大(nvarchar(max))。我在考虑延迟加载或只加载必需的字段。但在那种情况下,我需要创建另一种方法,返回一个“完整”的客户列表,包括bio,以便第三方应用程序可以通过服务层使用它。所以可以创建这样的方法:

Collection<Customer> FindAllCustomers(bool loadPartial);

如果loadPartial = true,则不要加载Bio,否则加载它。在这种情况下,因为我不想从SP返回Bio,我需要根据bool值在我的SP中创建2个select语句。

我认为在这里使用延迟加载是行不通的,因为DAL方法可以被第三方应用程序访问,这可能也想加载bio。

有关在这种情况下实施的最佳模式的任何建议吗?

感谢,

维卡斯

8 个答案:

答案 0 :(得分:3)

第三方是绑定。

乍一看,我通常会建议您只加载最小数据,然后按要求加载完整或更详细的信息(即触摸属性可能触发数据库调用 - 可能会轻微滥用财产)或背景过程基础,取决于你正在做的事情的性质。

通过澄清的懒惰属性代码:

class Customer
{
  private string _lazydata = null;

  public string LazyData
  {
    get
    {
      if (this._lazydata==null)
      {
        LazyPopulate();
      }
      return this._lazydata;
    }
  }

  private void LazyPopulate()
  {
    /* fetch data and set lazy fields */
  }
}

小心这一点,你不想进行大量的数据库调用,但是当你看到懒惰的东西时,你也不想创建瓶颈。只有您应用的性质才能决定这是否合适。

我认为你有一个有效的案例来创建布尔标志方法(虽然我会默认为轻量级版本),理由是第三方很可能会因为你做的原因而想要轻量级版本。

我会选择:

Collection<Customer> FindAllCustomers()
{
  return this.FindAllCustomers(false);
}

Collection<Customer> FindAllCustomers(bool alldata)
{
  /* do work */
}

答案 1 :(得分:3)

在这种情况下,我会使用枚举来更清楚地了解参数的含义。

public enum RetrieveCustomerInfo
{
   WithBio,
   WithoutBio
}

当你打电话给方法时:

dao.FindAllCustomers(RetrieveCustomerInfo.WithBio);

我不知道它是否更好,但我认为它更清楚。

答案 2 :(得分:1)

如果您的客户列表从未显示过bio,那么使用简化版本就可以了。

一些问题......

  • 该参数是否仅确定是否加载了Bio?将来,当其设置为true时,您是否还有其他未加载的字段?
  • 如果我尝试访问Bio,如果loadPartial设置为true,会发生什么?

关键是确保您选择的任何机制都能适应变化。把自己置于第三方的角度,并尝试让你的方法做你期望的。您不希望使用您的类的开发人员必须深入了解这些机制。因此,您可以使用不同的方法来解析绑定到列表所需的快速,最小化数据,并根据需要延迟加载其他字段,而不是“loadPartial”参数。

答案 3 :(得分:1)

我认为这是可以接受的...这是你的计划。您只是想确保API已记录在案并对其他人有意义。

作为旁注,您不一定需要在存储过程中使用两个存储过程或经典if语句。

NULL时,您可以在loadPartial == true字段中使用案例陈述。

Case WHEN @loadPartial = 1 THEN NULL ELSE [bio] END

答案 4 :(得分:1)

我认为只要在方法名称中明确说明,就可以为特定情况优化两种方法。我个人认为:

Collection<Customer> FindAllCustomers(bool loadPartial);

很清楚。开发人员如何知道该布尔参数在实践中的实际意义?请参阅boolean parameters — do they smell?问题。

说清楚,一切都很好。

答案 5 :(得分:1)

为什么不在Customer Class本身的属性中使用延迟加载?给每个属性(Id,Name,Bio)一个私有变量。在每个属性的getter中,如果私有变量不为null,则返回它,否则从DAL中读取它。

说到Bio,如果你不得不加载它,那么在你的getter中你调用Customer Class中另一个名为LazyLoadAdditionalDetails()的方法并在那里调用相应的sprocs,然后返回你的私有变量。

通过这种方式,您可以保持代码正常,并且您的分页视图只会调用ID和名称的getter,并且只有在需要时才会从sproc中填充您的Bio,而无需记住调用延迟加载方法

答案 6 :(得分:0)

class CustomerDAO
{
   private bool _LoadPartial = true;
   public bool LoadPartial
   {
      get
      {
         return _LoadPartial;
      }

      set
      {
         _LoadPartial = value;
      }
   }


   public Collection<Customer> FindAllCustomers()
   {
      ...
   }
}

将是另一种选择,虽然我也喜欢annakata的一个。

答案 7 :(得分:0)

而不是

Collection<Customer> FindAllCustomers(bool loadPartial);

我做到了

Collection<Customer> FindAllCustomers(bool includeBio);

“loadPartial”不会告诉消费者什么构成“部分”客户。我也同意annakata的观点。