ハロの外部記憶インターフェイス

そろそろ覚える努力が必要かも…

DbContextで接続元のIPとホスト名を取得する方法

IHttpContextAccessorを変数についかし、DbContext生成じに取得する。

ライブラリプロジェクトではIHttpContextAccessorが見つからなかったWeb APIプロジェクトでは追加できたからWebアプリケーション開発テンプレートの場合は問題ないみたい

MyDbContext.cs

private readonly IHttpContextAccessor _httpContextAccessor;
public MyDbContext(DbContextOptions<MyDbContext> options, IHttpContextAccessor httpContextAccessor)
    : base(options)
{
    _httpContextAccessor = httpContextAccessor;
}
public class MyDbContext : DbContext
{
    private readonly IHttpContextAccessor _httpContextAccessor;
    public DbSet<ChangeLog> ChangeLogs { get; set; }

    public MyDbContext(DbContextOptions<MyDbContext> options, IHttpContextAccessor httpContextAccessor)
        : base(options)
    {
        _httpContextAccessor = httpContextAccessor;
    }

    public override int SaveChanges()
    {
        var ip = _httpContextAccessor.HttpContext?.Connection?.RemoteIpAddress?.ToString();
        var host = System.Net.Dns.GetHostEntry(_httpContextAccessor.HttpContext?.Connection?.RemoteIpAddress)?.HostName;

        var changeLogs = new List<ChangeLog>();

        foreach (var entry in ChangeTracker.Entries().Where(e => e.State == EntityState.Modified || e.State == EntityState.Added || e.State == EntityState.Deleted))
        {
            var entityName = entry.Entity.GetType().Name;

            foreach (var prop in entry.Properties)
            {
                var original = entry.State == EntityState.Added ? null : prop.OriginalValue?.ToString();
                var current = prop.CurrentValue?.ToString();

                if (original != current)
                {
                    changeLogs.Add(new ChangeLog
                    {
                        EntityName = entityName,
                        PropertyName = prop.Metadata.Name,
                        OriginalValue = original,
                        CurrentValue = current,
                        IpAddress = ip,
                        HostName = host,
                        ChangedAt = DateTime.UtcNow
                    });
                }
            }
        }

        ChangeLogs.AddRange(changeLogs);

        return base.SaveChanges();
    }
}

このままだとIHttpContextAccessorが取得できないため、以下を追加

builder.Services.AddHttpContextAccessor();

Programs.cs

var builder = WebApplication.CreateBuilder(args);
// ここで登録!
builder.Services.AddHttpContextAccessor();
// 他のサービス登録
builder.Services.AddDbContext<AppDbContext>();
var app = builder.Build();