ここで示している例は、問題をできるだけ明確に説明するためのものであり、実際の実装や製品コードではありません。
また、何かがバックエンドから保存または返された場合、キャッシュされると仮定しましょう。それがどこでどのように発生するかの例を、コードから省略しました。
この問題の範囲については、MyType コレクションは常に小さく、かなり静的であり、アプリケーションの起動時にバックエンドからすべてを一度取得し、アプリケーションがシャットダウンされるまでキャッシュされたコピーを再利用することも想定する必要があります。これが、GetCached(id)
andが実際にはandGetBackend(id)
の単なるラッパーである理由です。ListCached
ListBackend
次のような単純なリポジトリがあるとします。
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
}
}
このような状況であなたはどうしますか?状況を検出し、バックエンドから新しいコレクションを取得するのに役立つパターンはありますか? ベストプラクティスは何ですか?