【问题标题】:Entity Framework Core Global Dynamic Query FilterEntity Framework Core 全局动态查询过滤器
【发布时间】:2021-08-21 12:17:29
【问题描述】:

我们使用的是 ef core 3.1 我们要使用动态查询过滤器, 我尝试了示例实现,但没有像我们预期的那样正常工作,过滤总是相同的租户 ID,我试图在下面解释


 public class TestDbContext : DbContext
    {
      
        public DbSet<TenantUser> TenantUsers { get; set; }
      

        private readonly ITenantProvider _tenantProvider;

        private Guid? TenantId => _tenantProvider.TenantId;

        public TestDbContext (DbContextOptions<TestDbContext > options, ITenantProvider tenantProvider) : base(options)
        {
               _tenantProvider = tenantProvider;
        }


        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<TenantUser>()
                .HasQueryFilter(p => EF.Property<Guid>(p, "TenantId") == TenantId);
        }

    }

ITenantProvider 从 HttpContext 标头返回 TenantId

此代码从第一个请求中过滤始终相同的租户 ID

更新:


 public class TenantProvider : ITenantProvider
    {
        private readonly IHttpContextAccessor _httpContextAccessor;

        public TenantProvider(IHttpContextAccessor httpContextAccessor)
        {
            _httpContextAccessor = httpContextAccessor;
        }

        public Guid? TenantId
        {
            get
            {
                if (_httpContextAccessor.HttpContext.Request.Headers.TryGetValue(HeaderNames.TenantId, out var tenantId) &&
                    Guid.TryParse(tenantId, out Guid parsedTenantId))
                {
                    return parsedTenantId;
                }
                return null;
            }
        }
    }

例如 第一个请求 TenantId = 60000000-0000-0000-0000-000000000000 这个过滤器 => 60000000-0000-0000-0000-000000000000

第二次请求 TenantId = 10000000-0000-0000-0000-000000000000 这个过滤器 => 60000000-0000-0000-0000-000000000000

【问题讨论】:

  • but did not work 不是问题描述。 this code filtering always same tenant id from coming first request 听起来像过滤器确实 工作。 _tenantProvider.TenantId 每次都返回相同的 ID。或者您每次都使用相同的 DbContext(非常糟糕的主意),这意味着您始终使用存储在 TenantId 字段中的值
  • 发布ITenantProvider 代码。这似乎与 EF Core 无关
  • @PanagiotisKanavos 添加
  • 看起来正确。将TenantId 的可见性更改为public 没有帮助?
  • 但是您使用的是不同的 DbContext 实例吗?还是单例/池化的?

标签: entity-framework entity-framework-core ef-core-3.1


【解决方案1】:

几年前我们尝试过类似的事情。主要问题是 OnModelCreating 方法只触发了一次。所以 HasQueryFilter 工作一次并从提供者那里获取当前的租户 id,它适用于所有查询相同的租户 id。

【讨论】:

    【解决方案2】:

    您还应该实现自定义 IModelCacheKeyFactory

    public class MyModelCacheKeyFactory : IModelCacheKeyFactory
    {
        public object Create(DbContext context)
        {
            if (context is TestDbContext testDbContext)
            {
                return (context.GetType(), testDbContext.TenantId);
            }
            return context.GetType();
        }
    }
    

    然后,你需要像这样替换

    var builder = new DbContextOptionsBuilder<TestDbContext>();
    
    builder.ReplaceService<IModelCacheKeyFactory, MyModelCacheKeyFactory>();
    
    var context = new TestDbContext(builder.Options);
    

    参考: https://docs.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.infrastructure.imodelcachekeyfactory

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-10-23
      • 2018-05-18
      • 1970-01-01
      • 2022-01-22
      相关资源
      最近更新 更多