Dependency Injectionを使用してUserId / TenantIdをリポジトリコンストラクタに渡す方法

asp.net-core asp.net-core-mvc asp.net-mvc dependency-injection entity-framework-core

質問

私はASP.NET 5とEF7を使ってマルチテナントWebサービスを書いています。リポジトリデータは、テナント/ユーザーに固有のものです。すべての呼び出しでTenantIdを使用するので、現在のTenantIdでリポジトリを初期化したいと考えています。

public class MyRepository {
    private int tenantId;
    public MyRepository(MyDbContext context, int tenantId) { 
        this.tenantId = tenantId;
        // ...
    }

    public Task<List<Data>> GetAllAsync() {
        return this.context.Data.Where(d => d.TenantId == this.tenantId).ToListAsync();
    }
}

public class Startup {
    public void ConfigureServices(IServiceCollection services) {
        // How do I pass the TenantId to the constructor?
        services.AddScoped<MyRepository>();
    }
}

ユーザーが認証された後で一度リポジトリを初期化することは可能ですか?コンストラクタでTenantIdをどうやって渡すのですか?

人気のある回答

あなたのテナントとユーザIDの両方の値はランタイムデータです。システムのコンポーネント (この場合はリポジトリ)にランタイムデータを挿入しないでください。これは、あなたがすでに経験しているようにコンポジションルートを驚くほど複雑にし、オブジェクトグラフを検証します。ランタイムデータは、既に構築されたオブジェクトグラフを通って流れる必要があります。これを達成するには、基本的に2つの方法があります。コンポーネントのパブリックAPIのメソッド呼び出しによってデータを渡すか、要求されたときにランタイム値を取得するコンポーネントを注入します。

あなたの場合、後者のオプションが最適です。したがって私のアドバイスは、このコンテキスト情報を取得できるコンポーネントを注入することです:

public interface ITenantContext
{
    int CurrentTenantId { get; }
}

public interface IUserContext
{
    int CurrentUserId { get; }
}

public class MyRepository {
    private readonly Func<MyDbContext> contextProvider;
    private readonly ITenantContext tentantContext;

    public MyRepository(Func<MyDbContext> contextProvider, ITenantContext tentantContext){ 
        this.contextProvider = contextProvider;
        this.tentantContex = tentantContex;
    }

    public Task<List<Data>> GetAllAsync() {
        return this.contextProvider().Data
            .Where(d => d.TenantId == this.tenantContext.CurrentTenantId)
            .ToListAsync();
}

これにより、現在の要求に対して正しいテナントIDを取得する方法を知っているITenantContext実装を定義できるようになり、問題をエレガントに解決します。例えば:

public sealed class AspNetSessionTenantContext : ITenantContext {
    public int CurrentTenantId {
        get { return (int)HttpContext.Current.Session["tenantId"]; }
    }
}

これにより、すべてのコンポーネントをシングルトンとして登録することもできます。これにより、パフォーマンスが向上し、 Captive Dependenciesなどの一般的な落とし穴の変更が軽減されます。



Related

ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ
ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ