【问题标题】:Multiple DBContext implemented with same Interface使用相同接口实现的多个 DBContext
【发布时间】:2022-08-18 16:14:30
【问题描述】:

我正在尝试注册多个(2)DbContexts 使用通用接口(@98​​7654324@)实现。然后我想在我的控制器中使用一些逻辑来决定我将使用哪个上下文。

我在HomeController 中注入IEnumerable<IDbContext>,但它只用我注册的第一个实例来解决。

程序.cs

builder.Services.AddDbContext<IDbContext, ApplicationDbContext>(context => { context.UseInMemoryDatabase(\"ConferencePlanner\");});
builder.Services.AddDbContext<IDbContext, Application2DbContext>(context => { context.UseInMemoryDatabase(\"ConferencePlanner2\");});

DBContext1

public class ApplicationDbContext: DbContext, IDbContext
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options): base(options){}
}

数据库上下文2

public class Application2DbContext: DbContext, IDbContext
{
    public Application2DbContext(DbContextOptions<Application2DbContext> options): base(options){}
}

IDbContext

public interface IDbContext {}

控制器:

 private readonly IEnumerable<IDbContext> contexts;

 public HomeController(ILogger<HomeController> logger, IEnumerable<IDbContext> contexts)
 {
     _logger = logger;
     this.contexts = contexts;
 }

我在这里期待DbContexts 如果我有多个具有通用接口的存储库/服务,我已经看到这种方法有效。

  • 我认为您也应该在 sturtup.cs 中通过 IEnumerable 。我的意思是:builder.Services.AddDbContext&lt;IEnumerable&lt;IDbContext&gt;, List&lt;DbContext&gt;&gt;(YOUR_IMPLEMENTATION) 或在您的控制器构造函数中放置 2 个上下文我的意思是:HomeController(IDbContext contexts1 , IDbContext&gt; contexts2)
  • AddDbContext 没有像你的例子那样的重载。它有这样的public static IServiceCollection AddDbContext&lt;TContextService, TContextImplementation&gt;(this IServiceCollection serviceCollection, Action&lt;DbContextOptionsBuilder&gt;? optionsAction = null, ServiceLifetime contextLifetime = ServiceLifetime.Scoped, ServiceLifetime optionsLifetime = ServiceLifetime.Scoped) where TContextImplementation : DbContext, TContextService; 因为它不工作
  • 这听起来可能是多租户设计。考虑使用 Scoped 或 Singleton Factory 依赖项来根据控制器等的需要构造/提供合适的 DbContext。 (即相关租户)

标签: c# .net entity-framework .net-core entity-framework-core


【解决方案1】:

我相信这是因为您正在尝试使用 AddDbContext 方法注册数据库上下文。如果您尝试使用工厂注册您的实例,它应该可以按预期工作。代码可能如下所示:

builder.Services.AddTransient<IDbContext>(sp => {
  var context = new ApplicationDbContext();
  ...
  context.UseInMemoryDatabase("ConferencePlanner");
  return context;
});

builder.Services.AddTransient<IDbContext>(sp => {
  var context = new ApplicationDb2Context();
  ...
  context.UseInMemoryDatabase("ConferencePlanner2");
  return context;
});

然后,当您将 IEnumerable 传递给控制器​​时,您将获得两个实例。但是,我会考虑在特定情况下使用作用域上下文,以便控制器始终使用唯一的实例。

【讨论】:

    猜你喜欢
    • 2014-10-25
    • 2021-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-03
    • 1970-01-01
    • 1970-01-01
    • 2012-12-22
    相关资源
    最近更新 更多