Наконец я понял. Я использую 2 DbContexts, как предложил Джеффри Паркс, и класс IModelCacheKeyFactory для генерации разных ключей для каждого арендатора.
DBContext, который должен запускаться OnModelCreating в зависимости от арендатора, должен быть определен как:
public class ApplicationDbContext : DbContext
{
private readonly IHttpContextAccessor _httpContextAccessor;
public int EnterpriseId { get; protected set; } = -1;
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options, IHttpContextAccessor httpContextAccessor) : base(options)
{
_httpContextAccessor = httpContextAccessor;
EnterpriseId = _httpContextAccessor.HttpContext.GetCurrentEnterpriseIdNotNull();
}
...
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
//Last in wins so first set base model features
base.OnModelCreating(modelBuilder);
HttpContext httpContext = _httpContextAccessor.HttpContext;
int enterpriseId = httpContext.GetCurrentEnterpriseIdNotNull();
//Define global filters for all entities
modelBuilder.Entity<Vehicle>().HasQueryFilter(o => o.EnterpriseId == EnterpriseId && !o.IsDeleted);
...
}
}
Обратите внимание, как я использую метод GetCurrentEnterpriseIdNotNull для получения TenantId. Это метод расширения HTTPContext, который получает запрос от HttpContext.User, который был ранее вставлен и проверен промежуточным программным обеспечением. Вы можете заменить его своим кодом, чтобы получить арендатора. Это может быть служба и т. Д. c.
Генератор ключей для кэширования моделей довольно прост:
public class TenantModelCacheKeyFactory : IModelCacheKeyFactory
{
public object Create(DbContext context) =>
context is ApplicationDbContext dynamicContext
? (context.GetType(), dynamicContext.EnterpriseId)
: (object)context.GetType();
}
Обратите внимание, как он извлекает tenantId из созданного DbContext (то есть создается для каждого HTTP-запроса).
После этого, если вы запустите запрос с правильным идентификатором клиента, после вызова OnModelCreating для этого клиента будет создан новый кэш модели, и все будет работать гладко. Если другой пользователь входит в систему для того же арендатора, новая модель не будет создана и кэшированная будет обслуживаться (помните, что DbContext всегда создается для запроса, поскольку он был добавлен в качестве службы с областью действия). Если другой пользователь входит в систему с другим tenantId, снова будет вызываться OnModelCreating, и будет также создан и обслужен другой кэш модели.