Open sandboxFocusImprove this doc

CAC002: Invalidated Method Is Not Cached

Severity Error
Reported by PostSharp.Patterns.Caching
Message The [InvalidateCache] aspect applied to <InvalidatingMethod> cannot invalidate <CachedMethod>: this method is not cached by the [Cache] aspect.

Cause

The InvalidateCacheAttribute aspect removes from the cache the values of the methods that you name in its constructor, each time the method to which you apply it, <InvalidatingMethod>, is called. PostSharp looks for these methods by name in the type of <InvalidatingMethod>, or in the type that you pass to the constructor, and reports CAC002 when a method of that name, <CachedMethod>, exists but does not have the CacheAttribute aspect. The message is reported on <InvalidatingMethod>.

When several overloads have this name, PostSharp ignores the overloads that are not cached as long as one overload can be invalidated, and reports CAC002 for each of them only when none can.

In the following example, SetPrice invalidates GetPrice, but GetPrice is not cached.

using System;
using System.Collections.Generic;
using PostSharp.Patterns.Caching;
using PostSharp.Patterns.Caching.Backends;

namespace Errors.CAC002_Error;

public class ProductCatalog
{
    private readonly Dictionary<string, decimal> prices = new() { ["TEA-01"] = 4.50m };

    public decimal GetPrice( string productId )
    {
        Console.WriteLine( $"Reading the price of {productId}." );

        return this.prices[productId];
    }

    [InvalidateCache( nameof(GetPrice) )]
    public void SetPrice( string productId, decimal price ) // GetPrice has no [Cache] aspect, so there is nothing to invalidate.
    {
        this.prices[productId] = price;
    }
}

public static class Program
{
    public static void Main()
    {
        CachingServices.DefaultService.Backend = new MemoryCachingBackend();

        var catalog = new ProductCatalog();
        Console.WriteLine( catalog.GetPrice( "TEA-01" ) );
        Console.WriteLine( catalog.GetPrice( "TEA-01" ) );
        catalog.SetPrice( "TEA-01", 5.00m );
        Console.WriteLine( catalog.GetPrice( "TEA-01" ) );
    }
}
error CAC002: CAC002_Error.cs(20,17): The [InvalidateCache] aspect applied to Errors.CAC002_Error.ProductCatalog.SetPrice(System.String, System.Decimal) cannot invalidate Errors.CAC002_Error.ProductCatalog.GetPrice(System.String): this method is not cached by the [Cache] aspect.

Resolution

  • Add the [Cache] aspect to the method that you want to invalidate.
  • If you named the wrong method, name the cached method instead. When the cached method belongs to another type, pass this type as the first argument of the constructor of [InvalidateCache].
  • If the method does not need to be cached, remove its name from the [InvalidateCache] aspect, or remove the aspect.

In the following example, GetPrice is cached, so the second call reads the price from the cache, and the call after SetPrice reads the new price.

using System;
using System.Collections.Generic;
using PostSharp.Patterns.Caching;
using PostSharp.Patterns.Caching.Backends;

namespace Errors.CAC002_Fixed;

public class ProductCatalog
{
    private readonly Dictionary<string, decimal> prices = new() { ["TEA-01"] = 4.50m };

    [Cache] // The method is cached, so SetPrice can invalidate it.
    public decimal GetPrice( string productId )
    {
        Console.WriteLine( $"Reading the price of {productId}." );

        return this.prices[productId];
    }

    [InvalidateCache( nameof(GetPrice) )]
    public void SetPrice( string productId, decimal price )
    {
        this.prices[productId] = price;
    }
}

public static class Program
{
    public static void Main()
    {
        CachingServices.DefaultService.Backend = new MemoryCachingBackend();

        var catalog = new ProductCatalog();
        Console.WriteLine( catalog.GetPrice( "TEA-01" ) );
        Console.WriteLine( catalog.GetPrice( "TEA-01" ) );
        catalog.SetPrice( "TEA-01", 5.00m );
        Console.WriteLine( catalog.GetPrice( "TEA-01" ) );
    }
}
Reading the price of TEA-01.
4.50
4.50
Reading the price of TEA-01.
5.00

See Also

Reference

InvalidateCacheAttribute
CacheAttribute

Other Resources

Removing Items From the Cache