Это не имеет ничего общего с кэшированием и контекстными экземплярами. Это проблема, связанная с деревьями выражений - смотрите мое обновление.

даю мультитенантное приложение и сталкиваюсь с трудностями, связанными с кэшированием идентификатора клиента в запросах. Единственная вещь, которая, кажется, помогает - постоянно перестраивать приложение, когда я вхожу и покидаю арендаторов.

Я думал, что это может иметь какое-то отношение кIHttpContextAccessor экземпляр является одиночным, но он не может быть ограничен областью действия, и когда я вхожу и выхожу без перестройки, я вижу изменение имени арендатора в верхней части страницы, так что это не проблема.

Единственное, о чем я могу думать, это то, что EF Core выполняет какое-то кэширование запросов. Я не уверен, почему он будет считать, что это экземпляр с заданной областью, и он должен перестраиваться при каждом запросе, если я не ошибаюсь, что, вероятно, и есть. Я надеялся, что он будет вести себя как экземпляр с заданной областью, поэтому я мог бы просто ввести идентификатор клиента во время построения модели для каждого экземпляра.

Я был бы очень признателен, если бы кто-то указал мне правильное направление. Вот мой текущий код:

TenantProvider.cs

public sealed class TenantProvider :
    ITenantProvider {
    private readonly IHttpContextAccessor _accessor;

    public TenantProvider(
        IHttpContextAccessor accessor) {
        _accessor = accessor;
    }

    public int GetId() {
        return _accessor.HttpContext.User.GetTenantId();
    }
}

... который вводится вTenantEntityConfigurationBase.cs где я использую его для настройки глобального фильтра запросов.

internal abstract class TenantEntityConfigurationBase<TEntity, TKey> :
    EntityConfigurationBase<TEntity, TKey>
    where TEntity : TenantEntityBase<TKey>
    where TKey : IEquatable<TKey> {
    protected readonly ITenantProvider TenantProvider;

    protected TenantEntityConfigurationBase(
        string table,
        string schema,
        ITenantProvider tenantProvider) :
        base(table, schema) {
        TenantProvider = tenantProvider;
    }

    protected override void ConfigureFilters(
        EntityTypeBuilder<TEntity> builder) {
        base.ConfigureFilters(builder);

        builder.HasQueryFilter(
            e => e.TenantId == TenantProvider.GetId());
    }

    protected override void ConfigureRelationships(
        EntityTypeBuilder<TEntity> builder) {
        base.ConfigureRelationships(builder);

        builder.HasOne(
            t => t.Tenant).WithMany().HasForeignKey(
            k => k.TenantId);
    }
}

... который затем наследуется всеми другими конфигурациями объекта-арендатора. К сожалению, это не работает так, как я планировал.

Я проверил, что идентификатор арендатора, возвращаемый принципалом пользователя, изменяется в зависимости от того, какой пользователь арендатора вошел в систему, поэтому проблема не в этом. Заранее благодарю за любую помощь!

Обновить

Для решения при использовании EF Core 2.0.1+ посмотрите на непринятый от меня ответ.

Обновление 2

Также посмотрите на обновление Ивана для 2.0.1+, оно прокси в выражении фильтра из DbContext, которое восстанавливает возможность определить его один раз в базовом классе конфигурации. Оба решения имеют свои плюсы и минусы. Я снова выбрал Ивана, потому что я просто хочу максимально использовать свои базовые конфигурации.

Ответы на вопрос(2)

Ваш ответ на вопрос