【问题标题】:Recommended Pattern for Lazy-loading Portions of Object Graph from Cache从缓存中延迟加载部分对象图的推荐模式
【发布时间】:2012-02-08 20:02:36
【问题描述】:

我在 Web 应用程序后面使用 memcache 来最大程度地减少对我们 SQL 数据库的访问。我通过用SerializableAttribute 标记它们将C# 对象存储到这个缓存中。我们通过 Ninject 在我们的应用程序中大量使用依赖注入。

其中一些对象很大,我想将它们分解。但是,它们来自单个存储过程调用(即一个存储过程调用被烹制到完整的对象图中),我希望能够分解这些对象并分别从缓存中延迟加载特定的子图,而不是一次将整个对象图加载到内存中。

有哪些模式可以帮助我完成这项工作?

【问题讨论】:

  • 我总是先咨询 Martin Fowler:martinfowler.com/eaaCatalog/lazyLoad.html
  • 所以我想我的一个问题是,为什么这个对象这么大——或者更确切地说,它是如何使用的,你不能只发回完全加载的对象?它是通过服务退回还是什么?如果是这种情况,那么我认为您需要更适当地隔离这些合同,这听起来需要进行一些相当大的重构。
  • 如果我理解正确,我很确定您可以使用我们的库 Patterns.NET @ www.nubilosoft.com 做到这一点。听起来就像做 Lazy.Create(..) 一样简单,它基本上将延迟加载包装器包装在对象周围。也不确定它是否适用于此,但我也会看看 Flyweight。
  • @Sinaesthetic:在这种情况下,存储过程调用的大粒度问题反映了设计不佳的遗留模式,其修改超出了范围。
  • 这个/这些对象最终是如何使用的?他们是否被排除在服务之外?我问是因为我的意思是,如果对象已经从数据库中拉出并构建,并且你缓存它,那么......它已经在那里,所以我不确定我是否看到尝试“延迟加载”某些东西的好处那已经在记忆中了。 ??

标签: c# .net ninject-2


【解决方案1】:

就模式而言,我认为从单个存储过程构建的一个大型复杂对象是可疑的。我不确定您的缓存是一项要求还是只是其实施的当前状态。

我习惯的模式是一种存储库模式,使用填充特定合同的操作。并且这些操作包含一个或多个数据源,这些数据源调用数据库中的存储过程,这些存储过程将用于构建您所说的那些子图之一。话虽如此,如果您要从数据库中延迟加载数据,那么我只能假设许多对象成员在很多时候都没有使用,这进一步证明了我的观点 - 分解该对象。

关于它的几件事:

  • 如果整个对象都经常使用,可能会很麻烦
  • 它可以通过操作完全注入
  • 数据源包含特定对象的读取器,因此仅执行一项任务 (SOLID)
  • 可以修改为使用Entity Framework,不用大惊小怪
  • 可以设计成实现一个接口,使其更易于重用
  • 将要求您将该 proc 分解成更小的、可咀嚼的部分,从长远来看,这可能只会使您受益。
  • 如果只使用其中的一部分,则该图中显示的复杂对象实际上不应该存在。相反,请考虑隔离这些对象。但是,这实际上取决于该对象的使用方式。

更新:

使用您的缓存作为存储库,我可能会这样处理它:

因此,基本上,您存储遗留对象,但在您的操作中,您使用它们来构建返回给客户端的更多相关 DTO。

【讨论】:

  • “[T]从单个存储过程构建的一个大型复杂对象是可疑的。”你是绝对正确的;但是,这对我来说是一个设计约束。我无法改变这一点。
【解决方案2】:

我知道 NHibernate 会延迟加载购买用代理对象替换对象。然后在代理对象中有某种检查会导致在您第一次尝试访问该对象时加载真实对象。

我不确定是否有任何设计模式可以涵盖这一点,但您可以查看 Nhibernate 源代码。

使用代理对象的一个​​缺点是您必须小心继承和类型检查,因为您可能会检查代理的类型而不是实际对象。

【讨论】:

    猜你喜欢
    • 2012-03-13
    • 2014-04-12
    • 2011-04-10
    • 1970-01-01
    • 2021-10-08
    • 1970-01-01
    • 2011-02-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多