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

时间:2011-11-09 04:02:23

标签: caching domain-driven-design repository

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

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
}

我的问题是放置此缓存的哪一层?服务,存储库,跨所有层的单独程序集。

2 个答案:

答案 0 :(得分:8)

放置缓存的位置?这取决于。 如果你的情况是你将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

中有大量有用的信息

答案 1 :(得分:0)

根据我的经验,根据我的经验,将缓存作为存储库会导致重复代码,域的复杂性以及所有事件都需要缓存吗?由于将实现IRepository接口... 因此,我选择了基础架构服务,让我们仅缓存应用程序中需要的内容。希望使用它的所有其他服务也可以使用它。