5

Entity Framework 6 CodeFirst を介して SQL Server で行レベル セキュリティを使用するために、このチュートリアルに従っています。チュートリアル コード サンプルは、IDbConnectionInterceptor を使用して現在のユーザー ID を に設定する方法を示していますsession_contextHttpContext.Current.User.Identity.GetUserId()ユーザー ID を取得するには、Asp.Net ID および System.Web 名前空間と結合された静的アクセサー メソッドを使用します。

私のマルチテナント Web アプリでは、 tenantIdを Unity を使用して ( とのハードカップリングを作成せずに)に注入し、tenantIdを に設定したいと考えていました。をグローバルに登録する必要があることがわかりました(たとえば、アプリケーションの起動時)。したがって、リクエストごとに Unity にインスタンスを作成させることはできません。DbConnectionInterceptorHttpContextsession_contextDbConnectionInterceptorDbConnectionInterceptor

また、ソリューションには 2 つの異なるデータベース (テナント データベースとシステム データベース) を表す 2 つの DbContext があり、テナント データベースのみに適用したいと考えていますsession_context

DbContext私に残っている唯一のオプションは、 tenantId を Unity を介してインスタンスに注入し、のメソッドDbContext内のインスタンスにアクセスすることです。この目的のために、メソッドでパラメーターを使用することを考えました。(複数の)プロパティを持っています。これに関するドキュメントがないため、次のようなものが機能すると想定しました。Opened()DbConnectionInterceptorinterceptionContextOpened()interceptionContextDbContexts

public void Opened(DbConnection connection, DbConnectionInterceptionContext interceptionContext)
{
    var firstDbContext = interceptionContext.DbContexts.FirstOrDefault(d => d is TenantDataContext);
    if (firstDbContext != null)
    {
        var dataContext = firstDbContext as TenantDataContext;
        var tenantId = dataContext.TenantId;

        DbCommand cmd = connection.CreateCommand();
        cmd.CommandText = $"EXEC sp_set_session_context @key=N'TenantId', @value={tenantId};";
        cmd.ExecuteNonQuery();
    }
}

私のコードは、DbContexts コレクションにTenantDataContext最初の要素として が含まれているかどうかを確認し、sp_set_session_context. しかし、私が心配しているのは、両方の DbContext が同時に存在する可能性があるかどうかです。その場合、他のデータベースへの接続もsession_context必要のない を設定します。Microsoft がこれを単一のプロパティではなくコレクション プロパティとして提供した理由を知りたいですDbContext。このプロパティは、同じ接続を複数の DbContext で使用できるかどうか疑問に思います。

私が望むことを達成した人はいますか?このinterceptionContextに関する説明も役に立ちます。

4

2 に答える 2