HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Cached repository implementation for small lists of data models

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
cachedsmallforrepositorylistsimplementationmodelsdata

Problem

I have been using Repositories in my ASP.NET MVC projects and I felt the need to fully cache small tables data (dictionaries, cities, countries etc.). This kind of information is changed (very) infrequently, so caching brings a great benefit. Also, I thought it would be nice to have cached repositories setup as simple as possible (even invisible to the services using them).

My inspiration was this nice article, but I needed to cache entire table content, rather than query results.

Here it is what I have managed to do so far:

1) Repository interface

public interface IRepository : IRepository
    where T : class
{
    IQueryable AllNoTracking { get; }

    IQueryable All { get; }
    DbSet GetSet { get; }

    T Get(int id);

    void Insert(T entity);
    void BulkInsert(IEnumerable entities);
    void Delete(T entity);
    void RemoveRange(IEnumerable range);
    void ClearAll();
    void Update(T entity);

    IList ExecProcedure(string procedureName, IList> parameters);
    void Truncate();

    IList Select(string queryText);
}

/// 
/// provides methods specific to a cached repository (as opposed to those from normal repositories)
/// 
public interface ICachedRepository where T : class, new()
{
    string CacheKey { get; }

    void InvalidateCache();
    void InsertIntoCache(T item);
}


2) Cached repository should work above a normal repository, that's why a cached repository requires a reference to a normal one. It is not fully implemented, but the core functionality is there:

```
public class CachedRepository : ICachedRepository, IRepository where T : class, new()
{
#region Properties
private int AbsoluteExpiration { get; }
private int SlidingExpiration { get; }
#endregion

#region Variables
private readonly IRepository _modelRepository;

private static readonly object CacheLockObject = new object();
#endregion

#region Properties
public string CacheKey => $"CachedRepository-{typeof(T).Name}";

#endreg

Solution

Cached repository should work above a normal repository, that's why a cached repository requires a reference to a normal one.

This clearly indicates the Decorator Pattern but you are not using it right. The second ICachedRepository is a bad choice here (unless it really provides different methods but you didn't show it so I cannot really say anything about it).

You should have a normal repository implementing the IRepository interface (let's assume T is int):

class MyRepository : IRepository 
{
    ... 
}


and another one that will provide caching for the first one but being a IRepository too:

class MyCachedRepository : IRepository 
{
    private readonly IRepository _repository;

    public MyCachedRepository(IRepository repository)
    {
        _repository = repository;
    }

    ...
}

Code Snippets

class MyRepository : IRepository<int> 
{
    ... 
}
class MyCachedRepository : IRepository<int> 
{
    private readonly IRepository<int> _repository;

    public MyCachedRepository(IRepository<int> repository)
    {
        _repository = repository;
    }

    ...
}

Context

StackExchange Code Review Q#142250, answer score: 5

Revisions (0)

No revisions yet.