I've been busting my head on this, and I'm sure it's something silly.
I've created a custom attribute:
[AttributeUsage(AttributeTargets.Method)]
public class CacheAttribute : Attribute
{
public string[] Keys { get; set; }
private int _retention;
public int Retention
{
get => _retention;
set
{
if (SlidingExpiration && value == 0)
{
throw new ArgumentException("Retention must have a value when SlidingExpiration is true.");
}
_retention = value;
}
}
public bool SlidingExpiration { get; set; }
public CacheAttribute(string[] keys = null, int retention = 0, bool slidingExpiration = false)
{
Keys = keys;
Retention = retention;
SlidingExpiration = slidingExpiration;
}
}
I'm using it like this:
[HttpPost("[action]")]
[Cache(Keys = new[] { "TableName", "d" }, SlidingExpiration = true)]
public ActionResult<string> ReadDataFromMsSqlDB([FromBody] DatabaseRequestModel requestModel, CancellationToken cancellationToken = default)
{
List<SqlParameter> parameterList = new();
List<SqlParamsModel> sqlParams = requestModel.Parameters ?? new List<SqlParamsModel>();
SqlParameter[]? parameterArray = null;
if (sqlParams.Count > 0)
{
foreach (var parameter in sqlParams)
{
parameterList.Add(new SqlParameter($"@{parameter.Key}", parameter.Value));
}
parameterArray = parameterList.ToArray();
}
// Create
DataTable resultSet = _msSql.ExecuteQuery(requestModel.Query ?? string.Empty, parameterArray);
string jsonResult = JsonConvert.SerializeObject(resultSet);
return Ok(jsonResult);
}
And ExecuteQuery is:
public DataTable ExecuteQuery(string query, SqlParameter[]? parameters)
{
StackFrame stackFrame = new StackFrame(1); // Skip one frame to get the caller's frame
MethodBase? callingMethod = stackFrame.GetMethod();
var cacheAttribute = callingMethod?.GetCustomAttribute<CacheAttribute>();
// If CacheAttribute is present and caching is enabled, try to fetch data from cache
if (cacheAttribute != null)
{
string cacheKey = GenerateCacheKey(query, parameters);
var cachedItem = _cache.GetAsync<DataTable>(cacheKey);
// If cached data is found, return it
if (cachedItem.Exception == null)
{
DataTable cachedData = cachedItem.Result;
return cachedData;
}
}
// ... some more code
}
The cacheAttribute variable has the data I'm supplying in the attribute (I can see keys' value and I can see that SlidingExpiration is indeed true, but when I'm debugging the code, I can see the CacheAttribute constructor has all the variables still with their default value - meaning, it's not being instantiated correctly, and as a result, the Retention getter is not throwing an exception as expected).
What am I doing wrong?
Thanks
I tried to make the Retention getter to kick in, and fire the exception.
It didn't happen, as the cacheAttribute class is not being instantiated.