Entity Framework 6 CodeFirst を介して SQL Server で行レベル セキュリティを使用するために、このチュートリアルに従っています。チュートリアル コード サンプルは、IDbConnectionInterceptor を使用して現在のユーザー ID を に設定する方法を示していますsession_context
。HttpContext.Current.User.Identity.GetUserId()
ユーザー ID を取得するには、Asp.Net ID および System.Web 名前空間と結合された静的アクセサー メソッドを使用します。
私のマルチテナント Web アプリでは、 tenantIdを Unity を使用して ( とのハードカップリングを作成せずに)に注入し、tenantIdを に設定したいと考えていました。をグローバルに登録する必要があることがわかりました(たとえば、アプリケーションの起動時)。したがって、リクエストごとに Unity にインスタンスを作成させることはできません。DbConnectionInterceptor
HttpContext
session_context
DbConnectionInterceptor
DbConnectionInterceptor
また、ソリューションには 2 つの異なるデータベース (テナント データベースとシステム データベース) を表す 2 つの DbContext があり、テナント データベースのみに適用したいと考えていますsession_context
。
DbContext
私に残っている唯一のオプションは、 tenantId を Unity を介してインスタンスに注入し、のメソッドDbContext
内のインスタンスにアクセスすることです。この目的のために、メソッドでパラメーターを使用することを考えました。(複数の)プロパティを持っています。これに関するドキュメントがないため、次のようなものが機能すると想定しました。Opened()
DbConnectionInterceptor
interceptionContext
Opened()
interceptionContext
DbContexts
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に関する説明も役に立ちます。