簡體   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