2013-07-05 117 views
2

我正在編寫一個管理智能應用程序,它需要相當多的複雜數據庫查詢,而且查詢的代價相當昂貴。爲了提高性能,我使用Memcached來存儲儘可能多的內存。什麼是緩存數據庫查詢的最佳方法

這導致了很多重複我的代碼,我渴望擺脫和建立一個更清潔的數據訪問解決方案。相當多的我的數據訪問功能已經結束了尋找這樣的..

public int NumberOfTimeouts(DateTime date, int? applicationId) 
{ 
    var functionCacheKey = "NumberOfTimeouts"; 
    var cacheKey = string.Format("{0}-{1}-{2}-{3}", RepositoryCacheKey, functionCacheKey, date, applicationId); 
    var cachedNumberTimeouts = _cache.Retrieve(cacheKey); 
    if (cachedNumberTimeouts != null) 
    { 
     return (int)cachedNumberTimeouts; 
    } 

    //query logic here, calculates numberOfTimeouts 

    UpdateCache(date, cacheKey, numberOfTimeouts); 
    return numberOfTimeouts; 
} 

我只是不太確定的標準方法是什麼這個,難道涉及使用自定義屬性類或類似的東西?

回答

0
+0

這似乎是一個很好的解決方案,如果我正在更新記錄,但是這個應用程序不會觸及實際的業務邏輯,並且更多地用於從數據庫讀取數據。 – lisburnite

1

這是一個橫切關注點。 Decorator模式可能適用於此處。我可能在這個模式沒有經驗,但是我會給它一個鏡頭

// model 
public class CustomObject 
{ 
    public int Id { get; set; } 
} 
// interface 
public interface IRepository<T> 
{ 
    IEnumerable<T> Find(Expression<Func<T, bool>> expression); 
} 
public interface ICacheableRepository<T> 
{ 
    IEnumerable<T> Find(Expression<Func<T, bool>> expression, Func<int> cacheKey); 
} 
public interface IRepositoryCacheManager<T> 
{ 
    IEnumerable<T> Get(int key); 
    bool Any(int key); 
    void Add(int key, IEnumerable<T> result); 
} 
// cache manager 
public class RepositoryCacheManager<T> : IRepositoryCacheManager<T> 
{ 
    private Dictionary<int, IEnumerable<T>> cache = new Dictionary<int,IEnumerable<T>>(); 
    #region IRepositoryCache<T> Members 

    public IEnumerable<T> Get(int key) 
    { 
     return cache[key]; 
    } 

    public bool Any(int key) 
    { 
     IEnumerable<T> result = null; 
     return cache.TryGetValue(key, out result); 
    } 

    public void Add(int key, IEnumerable<T> result) 
    { 
     cache.Add(key, result); 
    } 

    #endregion 
} 

// cache repository decorator 
public class CachedRepositoryDecorator<T> : IRepository<T>, ICacheableRepository<T> 
{ 
    public CachedRepositoryDecorator(IRepositoryCacheManager<T> cache 
     , IRepository<T> member) 
    { 
     this.member = member; 
     this.cache = cache; 
    } 

    private IRepository<T> member; 
    private IRepositoryCacheManager<T> cache; 

    #region IRepository<T> Members 

    // this is not caching 
    public IEnumerable<T> Find(Expression<Func<T, bool>> expression) 
    { 
     return member.Find(expression); 
    } 

    #endregion 

    #region ICacheableRepository<T> Members 

    public IEnumerable<T> Find(Expression<Func<T, bool>> expression, Func<int> cacheKey) 
    { 
     if (cache.Any(cacheKey())) 
     { 
      return cache.Get(cacheKey()); 
     } 
     else 
     { 
      IEnumerable<T> result = member.Find(expression); 
      cache.Add(cacheKey(), result); 
      return result; 
     } 
    } 

    #endregion 
} 
// object repository 
public class CustomObjectRepository : IRepository<CustomObject> 
{ 
    #region IRepository<CustomObject> Members 

    public IEnumerable<CustomObject> Find(Expression<Func<CustomObject, bool>> expression) 
    { 
     List<CustomObject> cust = new List<CustomObject>(); 
     // retrieve data here 
     return cust; 
    } 

    #endregion 
} 
// example 
public class Consumer 
{ 
    // this cache manager should be persistent, maybe can be used in static, etc 
    IRepositoryCacheManager<CustomObject> cache = new RepositoryCacheManager<CustomObject>(); 
    public Consumer() 
    { 
     int id = 25; 

     ICacheableRepository<CustomObject> customObjectRepository = 
      new CachedRepositoryDecorator<CustomObject>(
       cache 
       , new CustomObjectRepository() 
       ); 
     customObjectRepository.Find(k => k.Id == id,() => { return id; }); 
    } 
} 

請注意:

  • 我沒有測試此代碼,不知道是否是功能齊全或不。我剛剛描述的例證
  • 是的,這有碼味由具有ICacheableRepository超載爲Find,但是我不能使用Expression作爲KeyDictionary

的優點:

  • 這CachedRepositoryDe​​corator可用於ANY通用存儲庫(可重複使用)
  • 選擇過程中沒有高速緩存邏輯,強調SRP

的缺點:

  • 難以實現無ORM,也許你會需要一些調整與反思,使其工作沒有ORM
  • 硬盤在開始
  • 佈線困難的理解,而不DI容器

感謝這個article :)

+0

謝謝,我會試一試,但正如你所說,它看起來很難理解! – lisburnite

相關問題