2009-08-11 302 views
2

我在DAL方法返回的客户名单:延迟加载

Collection<Customer> FindAllCustomers(); 

客户有这些列:ID,姓名,地址,生物

我需要证明他们在我的ASPX格式(show-customers.aspx)的分页网格中,我将只显示这些列:ID,名称

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

Collection<Customer> FindAllCustomers(bool loadPartial); 

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

我认为在这里使用延迟加载将无法正常工作,因为DAL方法可以被第三方应用程序访问,该应用程序也可能需要加载该生物。

关于在这种情况下实现的最佳模式的任何建议?

感谢,

维卡斯

回答

1

如果您的客户清单从未展示生物,然后有一个精简版就可以了。

的几个问题...

  • 这是否参数仅确定生物是否加载?将来,您将有其他字段在设置为true时无法加载吗?
  • 如果我尝试访问生物,如果loadPartial设置为true,会发生什么?

关键是要确保您选择的任何机制都具有适应变化的能力。让自己置身于第三方的视角,并努力让自己的方法达到您的期望。您不希望使用您的类的开发人员必须深入理解这些机制。因此,也许不是“loadPartial”参数,您只需要一种不同的方法来解析绑定到列表所需的快速,最少的数据,并根据需要延迟加载其他字段。

+0

1.在DAL中传递的bool参数决定我们是否需要加载其他“非必要大”字段。未来可能有其他领域可能不需要。 2.如果loadPartial = true,bio将根本无法访问。我了解另一种方式:只要访问该资源,就会延迟加载Bio。 – user154624 2009-08-11 20:52:20

+0

但是再次强调,IMO对于这种延迟加载有两种方法: 1.在DAL中,让读者阅读Bio列,但不要将其加载到Customer属性中。在这种情况下,由于阅读器读取整行(而不是按列方式),因此我们会通过让SP返回整个Bio列来记录每个记录,从而浪费宝贵的DB带宽。 2.一旦Bio属性被访问,通过参数化的SP加载生物列。在这种情况下,我会进行2个DAL呼叫。不知道这有多好? – user154624 2009-08-11 20:53:12

1

我认为这是可以接受的......这是你的程序。你只是想确保API被记录并且对其他人有意义。

作为一个方面说明,您不一定需要两个存储过程或存储过程中的经典if语句。

loadPartial == true时,您可以使用case语句到NULL

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

我认为可以有两种方法针对特定情况进行优化,只要您在方法名称中明确说明即可。我个人认为:

Collection<Customer> FindAllCustomers(bool loadPartial); 

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

说清楚,一切都很好。

3

第三方的东西是一个绑定。

乍一看我通常会建议你只加载通常是最小的数据,然后在AS-要求加载完成或进一步的细节(即触摸特性可能引发DB调用 - 财产轻度滥用有可能)或后台进程的基础上,取决于你在做什么的性质。通过澄清的方式

懒惰的属性代码:

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

为什么在客户类本身的属性不使用延迟加载?给每个属性(Id,Name,Bio)一个私有变量。在每个属性的getter中,如果private变量不为null,则返回它,否则从DAL中读取它。当涉及到生物,如果你不得不懒惰加载它,然后在你的getter你调用客户类中另一个名为LazyLoadAdditionalDetails()的方法,并调用适当的sprocs那里,然后返回您的私有变量。

这样你就可以保持你的代码正常,你的分页视图只会调用ID和Name的getters,而你的Bio只会在需要的时候从一个sproc填充,而你不必记得调用一个懒惰加载方法。

+0

在网络环境中,必须注意这种方法。在Customer对象的单个属性上使用LazyLoad方法本身的缺点是,如果列表中存在一串DB请求,那么可能会按顺序触发这些请求。在这种情况下,必须为整个列表启用LazyLoading,例如在一个页面上显示的对象数量(如果列表使用分页),则会导致单个数据库访问。 – Juri 2009-08-11 20:57:56

+0

它可能是一个请求不是一堆,但它肯定需要照顾 – annakata 2009-08-11 20:59:51

+0

@annakata:我同意。我的一些同事在一个以前的项目中尝试过,因为这个原因他们说没有正常工作。我猜他们没有尝试在整个列表上实现延迟加载,因为这可能会更具性能(或实现某种缓存)。 – Juri 2009-08-11 21:34:25

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

     set 
     { 
     _LoadPartial = value; 
     } 
    } 


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

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

0

而不是

Collection<Customer> FindAllCustomers(bool loadPartial); 

我会让它

Collection<Customer> FindAllCustomers(bool includeBio); 

“loadPartial” 不知道什么是 “局部的” 客户消费。我也同意annakata的观点。

3

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

public enum RetrieveCustomerInfo 
{ 
    WithBio, 
    WithoutBio 
} 

当你调用方法:

dao.FindAllCustomers(RetrieveCustomerInfo.WithBio); 

我不知道,如果是更好,但我认为这是更清晰。