繁体   English   中英

将服务依赖注入到Entity Framework Core数据库上下文中

[英]Dependency Injection of services into an Entity Framework Core database context

我一直在尝试使用DI将服务注入到我的数据库上下文中。 例如,用于审核日志记录的User Resolver服务。 我对ChangeTracker进行了扩展,以审计创建,修改和删除的属性,还具有审计记录器,用于记录实体的已更改属性。 为了使它们有效且无缝地工作,我需要确定已登录的用户。 在EF Core 1.1中,我可以通过将IUserResolverService添加到构造函数中来完成此工作。

当我尝试升级到2.0时,由于工具无法处理扩展的构造函数,我开始遇到各种问题。 我最终将其删除,所有内容开始工作,但是没有确定登录用户的可靠方法。

我现在尝试在许多场合找到答案,并且搜索仅发现了大量关于将上下文本身注入到控制器之类的文章。

是否可以在EF Core中实现而无需破坏工具等? 是否有通过Startup ConfigureServices注入服务的方法?

我遇到了非常相似的情况。 我最终只是在Startup中手动注入了它,但仍然解决了依赖性。 我不喜欢这个,希望将这些服务注入DbContext构造函数中。 这是我下面的解决方案:

public interface IUserContextProvider {
  User GetCurrentUser();
}


public class MvcUserContextProvider : IUserContextProvider {

  protected IHttpContextAccessor Accessor { get; set; }

  public MvcUserContextProvider(IHttpContextAccessor accessor) {
    Accessor = accessor;
  }
  public User GetCurrentUser() {
    //  Probably need some error handling and Special case pattern when
    // context is null.
    return (User) Accessor.HttpContext.User.Identity;
  }
}


public interface IEntityFrameworkOverrides {
  void EntityInitializing(ModelBuilder modelBuilder, IMutableEntityType entity);

  void EntityChanged(EntityEntry entity);
}


public abstract class UserAwareOverride : IEntityFrameworkOverrides {
  protected IUserContextProvider UserProvider { get; private set; }
  protected UserAwareOverride(IUserContextProvider userProvider)
  {
    UserProvider = userProvider;
  }
  public abstract void EntityInitializing(ModelBuilder modelBuilder, IMutableEntityType entity);

  public abstract void EntityChanged(EntityEntry entity);
}


public class ApplicationContext : IdentityDbContext<User> {

  private static bool ConfigurOverridesSet = false;
  protected static readonly List<IEntityFrameworkOverrides> EFOverrides = new List<IEntityFrameworkOverrides>();

  public static void ConfigureOverrides(IEnumerable<IEntityFrameworkOverrides> overrides) {
    if (ConfigurOverridesSet) {
     throw new NotSupportedException("Cannot set overrides on SplitFamContext More than once.");
    }
    EFOverrides.AddRange(overrides);
    ConfigurOverridesSet = true;
  }

  public ApplicationContext(DbContextOptions<ApplicationContext> options) 
    :base(options) { }
}

然后在Startup中,我只是这样做了:

public IServiceProvider ConfigureServices(IServiceCollection services) {
  services.AddMvc();

  var builder = new ContainerBuilder();

  services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
  services.AddSingleton<IUserContextProvider, MvcUserContextProvider>();

  services.AddDbContext<ApplicationContext>(options => {

  options.UseNpgsql(
    Configuration.GetConnectionString("ApplicationContext"));
  });

  services.AddIdentity<User, IdentityRole>()
    .AddEntityFrameworkStores<ApplicationContext>()
    .AddDefaultTokenProviders();

  builder.Populate(services);
  this.ApplicationContainer = builder.Build();

  // Create the IServiceProvider based on the container.
  return new AutofacServiceProvider(this.ApplicationContainer);
}

public void Configure(
  IApplicationBuilder app,
  IHostingEnvironment env,
  ILoggerFactory loggerFactory,
  IApplicationLifetime appLifetime) {
  if (env.IsDevelopment()) {
    app.UseDeveloperExceptionPage();
  }
  loggerFactory.AddConsole(this.Configuration.GetSection("Logging"));
  loggerFactory.AddDebug();

  app.UseMvc();

  var userContexProvider = app.ApplicationServices.GetService<IUserContextProvider>();
  ApplicationContext.ConfigureOverrides(new List<IEntityFrameworkOverrides>(){
    new SoftDeleteOverrides(userContexProvider),
    new TrackCreatedOverride(userContexProvider),
    new TrackModifiedOverride(userContexProvider)
  });

  appLifetime.ApplicationStopped.Register(() => {
    this.ApplicationContainer.Dispose();
  });
}

可能需要一些调整,但我不喜欢它,但是在您可以将服务注入DbContext之前,它可能是一种解决方法。

您可以使用的另一种方法是像在旧版本的MVC中那样获取静态HttpContext。 在此处找到解决方案: https : //www.strathweb.com/2016/12/accessing-httpcontext-outside-of-framework-components-in-asp-net-core/

我仍然还没有尝试过Thread.CurrentPrincipal.Identity,也不知道有什么问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM