Caching and generic query using NHibernate [.NET Core]

One of the important aspects in API design is to reduce the number of fetch request to database. NHibernate provides 2 levels of caching, with the first level cache persist through a session only, while the 2nd level cache persists across multiple sessions.

The second level cache can be implemented by installing the NuGet package of NHibernate.Caches.SysCache. Then, it involves some configuration setup to utilize the cache feature. However, there is an alternative way that exists in .NET Core which we could use to build a simpler cache.


The caching that we could use is IMemoryCache. Firstly, we could setup the cache during ConfigureServices.


public void ConfigureServices(IServiceCollection services)
{
   services.AddMemoryCache();
}

Then, assuming we want to retrieve all the records from a table called DailySales, and we want to keep the records in the cache for 1 minute, we could do the following.

private readonly IMemoryCache cache;

public DBHelper(IMemoryCache memoryCache)
{    
  this.cache = memoryCache;
}

public async Task<List<T>> GetDbRecordsList<T>()
{
  var cacheKey = typeof(T).Name;

  if (!cache.TryGetValue(cacheKey, out List<T> cacheEntry))
  {
    cacheEntry = await GetSession().Query<T>().ToListAsync();
    cache.Set(cacheKey, cacheEntry, new MemoryCacheEntryOptions().SetAbsoluteExpiration(TimeSpan.FromMinutes(1)));
  }

  return cacheEntry;
}
We could easily use the method defined above to retrieve the list.
var dailySalesList = await GetDbRecordsList<DailySales>();

Furthermore, below are some of the useful generic methods that I feel I use often alongside NHibernate.
// Check if a record exists or not
public async Task<bool> IsRecordExistsAsync<K>(Expression<Func<K, bool>> condition) where K : class
{
    bool isExist = await GetSession().QueryOver<K>()
                                     .Where(condition)
                                     .RowCountAsync() > 0;
    return isExist;
}

// Return a record based on the given condition
public async Task<T> GetRecordAsync<T>(Func<T, bool> condition) where T : class
{
    return (await GetDbRecordsList<T>()).FirstOrDefault(condition));
}

// Return a list of records based on the given condition
public async Task<List<T>> GetRecordListAsync<T>(Func<T, bool> condition) where T : class
{
    return (await GetDbRecordsList<T>()).Where(condition)).ToList();
}

Comments

Popular posts from this blog

ASP.NET Core service locator pattern

Ways to perform eager loading via NHibernate