Orchard CMS中缓存的使用

发布于:
分类: Orchard CMS Tagged

Orchard缓存的优点和机制:

多级缓存:

Orchard缓存的多级缓存控制机制是非常值得称道的,他可以将有依赖关系的对象自动关联起来进行自动控制,比如:A对象是从B对象得到的,这时候如果B对象过期,那么A对象也会自动过期;这里可以看到所有的缓存是存放在一个ConcurrentDictionary结构里的,这个ConcurrentDictionary可以保证线程安全。

使用简单:

Orchard抛弃传统的传统get set的缓存方式,Orchard缓存的管理都只提供了一个Get方面没有其他Add、Update等等的东西.从缓存类里Get的方法的实现我们知道, 当程序无法根据TKey获取到结果的时候,就会创建一个新的结果同时保存到缓存里。

过期机制:

Orchard的缓存拥有强大的过期机制,实际上他的根本是一个失效令牌的机制,令牌只有一个属性: bool IsCurrent 如果IsCurrent==false时Cache过期,而客户代码可以通过实现不同的IVolatileProvider来实现各种不同的过期机制。

优雅的代码风格:

在Orchard.Framework的Caching目录下有18个文件,有兴趣的同学可以读读源码,写的非常不错。

下面我们用一段简单的代码来演示一下怎么使用其缓存:

private PackagesStatusResult GetPackages(PackagingSource packagingSource) {
            // Refresh every 23 hours or when signal was triggered
            return _cacheManager.Get(packagingSource.FeedUrl, ctx => {
                ctx.Monitor(_clock.When(TimeSpan.FromMinutes(60 * 23)));
                ctx.Monitor(_signals.When("PackageUpdateService"));

                // We cache exception because we are calling on a network feed, and failure may
                // take quite some time.
                var result = new PackagesStatusResult {
                    DateTimeUtc = _clock.UtcNow,
                    Entries = new List<UpdatePackageEntry>(),
                    Errors = new List<Exception>()
                };
                try {
                    result.Entries = GetPackagesWorker(packagingSource);
                }
                catch (Exception e) {
                    result.Errors = new[] { e };
                }
                return result;
            });
        }

上面展示的是基于时间的缓存过期机制,您也可以监测数据和其他环境变量的变化,来改变其机制蛤需要将_clock换成_Signals,比如下面这个使用:

private ContentTypeRecord AcquireContentTypeRecord(string contentType) {
            var contentTypeId = _cacheManager.Get(contentType + "_Record", ctx => {
                ctx.Monitor(_signals.When(contentType + "_Record"));

                var contentTypeRecord = _contentTypeRepository.Get(x => x.Name == contentType);

                if (contentTypeRecord == null) {
                    //TEMP: this is not safe... ContentItem types could be created concurrently?
                    contentTypeRecord = new ContentTypeRecord { Name = contentType };
                    _contentTypeRepository.Create(contentTypeRecord);
                }

                return contentTypeRecord.Id;
            });

            // There is a case when a content type record is created locally but the transaction is actually
            // cancelled. In this case we are caching an Id which is none existent, or might represent another
            // content type. Thus we need to ensure that the cache is valid, or invalidate it and retrieve it 
            // another time.
            
            var result = _contentTypeRepository.Get(contentTypeId);

            if (result != null && result.Name.Equals(contentType, StringComparison.OrdinalIgnoreCase) ) {
                return result;
            }

            // invalidate the cache entry and load it again
            _signals.Trigger(contentType + "_Record");
            return AcquireContentTypeRecord(contentType);
        }

上面的代码中28行:_signals.Trigger(contentType + “_Record”);  作用为使其缓存过期。

留下评论

您的电子邮箱地址不会被公开。 必填项已用 * 标注