web-dev-qa-db-ja.com

Asp.net C#mvcで多くのデータベースクエリを防ぐためにデータベーステーブルをキャッシュする方法

Asp.net mvc 4(c#)を使用して独自のcmsを構築し、いくつかのデータベースデータをキャッシュします。ローカライズ、検索カテゴリ(ロングテール、各カテゴリには独自のサブおよびサブサブカテゴリがあります)など..

ページリクエストごとに30〜100件を超えるクエリになる可能性があるため、常にデータベースをクエリするのはやり過ぎです。ただし、ユーザーがデータベースを更新することはほとんどありません。

だからそれを行うための最良の方法(パフォーマンスと利便性)は何ですか?

アクションのOutputCacheの使用方法は知っていますが、この状況で必要なものではなく、htmlをキャッシュしますが、たとえば、自分のヘルパー@html.Localization("Newsletter.Tite")が値を取得することです言語、またはデータなどとやり取りする他のヘルパー.

アプリケーションが最初に呼び出されたときにのみ、必要なデータをキャッシュし、キャッシュの場所を操作する必要があるとは(確かではありませんが)考えていますが、それについての経験もありません。

27
Daniel Ezra

組み込みの MemoryCache を使用して、データベースから取得した結果セット全体を保存できます。

典型的なパターン:

MyModel model = MemoryCache.Default["my_model_key"] as MyModel;
if (model == null)
{
    model = GetModelFromDatabase();
    MemoryCache.Default["my_model_key"] = model;
}

// you could use the model here
31
Darin Dimitrov

ドロップダウンに表示されるデータのような一般的なデータベースデータをキャッシュする必要がありました。 MemoryCacheを使用しました。そして、依存性注入にEntity Framework code firstAutofacを使用しました。

ここに私が私の解決策で行ったことの一部がありますが、あなたにはうまくいかないかもしれませんが、私にはうまくいきましたが、完璧ではありませんが、多くのクリーンアップが必要です。

私のICacheManagerインターフェイス:

public interface ICacheManager
{
     T Get<T>(string key);

     void Set(string key, object data, int cacheTime);

     bool IsSet(string key);

     void Remove(string key);

     void Clear();
}

私のCacheManagerクラス:

public class CacheManager : ICacheManager
{
     private ObjectCache Cache
     {
          get
          {
               return MemoryCache.Default;
          }
     }

     public T Get<T>(string key)
     {
          return (T)Cache[key];
     }

     public void Set(string key, object data, int cacheTime)
     {
          if (data == null)
          {
               return;
          }

          CacheItemPolicy policy = new CacheItemPolicy();
          policy.AbsoluteExpiration = DateTime.Now + TimeSpan.FromMinutes(cacheTime);

          Cache.Add(new CacheItem(key, data), policy);
     }

     public bool IsSet(string key)
     {
          return (Cache.Contains(key));
     }

     public void Remove(string key)
     {
          Cache.Remove(key);
     }

     public void Clear()
     {
          foreach (var item in Cache)
          {
               Remove(item.Key);
          }
     }
}

私のキャッシングの拡張クラス:

public static class CacheExtensions
{
     public static T Get<T>(this ICacheManager cacheManager, string key, Func<T> acquire)
     {
          return Get(cacheManager, key, 60, acquire);
     }

     public static T Get<T>(this ICacheManager cacheManager, string key, int cacheTime, Func<T> acquire)
     {
          if (cacheManager.IsSet(key))
          {
               return cacheManager.Get<T>(key);
          }
          else
          {
               var result = acquire();

               cacheManager.Set(key, result, cacheTime);

               return result;
          }
     }
}

これが、リポジトリクラスでの使用方法です。このメソッドは、ドロップダウンに表示されるすべての銀行のリストを返します。

public class BankRepository : RepositoryBase<Bank>, IBankRepository
{
     private readonly ICacheManager cacheManager;
     private const string BanksAllCacheKey = "banks-all";

     public BankRepository(IDatabaseFactory databaseFactory, ICacheManager cacheManager)
          : base(databaseFactory)
     {
          Check.Argument.IsNotNull(cacheManager, "cacheManager");

          this.cacheManager = cacheManager;
     }

     public IEnumerable<Bank> FindAll()
     {
          string key = string.Format(BanksAllCacheKey);

          return cacheManager.Get(key, () =>
          {
               var query = from bank in DatabaseContext.Banks
                           orderby bank.Name
                           select bank;

               return query.ToList();
          });
     }
}

これがお役に立てば幸いです。これは非常に単純な実装ですが、私には役立ちます。 ASP.NET MVCでキャッシュ戦略を使用する方法に関する多くのオンライン記事があります。ちょうどGoogle it。

32
Brendan Vogt

キャッシュの実装を選択する前に考慮すべき点がいくつかありますが、決定する必要がある主なことの1つは、データアクセス時、モデル作成時、またはUI生成時にキャッシュを発生させるポイントです。これらの場所の1つまたはすべてですか?

いくつかのオプションがありますが、一般的なデータキャッシュには System.Runtime.Caching.MemoryCache 、またははるかに柔軟でやりがいのあるものについては、 Redis のようなNoSQLを使用した実装を見ることができます。

データキャッシュにはMemoryCacheを使用できますが、ビューモデルを構成する集計のキャッシュにはRedisを使用できます。 Redisを使用した場合、もちろんこれを使用してすべてのキャッシュを処理できます。利点は、すべてのデータがアプリケーションの再起動後も持続することです。欠点は、CMSを実行するための追加要件になることです。

考慮すべきその他のことは、一貫性(一部のIoCの使用が役立つ)と、更新後にデータを無効にすることです。したがって、キャッシュを更新するいくつかの手段があります。

bestアプローチに関しては、新しいCMSアプリケーションを作成している場合は、小規模/単純に開始し、段階的に構築してください。最初は完璧ではないかもしれませんが、アプローチに一貫性があり明確である限り、あなたがやったことを基に簡単に構築したり、交換したり、別の/より良いことを試してみてください。

4
Digbyswift