J'essaie de développer une bibliothèque de classes dans laquelle je souhaite implémenter DbContext
personnalisé. Dans la méthode SaveChanges
de DbContext
, j'ai besoin d'obtenir les informations de l'utilisateur actuel (service, nom d'utilisateur, etc.) à des fins d'audit. Une partie du code DbContext
est ci-dessous:
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();
}
Deux options viennent à l'esprit:
HttpContext.Items
pour conserver les informations utilisateur, injecter IHttpContextAccessor et obtenir des informations à partir de HttpContext.Items
(Dans ce cas DbContext
dépend HttpContext
, est-ce correct?)HttpContext.Items
et obtenir des informations de l'objet (j'ai lu certains articles que ThreadStatic n'est pas sûr)Question: Quel est le mieux adapté à mon cas? Y a-t-il une autre façon de suggérer?
J'ai implémenté une approche similaire à celle décrite dans cet article de blog et implique essentiellement la création d'un service qui utilisera l'injection de dépendance pour injecter le HttpContext
(et les informations utilisateur sous-jacentes) dans un particulier contexte ou comme vous préférez l’utiliser.
Une implémentation très basique pourrait ressembler à ceci:
public class UserResolverService
{
private readonly IHttpContextAccessor _context;
public UserResolverService(IHttpContextAccessor context)
{
_context = context;
}
public string GetUser()
{
return _context.HttpContext.User?.Identity?.Name;
}
}
Vous auriez juste besoin d'injecter cela dans le pipeline au sein de la méthode ConfigureServices
dans votre Startup.cs
fichier :
services.AddTransient<UserResolverService>();
Et enfin, accédez-y simplement dans le constructeur de votre DbContext
spécifié:
public partial class ExampleContext : IExampleContext
{
private YourContext _context;
private string _user;
public ExampleContext(YourContext context, UserResolverService userService)
{
_context = context;
_user = userService.GetUser();
}
}
Vous devriez alors pouvoir utiliser _user
pour référencer l'utilisateur actuel dans votre contexte. Cela peut facilement être étendu pour stocker/accéder à tout contenu disponible dans la demande actuelle.