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ミリ秒未満です。しかし、私はなぜそれが続けて、私が間違っているのかを知りたいです。
回答 クレジットは私が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
どのEFのバージョンを使用していますか? –
Entity Frameworkコア "Microsoft.EntityFrameworkCore.Tools": "1.1.0-preview4-final" – TTCG