【问题标题】:Which layer should I implement caching of lookup data from database in a DDD application?在 DDD 应用程序中,我应该在哪一层实现从数据库中查找数据的缓存?
【发布时间】:2011-11-09 04:02:23
【问题描述】:

我正在使用 DDD 设计 WCF 服务。 我有一个域服务层,它调用存储库来创建域对象。存储库是使用 ADO.Net 而不是 ORM 实现的。数据来自使用存储过程的数据库。在创建一个对象时说一个地址,SP 返回一个状态的 id。 SP 不会将地址表与状态表连接起来。状态由具有 id、abbr 和 name 属性的值对象类 State 表示。当应用程序启动时,状态对象列表可以被缓存(使用 system.runtime.caching.memorycache),因为它是非易失性数据。一般来说,我有一个 LookupDataRepository 可以从表中检索所有此类查找数据。现在,AddressRepository 必须从状态 id 填充地址的状态属性。
伪代码:

class AddressRepository : IAddressRepository
{
    Address GetAddressById(int id)
    {
        // call sp and map from data reader
        Address addr = new Address(id);
        addr.Line = rdr.GetString(1);
        addr.State = // what to do ?, ideally LookupCache.GetState(rdr.GetInt32(2))
    }
}

class State
{
    public int Id;
    public string Abbr;
    public string Name;
    enum StateId {VIC, NSW, WA, SA};
    public static State Victoria = // what to do, ideally LookupCache.GetState(StateId.VIC)
}

// then somewhere in address domain model
if(currentState = State.Victroia)
{
    // specific logic for Victoria
}

我的问题是把这个缓存放在哪一层?服务,存储库,一个可跨所有层使用的单独程序集。

【问题讨论】:

    标签: caching domain-driven-design repository


    【解决方案1】:

    在哪里放置缓存?这取决于。 如果您的场景是将您的 IAddressRepository 注入多个应用程序服务(我相信您称为 em 域服务),结果将是:

    • 在存储库级别缓存将使所有服务都受益(优点)。
    • 在存储库级别缓存将导致所有服务都必须使用缓存(缺点)。
    • 服务级别的缓存只会缓存那些使用特定服务和方法的客户端/服务(优点/缺点?)
    • 如果您在服务层进行事务管理,则在存储库级别应用缓存时需要小心。有时,读取操作可能会命中缓存,并且事务无法验证您要对其执行写入操作的读取数据是否未被修改。

    我会在服务层进行缓存。如果感觉更自然,并让您更好地控制要缓存的位置和时间。存储库级别通常是低粒度的。服务层及其方法更接近用例,然后您就知道何时以及缓存什么。

    我真的建议写一个像

    这样的缓存包装器
    public class CacheManager : ICacheManager
    {
     public Address Address
            {
                get { }
                set { }
            }
    }
    

    拥有对 System.Runtime.Caching.MemoryCache.Default 的静态引用。

    它使您的缓存类型安全,并且强制转换仅在包装器内完成。您还可以使用注入的 Mocked ICacheManager 对您的服务进行单元测试。

    更高级的方法是使用面向方面的编程和装饰器/拦截器来做到这一点。 StackOverFlow https://stackoverflow.com/search?q=AOP+caching

    【讨论】:

    • 我在考虑同一行。我唯一不同的是创建了一个读取这些值对象的新存储库(技术上不是存储库,而是更多的数据访问对象)。缓存将在这些值对象的特定服务层。真正的域存储库也将在创建域对象时使用此服务。
    • 所以如果你喜欢这个答案,请确认答案。它会帮助我,但它会帮助其他人找到这个问题并且它有一个确认的答案。
    【解决方案2】:

    根据我的观点和经验,缓存作为存储库会导致代码重复、域更复杂以及所有事件都需要缓存吗?由于将实现 IRepository 接口... 所以我选择了基础设施服务,让我们只缓存我们应用程序中需要的东西。它也可供所有其他希望使用它的服务使用。

    【讨论】:

      猜你喜欢
      • 2012-07-04
      • 1970-01-01
      • 2013-05-09
      • 2020-06-27
      • 2011-02-15
      • 1970-01-01
      • 2019-10-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多