Reputation: 236
I have a method that will expire null items immediately, however I wanted to know if there w as better way to do this for all memory cache items instead of repeating the same code over and over
output = _cache.GetOrAdd("GetRecordUri" + 123, entry =>
{
var record = internalGetRecordUri();
if (record == null)
// expire immediately
entry.AbsoluteExpirationRelativeToNow = new TimeSpan(-1, 0, 0, 0);
else
entry.AbsoluteExpirationRelativeToNow = new TimeSpan(1, 0, 0, 0);
return record;
});
The code in bold seems redundant Is there an extension that I can use that will do the same?
Upvotes: 0
Views: 1611
Reputation: 5226
It would be nice if you could signal in addtemFactory
that the value is not to be cached at all, e.g.
output = _cache.GetOrAdd("GetRecordUri_" + id, entry =>
{
var record = internalGetRecordUri(id);
if (IsError(record))
entry.IsValidToCache = false; // not actual
return record;
});
But there is no such mechanism, without throwing an exception.
Setting the AbsoluteExpirationRelativeToNow
to a zero or negative value does not work, it throws a ArgumentOutOfRangeException
:
System.ArgumentOutOfRangeException
Message=The relative expiration value must be positive. (Parameter 'AbsoluteExpirationRelativeToNow')
Actual value was 00:00:00.
Source=Microsoft.Extensions.Caching.Memory
StackTrace:
at Microsoft.Extensions.Caching.Memory.CacheEntry.set_AbsoluteExpirationRelativeToNow(Nullable`1 value)
Throwing an exception in the addtemFactory
, is however supported and effective to prevent caching of the result: "LazyCache Stops you inadvertently caching an exception by removing Lazys that evaluate to an exception". I recommend using a more meaningful exception type than a ArgumentOutOfRangeException
e.g.
output = _cache.GetOrAdd("GetRecordUri_" + id, entry =>
{
var record = internalGetRecordUri(id);
if (IsError(record))
throw new SomeException("GetRecordUri failed for " + id); // actual
return record;
});
You just have to now think about where the exception is caught.
Upvotes: 1
Reputation: 12201
You can place this check in separate method:
public void SetAbsoluteExpiration(Entry entry, object value) // change Entry to correct type
{
if (value is null) // or if (value == null)
// expire immediately
entry.AbsoluteExpirationRelativeToNow = new TimeSpan(-1, 0, 0, 0);
else
entry.AbsoluteExpirationRelativeToNow = new TimeSpan(1, 0, 0, 0);
}
And call it everywhere you need:
output = _cache.GetOrAdd(
"GetRecordUri" + 123, entry => {
var record = internalGetRecordUri();
SetAbsoluteExpiration(entry, record);
return record;
});
Upvotes: 0