【问题标题】:ASP.NET Core DI with Simple Injector sharing DbContextASP.NET Core DI 与 Simple Injector 共享 DbContext
【发布时间】:2019-08-08 10:14:31
【问题描述】:

我正在设置一个 ASP.NET Core 项目并遵循基于 Tripod 项目的工作的 CQRS 模式。我遵循了 Simple Injector 集成指南,但在某一点上有点困惑......我想继续使用 UseInMemoryDatabase 选项进行测试,并且只能使用 Core DI AddDbContext 方法找到示例。

我的 DbContext 实现了几个接口:

public class EntityDbContext : DbContext,
    IUnitOfWork,
    IReadEntities,
    IWriteEntities
{
    // code here
}

我在Startup.ConfigureServices 方法中这样做:

services.AddDbContext<EntityDbContext>(options => options.UseInMemoryDatabase("Snoogans"));

并在 Startup.Configure 方法中遵循 SI 集成指南:

container.Register<IUnitOfWork, xxxx>();
container.Register<IReadEntities, xxxx>();
container.Register<IWriteEntities, xxxx>();

我是否能够通过交叉线将核心注册到每个目标的插件,还是应该直接在 SI 中注册上下文?

== 我正在玩 Tripod 的原始概念:

var contextRegistration =
    lifestyle.CreateRegistration<EntityDbContext, EntityDbContext>(container);
container.AddRegistration(typeof(EntityDbContext), contextRegistration);
container.AddRegistration(typeof(IUnitOfWork), contextRegistration);
container.AddRegistration(typeof(IWriteEntities), contextRegistration);
container.AddRegistration(typeof(IReadEntities), contextRegistration);

尝试使用 SI 做所有事情,但不确定我如何获得 3 个接口的注册:

container.Register<EntityDbContext>(() =>
{
    var optionsBuilder =
        new DbContextOptionsBuilder<EntityDbContext>().UseInMemoryDatabase("Snoogans");
    return new EntityDbContext(optionsBuilder.Options);
});
container.AddRegistration<IUnitOfWork>(xxxx);
container.AddRegistration<IReadEntities>(xxxx);
container.AddRegistration<IWriteEntities>(xxxx);

【问题讨论】:

    标签: c# asp.net-core dependency-injection entity-framework-core simple-injector


    【解决方案1】:

    我是否能够通过交叉线将核心注册到每个目标的插件,还是应该直接在 SI 中注册上下文?

    这两种选择都是可行的。您可以选择将 DbContext 直接注册到 Simple Injector 中。这通常是最明显的选择,因为您的 DbContext 是一个应用程序组件。应用程序组件通常应在您的应用程序容器(即 Simple Injector)中注册,而不是在框架的注册系统中(即ServiceCollection)。

    然而,在注册DbContext 时,与 ASP.NET Core 配置系统有一些紧密的集成。这可以更直接地在那里进行注册,并简单地从 Simple Injector 进行交叉接线。这让配置系统可以控制 DbContext 的创建和销毁。这在执行 DbContext 池之类的操作时变得特别有价值,因为此池功能与此配置和注册 API 紧密耦合。

    通常,这两个选项都非常简单,但是因为您的 DbContext 实现了多个您想要单独注册的接口,这会导致您的注册变得更加复杂。如果您也使用内置的 DI 容器,情况也会如此,因此这不是 Simple Injector 特有的。

    在您的情况下,纯粹在 Simple Injector 中进行注册将如下所示:

    var reg = Lifestyle.Scoped.CreateRegistration(() =>
        {
            var optionsBuilder =
                new DbContextOptionsBuilder<EntityDbContext>().UseInMemoryDatabase("Snoogans");
            return new EntityDbContext(optionsBuilder.Options);
        },
        container);
    
    container.AddRegistration<IUnitOfWork>(reg);
    container.AddRegistration<IReadEntities>(reg);
    container.AddRegistration<IWriteEntities>(reg);
    

    如果您选择从 .NET Core 配置系统交叉连接 DbContext,您的配置将如下所示:

    // Add to the built-in ServiceCollection
    services.AddDbContext<EntityDbContext>(options => options.UseInMemoryDatabase("Snoogans"));
    
    // Cross-wire in Simple Injector
    container.CrossWire<EntityDbContext>(app);
    
    // Pull that registration out of Simple Injector and use it for the interface registrations
    var reg = container.GetRegistration(typeof(EntityDbContext)).Registration;
    
    // Same as before
    container.AddRegistration<IUnitOfWork>(reg);
    container.AddRegistration<IReadEntities>(reg);
    container.AddRegistration<IWriteEntities>(reg);
    

    如果您不使用 Simple Injector,而是纯粹使用 .NET Core 的内置 DI Container,则注册将如下所示:

    services.AddDbContext<EntityDbContext>(options => options.UseInMemoryDatabase("Snoogans"));
    
    services.AddScoped<IUnitOfWork>(c => c.GetRequiredService<EntityDbContext>());
    services.AddScoped<IReadEntities>(c => c.GetRequiredService<EntityDbContext>());
    services.AddScoped<IWriteEntities>(c => c.GetRequiredService<EntityDbContext>());
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-07
      • 1970-01-01
      • 2018-10-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多