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
    }
}

在这种情况下你会怎么做?是否存在有助于检测情况并从后端获取新集合的模式。最好的做法是什么?

4

2 回答 2

1

恕我直言 ,

1-如果您没有在数据库之间添加,那么您可以保留一个计数器并在启动应用程序时填充它。

2- 如果您可以将 List 更改为 Observable Collection,该集合会在更新时进行报告,以便在删除项目时通知您,并且您可以与计数器检查是否相同,您可以重新加载它。

3-如果不可能使用可观察集合,那么您可以使用 CacheExpiray 策略的概念,您可以在其中模拟缓存,该缓存将在一段时间后从源重新加载。

于 2013-03-11T08:08:27.623 回答
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>();
    }
}
于 2013-03-11T08:10:08.297 回答