caching - 在 DDD 应用程序中,我应该在哪一层实现从数据库中查找数据的缓存?

标签 caching domain-driven-design repository

我正在使用 DDD 设计 WCF 服务。
我有一个域服务层,它调用存储库来创建域对象。存储库是使用 ADO.Net 而不是 ORM 实现的。数据来自使用存储过程的数据库。在创建一个对象时说一个地址,SP 返回一个状态的 id。 SP 不会将地址表与状态表连接起来。状态由具有 id、abbr 和 name 属性的值对象类 State 表示。当应用程序启动时,状态对象列表可以被缓存(使用 system.runtime.caching.memorycache),因为它是非 volatile 数据。一般来说,我有一个 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
}

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

最佳答案

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

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

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

    我真的建议编写一个缓存包装器,例如
    public class CacheManager : ICacheManager
    {
     public Address Address
            {
                get { }
                set { }
            }
    }
    

    它包含对 System.Runtime.Caching.MemoryCache.Default 的静态引用。

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

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

    关于caching - 在 DDD 应用程序中,我应该在哪一层实现从数据库中查找数据的缓存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8060193/

    相关文章:

    domain-driven-design - CQRS 和事件溯源 - 保存命令而不是事件?

    wordpress - 找不到与我的 GOOGLE APP 引擎应用程序关联的任何远程存储库

    linux - 如何配置Yum从自托管存储库更新

    c++ - 高效缓存和 BLOB - 分析缓存命中/未命中

    mysql - 如何为 AWS RDS 中的 MySQL 数据库刷新查询缓存?

    c# - 领域特定语言 (DSL) 和领域驱动设计 (DDD)

    c# - 在并发编辑环境中为子实体强制执行不变量

    php - 如何在 Doctrine2/Symfony2 的存储库中获取外部存储库?

    java - 在 Apache Felix 中禁用缓存

    ruby-on-rails - Rails 3.1 Sweeper 用于不同命名空间中的 Controller 方法