0

ここで示している例は、問題をできるだけ明確に説明するためのものであり、実際の実装や製品コードではありません。

また、何かがバックエンドから保存または返された場合、キャッシュされると仮定しましょう。それがどこでどのように発生するかの例を、コードから省略しました。

この問題の範囲については、MyType コレクションは常に小さく、かなり静的であり、アプリケーションの起動時にバックエンドからすべてを一度取得し、アプリケーションがシャットダウンされるまでキャッシュされたコピーを再利用することも想定する必要があります。これが、GetCached(id)andが実際にはandGetBackend(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-リストを更新時に報告する監視可能なコレクションに変更できる場合、アイテムが削除されたときに通知され、同じでない場合はカウンターで確認してリロードできます。

3- 監視可能なコレクションを使用できない場合は、CacheExpiray ポリシーの概念を使用できます。このポリシーでは、一定期間後にソースから自身をリロードするキャッシュをシミュレートできます。

于 2013-03-11T08:08:27.623 に答える
0

利用可能ないくつかのオプションがあるかもしれません。

まず、有効期限キャッシュを使用します。現在のキャッシュに特定の有効期限を設定するだけです。時間が経過した場合は、データを更新してください。ただし、このパターンはできません。

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

ただし、最新のデータを確実に取得したい場合は、通常、次の方法を使用します。

まず、キャッシュが生成されたときに現在のタイムスタンプを設定します。いくつかの例:

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 に答える