坂本  篤司

坂本 篤司

1654967340

NCacheを使用したEntityFrameworkCoreでのキャッシュ

この記事では、NCacheを使用してEntityFrameworkCoreをキャッシングエンジンと統合する方法について説明します。この記事では、コンソールアプリケーションでEntity Framework Coreをセットアップする方法と、NCacheを使用して、ネイティブのメモリ内分散キャッシュを使用してデータベースに対してより高速なリクエストを行う方法の実際的な例を示します。

Entity Framework Coreとは何ですか?

Entity Framework Coreは、Microsoftの最新のORMであるObject Relational Mapperであり、ソフトウェアアプリケーションがエンティティをさまざまなデータベースにマッピング、接続、および管理するのに役立ちます。Entity Framework Coreはオープンソースでクロスプラットフォームであり、Microsoftテクノロジを使用するソフトウェアで使用されるORMのトップ1です。

この記事を書いている時点で、Entity Framework Coreは、エンティティをデータベースに接続する2つの方法を提供しています。

  • コード最初に、プロジェクトのエンティティを最初に記述し、次にそれらのオブジェクトをデータベースに反映します。
  • データベースまず、データベースを最初に作成してから、プロジェクトのエンティティを生成します。

NCacheとは何ですか?

NCacheは、オープンソースおよびクロスプラットフォームのソフトウェアでもあります。そのキャッシュサーバーは、.NET、Java、Scala、Python、およびNode.js用のスケーラブルなメモリ内分散キャッシュを提供します。この記事では.NETテクノロジーに焦点を当てているため、NCacheを使用して次の使用法を利用できます。

  • ASP.NETセッション状態ストレージ。
  • ASP.NETビューステートキャッシング。
  • ASP.NET出力キャッシュ。
  • EntityFrameworkキャッシュ;
  • NHibernateの第2レベルのキャッシュ。

EntityFrameworkCoreを使用したNCache

Entity Framework CoreとNCacheを使用するアプリケーションの間にキャッシュのレイヤーを追加できます。これにより、クエリの応答時間が改善され、NCacheのキャッシュされたエンティティからデータを取得する限り、データベースへのラウンドトリップの必要性が減ります。 

キャッシングオプション

NCacheを使用すると、各リクエストから送信されるオプションのセットを変えることができます。つまり、効率を上げるために、使用している結果セットに基づいてキャッシュを異なる方法で使用できます。

実際のサンプルで見るように、NCacheへの各リクエストでキャッシュオプションを提供する必要があり、それらのオプションは次のとおりです。

  • AbsoluteExpirationTimeは、キャッシュされたアイテムが期限切れになる絶対時間を設定します。
    • データ型:日時
  • CreateDbDependencyは、結果セットからデータベースの依存関係を作成するかどうかを決定します。
    • データ型:ブール値
  • ExpirationTypeは、有効期限タイプを設定します。
    • 絶対の、
    • スライディング、
    • なし。
  • IsSyncEnabledは、期限切れのアイテムをデータベースと再同期する必要があるかどうかを設定します。
    • データ型:ブール値
  • 優先度、キャッシュに保存されているアイテムの相対的な優先度を設定します。
    • 普通、
    • 低い、
    • ノーマル以下、
    • 通常より上、
    • 高い、
    • 取り外し不可、
    • デフォルト
  • QueryIdentifier、結果セット識別子。
    • データ型:文字列。
  • ReadThruProviderは、キャッシュ同期用の読み取りスループロバイダーを設定します
    • データ型:文字列
  • SlidingExpirationTimeは、スライドの有効期限を設定します
    • データ型:TimeSpan
  • StoreAsは、アイテムの保存方法を設定します。
    • コレクション
    • SeperateEntities

延期された通話

NCacheには、Entity Framework Coreの遅延呼び出しを処理するための独自の拡張メソッドがあり、それらは3つの異なるグループに属しています。

  • 演算子を集約し、コレクションに対して操作を行います。FromCacheメソッドとFromCacheOnlyメソッドの両方で使用できます。
    • DeferredAverage。
      • Products.Select(o => o.UnitPrice).DeferredAverage()
    • DeferredCount
      • Customers.Select(c => c.Country).GroupBy(c => c).DeferredCount()
    • DeferredMin
      • Orders.Where(o => o.CustomerId == "VINET")。Select(o => o.RequiredDate).DeferredMin()
    • DeferredMax
      • Orders.Select(o => o.RequiredDate).DeferredMax()
    • DeferredSum
      • OrderDetails.Select(o => o.UnitPrice).DeferredSum()
  • 要素演算子、単一要素の操作を行います。FromCacheメソッドでのみ使用できます。
    • DeferredElementAtOrDefault
      • Customers.DeferredElementAtOrDefault(c => c.City == "London")
    • DeferredFirst
      • Customers.DeferredFirst(c => c.ContactTitle == "営業担当者")
    • DeferredFirstOrDefault
      • Customers.DeferredFirstOrDefault(c => c.ContactTitle == "営業担当者")
    • DeferredLast
      • Customers.DeferredLast(c => c.City == "London")
    • DeferredLastOrDefault
      • Customers.DeferredLastOrDefault(c => c.City == "London")
    • DeferredSingle
      • Customers.DeferredSingle(c => c.CustomerId == "ALFKI")
    • DeferredSingleOrDefault
      • Customers.DeferredSingleOrDefault(c => c.CustomerId == "ANATR")
  • その他。FromCacheメソッドでのみ使用できます。
    • DeferredAll
      • Products.DeferredAll(式)
    • DeferredLongCount
      • Products.DeferredLongCount()
    • DeferredContains
      • Products.DeferredContains(new Products {ProductId = 1})

キャッシング方法

キャッシュされたオブジェクトを操作するNCacheのメソッド:

  • 入れる

独自のオプションを使用して、単一のオブジェクトをキャッシュに挿入します。キャッシュキーを返します

var customerEntity = new Customers
   {
       CustomerId = "HANIH",
       ContactName = "Hanih Moos",
       ContactTitle = "Sales Representative ",
       CompanyName = "Blauer See Delikatessen"
   };

   //Add customer entity to database
   database.Customers.Add(customerEntity);
   database.SaveChanges();

   //Caching options for cache
   var options = new CachingOptions
   {
       QueryIdentifier = "CustomerEntity",
       Priority = Runtime.CacheItemPriority.Default,
   };

   //Add customer entity to cache
   Cache cache = database.GetCache();

   cache.Insert(customerEntity, out string cacheKey, options);
  • 削除(オブジェクトエンティティ)

キャッシュから1つのオブジェクトを削除します。

var cust = new Customers
  {
      CustomerId = "HANIH",
      ContactName = "Hanih Moos",
      ContactTitle = "Sales Representative",
      CompanyName = "Blauer See Delikatessen"
  };

  cache.Remove(cust);
  • 削除(文字列cacheKey)

キャッシュキーを渡してオブジェクトを削除します

cache.Remove("cacheKey");
  • RemoveByQueryIdentifier

クエリ識別子に一致するすべてのエンティティをキャッシュから削除します

Tag tag = new Tag(queryIdentifier);
cache.RemoveByQueryIdentifier(tag);

NCache拡張メソッドを使用したキャッシュ 

EntityFrameworkCore用のNCacheの拡張メソッド

  • GetCache

キャッシュインスタンスを取得します。

using (var context = new NorthwindContext())
{
Cache cache = context.GetCache();
}
  • FromCache

キャッシュされたデータがある場合は、データソースを経由せずに返されます。キャッシュされたデータがない場合、データはデータソースから返され、キャッシュされます。

var options = new CachingOptions
{
    StoreAs = StoreAs.SeperateEntities
};

var resultSet = (from cust in context.Customers
                 where cust.CustomerId == 10
                 select cust).FromCache(options);

結果セットからcacheKeyを返す

var options = new CachingOptions
{
    StoreAs = StoreAs.Collection
};

var resultSet = (from cust in context.Customers
                where cust.CustomerId == 10
                select cust).FromCache(out string cacheKey, options);
  • LoadIntoCache

すべてのリクエストは最初にデータソースに送られ、その結果セットをキャッシュして返します。

var options = new CachingOptions
    {
        StoreAs = StoreAs.SeperateEntities
    };

    var resultSet = (from custOrder in context.Orders
                     where custOrder.Customer.CustomerId == 10
                     select custOrder)).LoadIntoCache(options);

結果セットからキャッシュキーを返す

var options = new CachingOptions
{
    StoreAs = StoreAs.Collection
};

var resultSet = (from custOrder in context.Orders
                 where custOrder.Customer.CustomerId == 10
                 select custOrder)).LoadIntoCache(out string cacheKey, options);
  • FromCacheOnly

データソースには絶対に行きません。リクエストはキャッシュにのみ送信されます。一致する結果がキャッシュされていない場合は、空の結果セットとして返されます。

インクルードと結合はFromCacheOnly()ではサポートされていません。

var resultSet = (from cust in context.Customers
                 where cust.CustomerId == someCustomerId
                 select cust).FromCacheOnly();

NCacheの実装ステップバイステップ

0.前提条件

1.アプリケーション

  • .NET 6.0を対象とするC#コンソールアプリケーションを作成し、次のnugetsパッケージをインストールします。
    • EntityFrameworkCore.NCache
    • Microsoft.EntityFrameworkCore.SqlServer
    • Microsoft.EntityFrameworkCore.SqlServer.Design
    • Microsoft.EntityFrameworkCore.Tools
    • System.Data.SqlClient
    • System.Collections
  • Nugetパッケージをインストールすると、次のNCacheファイルがプロジェクトに挿入されます。
    • client.ncconf
    • config.ncconf
    • tls.ncconf

2.モデル

このサンプルでは、​​次のように非常に単純なモデル関係が作成されました。

  • 製品
[Serializable]
public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public double Price { get; set; }
    public List<Transaction> Transactions { get; set; }
    public Store Store { get; set; }
    public int? StoreId { get; set; }
}
[Serializable]
public class Store
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Location { get; set; }
    public ICollection<Product> AvailableProducts { get; set; }
    public ICollection<Consumer> RegularConsumers { get; set; }
}
  • 消費者
[Serializable]
public class Consumer
{
    public int Id { get; set; }
    public string Name { get; set; }
    public Store FavouriteStore { get; set; }
    public int? FavouriteStoreId { get; set; }
    public List<Transaction> Transactions { get; set; }
}
  • 取引
[Serializable]
public class Transaction
{
     public int Id { get; set; }

     public Consumer Consumer { get; set; }
     public int ConsumerId { get; set; }

     public Product Product { get; set; }
     public int ProductId { get; set; }
}
  • DBContext

DBContextクラスには、NCache初期化設定とモデルの関係があります。

public class SampleDbContext : DbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        // configure cache with SQLServer DependencyType and CacheInitParams
        CacheConnectionOptions initParams = new CacheConnectionOptions();
        initParams.RetryInterval = new TimeSpan(0, 0, 5);
        initParams.ConnectionRetries = 2;
        initParams.ConnectionTimeout = new TimeSpan(0, 0, 5);
        initParams.AppName = "appName";
        initParams.CommandRetries = 2;
        initParams.CommandRetryInterval = new TimeSpan(0, 0, 5);
        initParams.Mode = IsolationLevel.Default;

        NCacheConfiguration.Configure("democache", DependencyType.SqlServer, initParams);

        optionsBuilder.UseSqlServer(@"Data Source=DESKTOP-AT3H2E;Initial Catalog=sampleDatabase;Integrated Security=True");
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Store>()
            .HasMany(x => x.AvailableProducts)
            .WithOne(x => x.Store)
            .HasForeignKey(x => x.StoreId)
            .IsRequired(false)
            .OnDelete(DeleteBehavior.NoAction);

        modelBuilder.Entity<Store>()
            .HasMany(x => x.RegularConsumers)
            .WithOne(x => x.FavouriteStore)
            .HasForeignKey(x => x.FavouriteStoreId)
            .IsRequired(false)
            .OnDelete(DeleteBehavior.NoAction);

        modelBuilder.Entity<Transaction>()
            .HasOne(x => x.Consumer)
            .WithMany(x => x.Transactions)
            .HasForeignKey(x => x.ConsumerId)
            .IsRequired(false);

        modelBuilder.Entity<Transaction>()
            .HasOne(x => x.Product)
            .WithMany(x => x.Transactions)
            .HasForeignKey(x => x.ProductId)
            .IsRequired(false);
    }

    public DbSet<Store> Stores { get; set; }
    public DbSet<Consumer> Consumers { get; set; }
    public DbSet<Product> Products { get; set; }
    public DbSet<Transaction> Transactions { get; set; }
}

3.NCacheメソッド

これは、キャッシュとの間でオブジェクトを操作するために必要なNCacheメソッドを持つクラスです。

public class NCacheExtensions
{
    private SampleDbContext Database { get; set; }
    private CachingOptions CachingOptions { get; set; }
    private Cache Cache { get; set; }

    public NCacheExtensions(SampleDbContext database)
    {
        this.Database = database;
        this.CachingOptions = new CachingOptions
        {
            QueryIdentifier = "Sample QueryIdentifier",
            Priority = Alachisoft.NCache.Runtime.CacheItemPriority.Default,
            CreateDbDependency = false,
            StoreAs = StoreAs.Collection
        };

        Cache = database.GetCache();
    }

    public string AddSingleEntity<T>(T entity)
    {
        Cache.Insert(entity, out string cacheKey, this.CachingOptions);
        return cacheKey;
    }
    public void RemoveSingleEntity<T>(T entity)
    {
        Cache.Remove(entity);
    }
    public void RemoveSingleEntity(string cacheKey)
    {
        Cache.Remove(cacheKey);
    }
    public void RemoveByQueryIdentifier(string queryIdentifier)
    {
        var tag = new Tag(queryIdentifier);
        Cache.RemoveByQueryIdentifier(tag);
    }

    public IEnumerable<Consumer> GetAllConsumersFromCache(CachingOptions cachingOptions)
    {
        return Database.Consumers.Include(x => x.Transactions).ThenInclude(x => x.Product).FromCache(cachingOptions);
    }
    public async Task<IEnumerable<Consumer>> GetAllConsumersFromCacheAsync(CachingOptions cachingOptions)
    {
        return await Database.Consumers.Include(x => x.Transactions).ThenInclude(x => x.Product).FromCacheAsync(cachingOptions);
    }
    public IEnumerable<Consumer> LoadAllConsumersIntoCache(CachingOptions cachingOptions)
    {
        return Database.Consumers.Include(x => x.Transactions).ThenInclude(x => x.Product).LoadIntoCache(cachingOptions);
    }
    public async Task<IEnumerable<Consumer>> LoadAllConsumersIntoCacheAsync(CachingOptions cachingOptions)
    {
        return await Database.Consumers.Include(x => x.Transactions).ThenInclude(x => x.Product).LoadIntoCacheAsync(cachingOptions);
    }
    public IEnumerable<Consumer> GetAllConsumersFromCacheOnly(CachingOptions cachingOptions)
    {
        return Database.Consumers.FromCacheOnly();
    }
}

4.program.csクラス

ここに、コンソールアプリケーションの開始点があります。NCacheに接続し、上記で提供された拡張メソッドを使用する方法の例を示します。

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Hello World!");

        using (var context = new SampleDbContext())
        {
            var cachedContext = new NCacheExtensions(context);

            Console.WriteLine("start LoadAllConsumersIntoCache " + DateTime.Now.ToString("HH:mm:ss.f"));
            var loadInCache = cachedContext.LoadAllConsumersIntoCache(new CachingOptions { StoreAs = StoreAs.Collection, QueryIdentifier = "Sample QueryIdentifier" });
            Console.WriteLine("finish LoadAllConsumersIntoCache" + DateTime.Now.ToString("HH:mm:ss.f"));

            Console.WriteLine("start GetAllConsumersFromCache " + DateTime.Now.ToString("HH:mm:ss.f"));
            var getFromCache = cachedContext.GetAllConsumersFromCache(new CachingOptions { Priority = Alachisoft.NCache.Runtime.CacheItemPriority.Default });
            Console.WriteLine("finish GetAllConsumersFromCache " + DateTime.Now.ToString("HH:mm:ss.f"));

            Console.WriteLine("start load from DBContext " + DateTime.Now.ToString("HH:mm:ss.f"));
            var getFromDb = context.Consumers.Include(x => x.Transactions).ThenInclude(x => x.Product);
            Console.WriteLine("finishg load from DBContext " + DateTime.Now.ToString("HH:mm:ss.f"));

            var cachedEntity = cachedContext.AddSingleEntity<Consumer>(getFromDb.FirstOrDefault());
            Console.WriteLine("cache key: " + cachedEntity);

            cachedContext.RemoveSingleEntity(cachedEntity);
            cachedContext.RemoveByQueryIdentifier("Sample QueryIdentifier");

        }
    }
}

アプリケーションの動作:

おめでとう!これで、EntityFrameworkCoreデータをキャッシュするためのNCacheの使用に成功しました。

このストーリーは、もともとhttps://www.c-sharpcorner.com/article/caching-in-entity-framework-core-using-ncache/で公開されました

#entity-framework 

What is GEEK

Buddha Community

NCacheを使用したEntityFrameworkCoreでのキャッシュ
坂本  篤司

坂本 篤司

1654967340

NCacheを使用したEntityFrameworkCoreでのキャッシュ

この記事では、NCacheを使用してEntityFrameworkCoreをキャッシングエンジンと統合する方法について説明します。この記事では、コンソールアプリケーションでEntity Framework Coreをセットアップする方法と、NCacheを使用して、ネイティブのメモリ内分散キャッシュを使用してデータベースに対してより高速なリクエストを行う方法の実際的な例を示します。

Entity Framework Coreとは何ですか?

Entity Framework Coreは、Microsoftの最新のORMであるObject Relational Mapperであり、ソフトウェアアプリケーションがエンティティをさまざまなデータベースにマッピング、接続、および管理するのに役立ちます。Entity Framework Coreはオープンソースでクロスプラットフォームであり、Microsoftテクノロジを使用するソフトウェアで使用されるORMのトップ1です。

この記事を書いている時点で、Entity Framework Coreは、エンティティをデータベースに接続する2つの方法を提供しています。

  • コード最初に、プロジェクトのエンティティを最初に記述し、次にそれらのオブジェクトをデータベースに反映します。
  • データベースまず、データベースを最初に作成してから、プロジェクトのエンティティを生成します。

NCacheとは何ですか?

NCacheは、オープンソースおよびクロスプラットフォームのソフトウェアでもあります。そのキャッシュサーバーは、.NET、Java、Scala、Python、およびNode.js用のスケーラブルなメモリ内分散キャッシュを提供します。この記事では.NETテクノロジーに焦点を当てているため、NCacheを使用して次の使用法を利用できます。

  • ASP.NETセッション状態ストレージ。
  • ASP.NETビューステートキャッシング。
  • ASP.NET出力キャッシュ。
  • EntityFrameworkキャッシュ;
  • NHibernateの第2レベルのキャッシュ。

EntityFrameworkCoreを使用したNCache

Entity Framework CoreとNCacheを使用するアプリケーションの間にキャッシュのレイヤーを追加できます。これにより、クエリの応答時間が改善され、NCacheのキャッシュされたエンティティからデータを取得する限り、データベースへのラウンドトリップの必要性が減ります。 

キャッシングオプション

NCacheを使用すると、各リクエストから送信されるオプションのセットを変えることができます。つまり、効率を上げるために、使用している結果セットに基づいてキャッシュを異なる方法で使用できます。

実際のサンプルで見るように、NCacheへの各リクエストでキャッシュオプションを提供する必要があり、それらのオプションは次のとおりです。

  • AbsoluteExpirationTimeは、キャッシュされたアイテムが期限切れになる絶対時間を設定します。
    • データ型:日時
  • CreateDbDependencyは、結果セットからデータベースの依存関係を作成するかどうかを決定します。
    • データ型:ブール値
  • ExpirationTypeは、有効期限タイプを設定します。
    • 絶対の、
    • スライディング、
    • なし。
  • IsSyncEnabledは、期限切れのアイテムをデータベースと再同期する必要があるかどうかを設定します。
    • データ型:ブール値
  • 優先度、キャッシュに保存されているアイテムの相対的な優先度を設定します。
    • 普通、
    • 低い、
    • ノーマル以下、
    • 通常より上、
    • 高い、
    • 取り外し不可、
    • デフォルト
  • QueryIdentifier、結果セット識別子。
    • データ型:文字列。
  • ReadThruProviderは、キャッシュ同期用の読み取りスループロバイダーを設定します
    • データ型:文字列
  • SlidingExpirationTimeは、スライドの有効期限を設定します
    • データ型:TimeSpan
  • StoreAsは、アイテムの保存方法を設定します。
    • コレクション
    • SeperateEntities

延期された通話

NCacheには、Entity Framework Coreの遅延呼び出しを処理するための独自の拡張メソッドがあり、それらは3つの異なるグループに属しています。

  • 演算子を集約し、コレクションに対して操作を行います。FromCacheメソッドとFromCacheOnlyメソッドの両方で使用できます。
    • DeferredAverage。
      • Products.Select(o => o.UnitPrice).DeferredAverage()
    • DeferredCount
      • Customers.Select(c => c.Country).GroupBy(c => c).DeferredCount()
    • DeferredMin
      • Orders.Where(o => o.CustomerId == "VINET")。Select(o => o.RequiredDate).DeferredMin()
    • DeferredMax
      • Orders.Select(o => o.RequiredDate).DeferredMax()
    • DeferredSum
      • OrderDetails.Select(o => o.UnitPrice).DeferredSum()
  • 要素演算子、単一要素の操作を行います。FromCacheメソッドでのみ使用できます。
    • DeferredElementAtOrDefault
      • Customers.DeferredElementAtOrDefault(c => c.City == "London")
    • DeferredFirst
      • Customers.DeferredFirst(c => c.ContactTitle == "営業担当者")
    • DeferredFirstOrDefault
      • Customers.DeferredFirstOrDefault(c => c.ContactTitle == "営業担当者")
    • DeferredLast
      • Customers.DeferredLast(c => c.City == "London")
    • DeferredLastOrDefault
      • Customers.DeferredLastOrDefault(c => c.City == "London")
    • DeferredSingle
      • Customers.DeferredSingle(c => c.CustomerId == "ALFKI")
    • DeferredSingleOrDefault
      • Customers.DeferredSingleOrDefault(c => c.CustomerId == "ANATR")
  • その他。FromCacheメソッドでのみ使用できます。
    • DeferredAll
      • Products.DeferredAll(式)
    • DeferredLongCount
      • Products.DeferredLongCount()
    • DeferredContains
      • Products.DeferredContains(new Products {ProductId = 1})

キャッシング方法

キャッシュされたオブジェクトを操作するNCacheのメソッド:

  • 入れる

独自のオプションを使用して、単一のオブジェクトをキャッシュに挿入します。キャッシュキーを返します

var customerEntity = new Customers
   {
       CustomerId = "HANIH",
       ContactName = "Hanih Moos",
       ContactTitle = "Sales Representative ",
       CompanyName = "Blauer See Delikatessen"
   };

   //Add customer entity to database
   database.Customers.Add(customerEntity);
   database.SaveChanges();

   //Caching options for cache
   var options = new CachingOptions
   {
       QueryIdentifier = "CustomerEntity",
       Priority = Runtime.CacheItemPriority.Default,
   };

   //Add customer entity to cache
   Cache cache = database.GetCache();

   cache.Insert(customerEntity, out string cacheKey, options);
  • 削除(オブジェクトエンティティ)

キャッシュから1つのオブジェクトを削除します。

var cust = new Customers
  {
      CustomerId = "HANIH",
      ContactName = "Hanih Moos",
      ContactTitle = "Sales Representative",
      CompanyName = "Blauer See Delikatessen"
  };

  cache.Remove(cust);
  • 削除(文字列cacheKey)

キャッシュキーを渡してオブジェクトを削除します

cache.Remove("cacheKey");
  • RemoveByQueryIdentifier

クエリ識別子に一致するすべてのエンティティをキャッシュから削除します

Tag tag = new Tag(queryIdentifier);
cache.RemoveByQueryIdentifier(tag);

NCache拡張メソッドを使用したキャッシュ 

EntityFrameworkCore用のNCacheの拡張メソッド

  • GetCache

キャッシュインスタンスを取得します。

using (var context = new NorthwindContext())
{
Cache cache = context.GetCache();
}
  • FromCache

キャッシュされたデータがある場合は、データソースを経由せずに返されます。キャッシュされたデータがない場合、データはデータソースから返され、キャッシュされます。

var options = new CachingOptions
{
    StoreAs = StoreAs.SeperateEntities
};

var resultSet = (from cust in context.Customers
                 where cust.CustomerId == 10
                 select cust).FromCache(options);

結果セットからcacheKeyを返す

var options = new CachingOptions
{
    StoreAs = StoreAs.Collection
};

var resultSet = (from cust in context.Customers
                where cust.CustomerId == 10
                select cust).FromCache(out string cacheKey, options);
  • LoadIntoCache

すべてのリクエストは最初にデータソースに送られ、その結果セットをキャッシュして返します。

var options = new CachingOptions
    {
        StoreAs = StoreAs.SeperateEntities
    };

    var resultSet = (from custOrder in context.Orders
                     where custOrder.Customer.CustomerId == 10
                     select custOrder)).LoadIntoCache(options);

結果セットからキャッシュキーを返す

var options = new CachingOptions
{
    StoreAs = StoreAs.Collection
};

var resultSet = (from custOrder in context.Orders
                 where custOrder.Customer.CustomerId == 10
                 select custOrder)).LoadIntoCache(out string cacheKey, options);
  • FromCacheOnly

データソースには絶対に行きません。リクエストはキャッシュにのみ送信されます。一致する結果がキャッシュされていない場合は、空の結果セットとして返されます。

インクルードと結合はFromCacheOnly()ではサポートされていません。

var resultSet = (from cust in context.Customers
                 where cust.CustomerId == someCustomerId
                 select cust).FromCacheOnly();

NCacheの実装ステップバイステップ

0.前提条件

1.アプリケーション

  • .NET 6.0を対象とするC#コンソールアプリケーションを作成し、次のnugetsパッケージをインストールします。
    • EntityFrameworkCore.NCache
    • Microsoft.EntityFrameworkCore.SqlServer
    • Microsoft.EntityFrameworkCore.SqlServer.Design
    • Microsoft.EntityFrameworkCore.Tools
    • System.Data.SqlClient
    • System.Collections
  • Nugetパッケージをインストールすると、次のNCacheファイルがプロジェクトに挿入されます。
    • client.ncconf
    • config.ncconf
    • tls.ncconf

2.モデル

このサンプルでは、​​次のように非常に単純なモデル関係が作成されました。

  • 製品
[Serializable]
public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public double Price { get; set; }
    public List<Transaction> Transactions { get; set; }
    public Store Store { get; set; }
    public int? StoreId { get; set; }
}
[Serializable]
public class Store
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Location { get; set; }
    public ICollection<Product> AvailableProducts { get; set; }
    public ICollection<Consumer> RegularConsumers { get; set; }
}
  • 消費者
[Serializable]
public class Consumer
{
    public int Id { get; set; }
    public string Name { get; set; }
    public Store FavouriteStore { get; set; }
    public int? FavouriteStoreId { get; set; }
    public List<Transaction> Transactions { get; set; }
}
  • 取引
[Serializable]
public class Transaction
{
     public int Id { get; set; }

     public Consumer Consumer { get; set; }
     public int ConsumerId { get; set; }

     public Product Product { get; set; }
     public int ProductId { get; set; }
}
  • DBContext

DBContextクラスには、NCache初期化設定とモデルの関係があります。

public class SampleDbContext : DbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        // configure cache with SQLServer DependencyType and CacheInitParams
        CacheConnectionOptions initParams = new CacheConnectionOptions();
        initParams.RetryInterval = new TimeSpan(0, 0, 5);
        initParams.ConnectionRetries = 2;
        initParams.ConnectionTimeout = new TimeSpan(0, 0, 5);
        initParams.AppName = "appName";
        initParams.CommandRetries = 2;
        initParams.CommandRetryInterval = new TimeSpan(0, 0, 5);
        initParams.Mode = IsolationLevel.Default;

        NCacheConfiguration.Configure("democache", DependencyType.SqlServer, initParams);

        optionsBuilder.UseSqlServer(@"Data Source=DESKTOP-AT3H2E;Initial Catalog=sampleDatabase;Integrated Security=True");
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Store>()
            .HasMany(x => x.AvailableProducts)
            .WithOne(x => x.Store)
            .HasForeignKey(x => x.StoreId)
            .IsRequired(false)
            .OnDelete(DeleteBehavior.NoAction);

        modelBuilder.Entity<Store>()
            .HasMany(x => x.RegularConsumers)
            .WithOne(x => x.FavouriteStore)
            .HasForeignKey(x => x.FavouriteStoreId)
            .IsRequired(false)
            .OnDelete(DeleteBehavior.NoAction);

        modelBuilder.Entity<Transaction>()
            .HasOne(x => x.Consumer)
            .WithMany(x => x.Transactions)
            .HasForeignKey(x => x.ConsumerId)
            .IsRequired(false);

        modelBuilder.Entity<Transaction>()
            .HasOne(x => x.Product)
            .WithMany(x => x.Transactions)
            .HasForeignKey(x => x.ProductId)
            .IsRequired(false);
    }

    public DbSet<Store> Stores { get; set; }
    public DbSet<Consumer> Consumers { get; set; }
    public DbSet<Product> Products { get; set; }
    public DbSet<Transaction> Transactions { get; set; }
}

3.NCacheメソッド

これは、キャッシュとの間でオブジェクトを操作するために必要なNCacheメソッドを持つクラスです。

public class NCacheExtensions
{
    private SampleDbContext Database { get; set; }
    private CachingOptions CachingOptions { get; set; }
    private Cache Cache { get; set; }

    public NCacheExtensions(SampleDbContext database)
    {
        this.Database = database;
        this.CachingOptions = new CachingOptions
        {
            QueryIdentifier = "Sample QueryIdentifier",
            Priority = Alachisoft.NCache.Runtime.CacheItemPriority.Default,
            CreateDbDependency = false,
            StoreAs = StoreAs.Collection
        };

        Cache = database.GetCache();
    }

    public string AddSingleEntity<T>(T entity)
    {
        Cache.Insert(entity, out string cacheKey, this.CachingOptions);
        return cacheKey;
    }
    public void RemoveSingleEntity<T>(T entity)
    {
        Cache.Remove(entity);
    }
    public void RemoveSingleEntity(string cacheKey)
    {
        Cache.Remove(cacheKey);
    }
    public void RemoveByQueryIdentifier(string queryIdentifier)
    {
        var tag = new Tag(queryIdentifier);
        Cache.RemoveByQueryIdentifier(tag);
    }

    public IEnumerable<Consumer> GetAllConsumersFromCache(CachingOptions cachingOptions)
    {
        return Database.Consumers.Include(x => x.Transactions).ThenInclude(x => x.Product).FromCache(cachingOptions);
    }
    public async Task<IEnumerable<Consumer>> GetAllConsumersFromCacheAsync(CachingOptions cachingOptions)
    {
        return await Database.Consumers.Include(x => x.Transactions).ThenInclude(x => x.Product).FromCacheAsync(cachingOptions);
    }
    public IEnumerable<Consumer> LoadAllConsumersIntoCache(CachingOptions cachingOptions)
    {
        return Database.Consumers.Include(x => x.Transactions).ThenInclude(x => x.Product).LoadIntoCache(cachingOptions);
    }
    public async Task<IEnumerable<Consumer>> LoadAllConsumersIntoCacheAsync(CachingOptions cachingOptions)
    {
        return await Database.Consumers.Include(x => x.Transactions).ThenInclude(x => x.Product).LoadIntoCacheAsync(cachingOptions);
    }
    public IEnumerable<Consumer> GetAllConsumersFromCacheOnly(CachingOptions cachingOptions)
    {
        return Database.Consumers.FromCacheOnly();
    }
}

4.program.csクラス

ここに、コンソールアプリケーションの開始点があります。NCacheに接続し、上記で提供された拡張メソッドを使用する方法の例を示します。

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Hello World!");

        using (var context = new SampleDbContext())
        {
            var cachedContext = new NCacheExtensions(context);

            Console.WriteLine("start LoadAllConsumersIntoCache " + DateTime.Now.ToString("HH:mm:ss.f"));
            var loadInCache = cachedContext.LoadAllConsumersIntoCache(new CachingOptions { StoreAs = StoreAs.Collection, QueryIdentifier = "Sample QueryIdentifier" });
            Console.WriteLine("finish LoadAllConsumersIntoCache" + DateTime.Now.ToString("HH:mm:ss.f"));

            Console.WriteLine("start GetAllConsumersFromCache " + DateTime.Now.ToString("HH:mm:ss.f"));
            var getFromCache = cachedContext.GetAllConsumersFromCache(new CachingOptions { Priority = Alachisoft.NCache.Runtime.CacheItemPriority.Default });
            Console.WriteLine("finish GetAllConsumersFromCache " + DateTime.Now.ToString("HH:mm:ss.f"));

            Console.WriteLine("start load from DBContext " + DateTime.Now.ToString("HH:mm:ss.f"));
            var getFromDb = context.Consumers.Include(x => x.Transactions).ThenInclude(x => x.Product);
            Console.WriteLine("finishg load from DBContext " + DateTime.Now.ToString("HH:mm:ss.f"));

            var cachedEntity = cachedContext.AddSingleEntity<Consumer>(getFromDb.FirstOrDefault());
            Console.WriteLine("cache key: " + cachedEntity);

            cachedContext.RemoveSingleEntity(cachedEntity);
            cachedContext.RemoveByQueryIdentifier("Sample QueryIdentifier");

        }
    }
}

アプリケーションの動作:

おめでとう!これで、EntityFrameworkCoreデータをキャッシュするためのNCacheの使用に成功しました。

このストーリーは、もともとhttps://www.c-sharpcorner.com/article/caching-in-entity-framework-core-using-ncache/で公開されました

#entity-framework