永続化層から論理削除されたデータの取得などに便利なグローバルクエリフィルターを試していきます。
実行環境
- Visual Studio 2022 17.10.5
- .NET8
データを用意する
次のようなテーブルから、公開日(PublishedDateTime)を過ぎているデータのみ取得するようにしてみます。
DbContextとEntityはこんな感じです。
publicclassAppDbContext : DbContext { public DbSet<Character> Characters { get; set; } protectedoverridevoid OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlServer(@"**********"); } } public record Character(int Id, string Name, DateTime PublishedDateTime);
グローバルクエリフィルターを設定する
DbContextのOnModelCreatingでグローバルクエリフィルターを設定します。
publicclassAppDbContext : DbContext { public DbSet<Character> Characters { get; set; } protectedoverridevoid OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlServer(@"**********"); } protectedoverridevoid OnModelCreating(ModelBuilder modelBuilder) { // 公開済みのキャラクターだけ取得する modelBuilder.Entity<Character>().HasQueryFilter(character => character.PublishedDateTime < DateTime.Now); } }
この状態でCharactersを取得してみます。
var dbContext =new AppDbContext(); var characters =await dbContext.Characters.ToListAsync(); foreach (var character in characters) { Console.WriteLine(character); }
実行結果
今日の日付(2024/8/16)以前のデータのみ取得できました。
Character { Id = 1, Name = リュウ, PublishedDateTime = 2023/06/02 0:00:00 } Character { Id = 2, Name = ケン, PublishedDateTime = 2023/06/02 0:00:00 } Character { Id = 3, Name = ベガ, PublishedDateTime = 2024/06/26 0:00:00 }
やっぱりグローバルクエリフィルター無しで取得したい場合
IgnoreQueryFiltersを付けることでQuery Filterを無視してデータを取得できます。
var dbContext =new AppDbContext(); var characters =await dbContext.Characters.IgnoreQueryFilters().ToListAsync(); foreach (var character in characters) { Console.WriteLine(character); }
実行結果
Character { Id = 1, Name = リュウ, PublishedDateTime = 2023/06/02 0:00:00 } Character { Id = 2, Name = ケン, PublishedDateTime = 2023/06/02 0:00:00 } Character { Id = 3, Name = ベガ, PublishedDateTime = 2024/06/26 0:00:00 } Character { Id = 4, Name = テリー, PublishedDateTime = 2024/10/01 0:00:00 }
まとめ
グローバルクエリフィルターを使うと削除済みデータを除外するようなWhereを毎回書く必要が無くなってスマートに書けるようになることが分かりました。