web-dev-qa-db-ja.com

Net Coreを使用してDbContextでユーザー情報を取得する方法

カスタムDbContextを実装するクラスライブラリを開発しようとしています。 SaveChangesDbContextメソッドでは、監査のために現在のユーザーの情報(部門、ユーザー名など)を取得する必要があります。 DbContextコードの一部を以下に示します。

public override int SaveChanges()
{
    // find all changed entities which is ICreateAuditedEntity 
    var addedAuditedEntities = ChangeTracker.Entries<ICreateAuditedEntity>()
           .Where(p => p.State == EntityState.Added)
           .Select(p => p.Entity);

    var now = DateTime.Now;

    foreach (var added in addedAuditedEntities)
    {
        added.CreatedAt = now;
        added.CreatedBy = ?;
        added.CreatedByDepartment = ?
    }
    return base.SaveChanges();
}

頭に浮かぶ2つのオプション:

  • HttpContext.Itemsを使用してユーザー情報を保持し、IHttpContextAccessorを挿入してHttpContext.Itemsから情報を取得します(この場合DbContextHttpContextに依存しますが、正しいですか?)
  • HttpContext.Itemsの代わりにThreadStaticオブジェクトを使用し、オブジェクトから情報を取得する(ThreadStaticは安全ではないという投稿をいくつか読んだ)

質問:私のケースに最適なのはどれですか?あなたが提案する別の方法はありますか?

17
adem caglin

私は このブログ投稿 でカバーされているこれに似たアプローチを実装し、基本的に依存関係注入を使用して特定のコンテキストにHttpContext(および基になるユーザー情報)を注入するサービスの作成を含みますが、それを使用したいと思います。

非常に基本的な実装は次のようになります。

public class UserResolverService  
{
    private readonly IHttpContextAccessor _context;
    public UserResolverService(IHttpContextAccessor context)
    {
        _context = context;
    }

    public string GetUser()
    {
       return _context.HttpContext.User?.Identity?.Name;
    }
}

これを、Startup.csファイルのConfigureServicesメソッド内のパイプラインに挿入するだけで済みます。

services.AddTransient<UserResolverService>();

そして最後に、指定したDbContextのコンストラクタ内でアクセスします。

public partial class ExampleContext : IExampleContext
{
    private YourContext _context;
    private string _user;
    public ExampleContext(YourContext context, UserResolverService userService)
    {
        _context = context;
        _user = userService.GetUser();
    }
}

次に、_userを使用して、コンテキスト内の現在のユーザーを参照できます。これは、現在のリクエスト内で利用可能なコンテンツを格納/アクセスするように簡単に拡張できます。

37
Rion Williams