EF 10 Named Query Filter

EF 10 Named Query Filter

Intro

EF Core 开始支持 global query filter,原本一个表 collection 只支持一个 global query filter,最近的 .NET 10 Preview 6 版本中的 EF 10 引入了 named query filter,支持指定同时指定多个 query filter,并且忽略 global query filter 的时候也可以忽略指定的 query filter,使得 query filter 的实用性更好了

Sample

来看一个简单的示例:

file sealed class QueryFilterContext(DbContextOptions<QueryFilterContext> options) : DbContext(options)
{
    public DbSet<BlogPost> Posts { get; set; } = null!;

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        // 可以配置多个 query filter 并指定名称
        modelBuilder.Entity<BlogPost>()
            .HasQueryFilter("non-deleted", p => !p.Title.StartsWith("[Deleted]")) 
            .HasQueryFilter("non-disabled", p => !p.Title.StartsWith("[Disabled]"))
            ;
        base.OnModelCreating(modelBuilder);
    }
}

publicclassBlogPost
{
    publicint Id { get; set; }

    [StringLength(64)]
    publicrequiredstring Title { get; set; }

    public DateTimeOffset UpdatedAt { get; set; }

    [StringLength(64)]
    publicrequiredstring UpdatedBy { get; set; }
}

在使用的时候也可以忽略指定的 filter,使用示例如下:

const string connString = "DataSource=QueryFilterSample.db";
awaitusingvar services = new ServiceCollection()
        .AddLogging(lb => lb.AddDefaultDelegateLogger())
        .AddDbContext<QueryFilterContext>((provider, options) =>
        {
            options.UseSqlite(connString);
        })
        .BuildServiceProvider()
    ;

usingvar scope = services.CreateScope();
var context = scope.ServiceProvider.GetRequiredService<QueryFilterContext>();
await context.Database.EnsureDeletedAsync();
await context.Database.EnsureCreatedAsync();
{
    context.Posts.Add(new BlogPost
    {
        Title = "test",
        UpdatedAt = DateTimeOffset.Now,
        UpdatedBy = "test"
    });
    context.Posts.Add(new BlogPost 
    { 
        Title = "[Disabled]test",
        UpdatedAt = DateTimeOffset.Now,
        UpdatedBy = "test"
    });
    context.Posts.Add(new BlogPost
    {
        Title = "[Deleted]test",
        UpdatedAt = DateTimeOffset.Now,
        UpdatedBy = "test"
    });
    await context.SaveChangesAsync();
}

{
    var posts = await context.Posts.AsNoTracking().ToArrayAsync();
    Console.WriteLine(posts.Length);
    Console.WriteLine();
}

{
    var posts = await context.Posts.AsNoTracking()
        .IgnoreQueryFilters().ToArrayAsync();
    Console.WriteLine(posts.Length);
    Console.WriteLine();
}

{
    var posts = await context.Posts.AsNoTracking()
        .IgnoreQueryFilters(["non-deleted"]).ToArrayAsync();
    Console.WriteLine(posts.Length);
    Console.WriteLine();
}

输出结果如下:

`samples output`

我们配置了两个 query filter,从输出的结果可以看出来第一次查询会把两个 filter 都带上,第二次我们使用了 IgnoreQueryFilters() 默认会忽略所有的 query filter,所以第二次是没有 query filter 应用的,而第三次是忽略了指定的 filter,没有被忽略的还是会被应用的

References

  • • https://github.com/WeihanLi/SamplesInPractice/blob/main/EFSamples/EFSamples/NamedQueryFilterSample.cs

  • • https://learn.microsoft.com/en-us/ef/core/querying/filters?tabs=ef10&WT.mc_id=DT-MVP-5004222

  • • https://github.com/dotnet/core/blob/main/release-notes/10.0/preview/preview6/efcore.md#named-query-filters

  • • https://github.com/WeihanLi/WeihanLi.EntityFramework/issues/79

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值