2013-03-11 60 views
0

请记住,示例我在这里展示只是为了尽可能明确,没有任何实际实施或生产代码说明问题。饲养缓存与后端

而且,我们假设如果有什么被存储或从后端返回,它会被缓存。我从代码中省略的例子和发生的地方。

对于这个问题的范围,我们还必须假设,MyType集合总是很小,相当静态,当应用程序启动时,它将从后端获取一切,并重用缓存副本,直到应用程序关闭。这就是为什么GetCached(id)GetBackend(id)实际上来说是ListCachedListBackend的包装。

假设我们有以下一种简单的存储库:

public class MyRepository : IRepository<MyType> 
{ 
    public IEnumerable<MyType> GetAll() 
    { 
     // Will return cached items if present 
     return ListCached ?? ListBackend; 
    } 

    public MyType Get(int id) 
    { 
     return GetCached(id) ?? GetBackend(id); 
    } 


    private MyType GetBackend(int id) 
    { 
     return ListBackend.FirstOrDefault(type => type.Id == id); 
    } 

    private MyType GetCached(int id) 
    { 
     return ListCached.FirstOrDefault(type => type.Id == id); 
    } 

    protected IEnumerable<MyType> ListBackend 
    { 
     get { return Backend.GetAll<MyType>(); } 
     set { Backend.StoreAll<MyType>(value); } 
    } 

    public IEnumerable<MyType> ListCached 
    { 
     get { return Cache.GetAll<MyType>(); } 
     set { Cache.StoreAll<MyType>(value); } 
    } 

    public void Store(MyType value) 
    { 
     Backend.Store(value); 
    } 
} 

而这里的挑战:

class Program 
{ 
    static void Main(string[] args) 
    { 
     #region Handling Missing Objects in Cache 
     // We have a repository 
     var rep = new MyRepository(); 

     // Into which we put stuff (3 for the demo) 
     rep.Store(new MyType { Id = 1 }); 
     rep.Store(new MyType { Id = 2 }); 
     rep.Store(new MyType { Id = 3 }); 

     // And the repository, after this, returns 3 items 
     // The items are returned from cache 
     var count = rep.GetAll().Count(); // Returns 3 

     // However, somewhere else in the application, it happens so, 
     // for any reason, bug, programmer error, photon from sun hitting the cpu 
     // or tinfoil-hat left home in rush, 
     // that one item gets removed from the cache 
     Cache.Remove(new MyType { Id = 2 }); 

     // After which, only 2 items are returned from the repository 
     // since the cache exists, it won't even try to hit the database 
     count = rep.GetAll().Count(); 

     // Now count = 2, while WE know the backend has now 3 items 
     // how would the program detect it and get a fresh copy from backend? 
     #endregion 
    } 
} 

,你会在这种情况下怎么办?是否有模式可以帮助检测情况并从后端获取新鲜收集。最佳实践是什么?

回答

1

恕我直言,

1 - 如果不加之间在到数据库中,那么你可以保留一个计数器并填充它,当你启动应用程序。

2-如果您可以将List更改为Observable Collection,它会在更新时报告以便删除某个项目时,您将收到通知,并且您可以检查计数器,如果它不相同,您可以重新加载它。

3-如果无法使用观察到的集合,那么你可以使用CacheExpiray政策,在其中您可以模拟一个缓存一些时间后,将自动重新加载从源代码的概念。

0

有可能一些可用的选项。

首先,使用过期的缓存。只是为当前缓存设置特定的过期时间。如果时间已过,则刷新数据。然而,这种模式不能

if(cacheExpiry){ 
    cacheList = GetListFromDatabase(); 
} 

但是,如果你想确保获得最新的数据,通常我用这个方法:

1,生成缓存时设置当前的时间戳。一些插图:

DateTime lastCache = DateTime.Now 

然后在你的sql中,有一个最新修改日期时间(例如UPDATE_STAMP)的表。然后每次修改所需的缓存表时,将UPDATE_STAMP表中的记录更新为当前日期。例如:

Update MyTable set //your code here 
Update UPDATE_STAMP set DATE_TIME = GETDATE() 

然后每次你得到ListCached,比较最新的缓存时间与UPDATE_STAMP表记录。例如:

public IEnumerable<MyType> ListCached 
{ 
    get { 
     DateTime latestModified = GetLatestModifiedDate(); 
     if(lastCache<latestModified) Cache = GetListFromDatabase(); 
     latestModified = DateTime.Now; 
     return Cache.GetAll<MyType>(); 
    } 
} 
+0

每次你需要得到缓存列表,你去数据库检查它是否同步,你不觉得它是以某种方式破坏缓存概念。 – TalentTuner 2013-03-11 08:17:38