这个问题源于我问过另一个关于接口,QCRS和Mediatr库(请求/响应)的问题
Mediatr: reducing number of DI'ed objects
我创建了许多命令和查询,并且有许多行为,其中之一是Cache行为,对于每个查询,在针对db实际执行查询之前都会检查cache的值。到目前为止,这很好用,但是当我有一个UpdateSomethingCommand时,就会出现delima,一旦更新了数据库中的基础对象,我想用成功保存到数据库中的内容刷新缓存。
我的问题是专门何时更新缓存:
答案 0 :(得分:0)
我们对使用MediatR的项目有类似的需求,最终将缓存合并到中介程序管道中,包括您所描述的缓存失效。
基本前提是我们在管道中插入了两种不同的行为,一种用于缓存来自请求的响应,另一种用于使来自另一请求的缓存的请求响应无效。
这两种行为之间存在一些相互作用,因为它们需要交换缓存密钥才能使正确的请求无效。
我最近将其中一些工作拉到一个独立的库中,理论上可以使用MediatR将其按原样放置到任何项目中。就您而言,您可能只想看看我们在这里使用的技术,然后根据需要重新创建它们。
在这里,我将为您指向项目页面,在此页面上的主页上的“入门”链接下有一些文档,而不是在此进行重复: https://github.com/Imprise/Imprise.MediatR.Extensions.Caching
我认为,缓存失效使整个过程极其简单明了,但是在某些情况下,我们需要对失效发生的时间进行更好的控制。在这些情况下,我们采取的另一种方法是将ICache<TRequest, TResponse> cache
注入INotificationHandler
中,然后根据需要手动调用_cache.Remove(key);
。然后,从您知道应该无效的任何请求中,仅引发由INotificationHandler
处理的通知,例如_mediator.Publish(SomethingUpdated);
答案 1 :(得分:0)
我的建议是使用缓存行为来处理实现某种 ICacheableRequest 标记接口的请求,并将缓存失效作为相应更新/删除命令处理程序中的一个步骤(如您在第 1 点中提到的那样)。
如果您选择创建无效者行为,则存在一些问题。
首先,不清楚该命令是否使缓存无效。每当我需要检查更新/删除实体时发生了什么时,我只需遵循命令处理程序,通过创建单独的缓存失效器没有副作用(更难遵循)。
第二,即使将失效代码放在单独的文件中更符合 SRP,您也必须选择放置缓存失效器类的位置。它是在缓存查询旁边还是在使缓存无效的命令处理程序旁边?
第三,在许多情况下,您没有足够的关于用于在关联命令中缓存请求的密钥的信息,您只会在 CommandHandler 中获得该信息和任何其他额外的失效条件。