2017-02-01 4 views
3

IMemoryCacheを使用してキャッシュにデータを格納していますが、キャッシュが存在する場合にそのコードが実行されなくても。.NetコアIMemoryCacheは、EFクエリが使用されている場合にデータベースを呼び出し続けます。

マイ検索サービス

public class QueryLookups 
    { 
     private IMemoryCache _memoryCache; 


     public QueryLookups(DbContexts.AppsecDbContext ctx, IMemoryCache memoryCache) 
     { 
      context = ctx; 
      _memoryCache = memoryCache; 
     } 

     public DbContexts.AppsecDbContext context 
     { 
      get; set; 
     } 

     public IEnumerable<string> GetCourseAreas() 
     { 
      IEnumerable<string> result; 

      // TryGet returns true if the cache entry was found 
      if (!_memoryCache.TryGetValue("CourseAreas", out result)) 
      { 
       oak.Frameworks.Utils.Debug("No Cache found for 'CourseAreas' - Get from Database"); 

       result = context.CourseAreas.Where(s => string.IsNullOrWhiteSpace(s.Area) == false).Select(s => s.Area).Distinct().OrderBy(s => s); 

       _memoryCache.Set("CourseAreas", result, DateTime.Now.AddHours(1)); // 1 hour cache 
      } 

      return result; 
     } 

     public IEnumerable<string> GetAcademicYearIDs() 
     { 
      IEnumerable<string> result; 

      // TryGet returns true if the cache entry was found 
      if (!_memoryCache.TryGetValue("AcademicYearIDs", out result)) 
      { 
       oak.Frameworks.Utils.Debug("No Cache found for 'AcademicYearIDs' - Get from Database"); 
       IDbConnection db = context.Database.GetDbConnection();     
       result = db.Query<string>("SELECT DISTINCT AcademicYearID FROM dbo.ER_vBaseStudents;");     

       _memoryCache.Set("AcademicYearIDs", result, DateTime.Now.AddHours(5)); // 5 hours cache 
      } 

      return result; 
     } 

    } 

私のテストView.cshtml

<div class="form-inline"> 
    <select class="form-control" asp-items="@LookupService.GetAcademicYearIDs().Select(g => new SelectListItem() { Text = g, Value = g })"> 
     <option value="">- All Years -</option> 
    </select> 
    <select class="form-control" asp-items="@LookupService.GetCourseAreas().Select(g => new SelectListItem() { Text = g, Value = g })"> 
     <option value="">- All Areas -</option> 
    </select> 
</div> 

_ViewImports.cshtml

@using MyProject 
@inject MyProject.Queries.QueryLookups LookupService 
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 

TestController

public IActionResult Test() 
{ 
    return View(); 
} 

理論上、dbコマンドをSQL Serverに送信すべきではありません。しかし、SQLプロファイラによれば、コードを実行してそこからデータを取得しても、まだ送信されています。キャッシュにヒットし、キャッシュからデータを返します。しかし、それはまだDBにSELECT xxxxを実行します。

奇妙なことに、私のルックアップサービスには2つの方法があります。 Dapperを使ったGetAcademicYearIDs()メソッドは同じことをしていません。それは、私がEF構文を使用したGetCourseAreasのためだけに行っています。

この問題で私を助けてください。これらのデータベース呼び出しは非常に高速で、100ミリ秒未満です。しかし、私はなぜそれが続けて、私が間違っているのかを知りたいです。

enter image description here

回答 クレジットは私がLondon.Netユーザグループに会った教祖に行きます。あなたがその質問に答えると、私はあなたの答えを正しいものとしてマークします。

理由は、EFCoreのレイジーローディング機能のためです。データベースからデータを読み取らずにエンティティを直接キャッシュします。その代わりに、私は.ToList()を追加して強制的に読み込み、結果をキャッシュに戻しました。それは完璧に動作します。

result = context.CourseAreas.Where(s => string.IsNullOrWhiteSpace(s.Area) == false).Select(s => s.Area).Distinct().OrderBy(s => s).ToList(); 

_memoryCache.Set("CourseAreas", result, DateTime.Now.AddHours(1)); // 1 hour cache 
+0

どのEFのバージョンを使用していますか? –

+0

Entity Frameworkコア "Microsoft.EntityFrameworkCore.Tools": "1.1.0-preview4-final" – TTCG

答えて

0

私は呼び出しがキャッシュが古くなるのを止めることだと思います。あなたはそれがリフレッシュする時間率を変更することができるはずですMicrosoft IMemeoryCache

関連する問題