具有简单注入器共享DbContext的ASP.NET Core DI

时间:2019-03-18 04:45:24

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

我正在建立一个ASP.NET Core项目,并按照C Tripod项目为基础的CQRS模式。我遵循了Simple Injector集成指南,但在一点上有些困惑……我想继续使用UseInMemoryDatabase选项进行测试,并且只能使用Core DI {{1} }方法。

我的DbContext实现了几个接口:

AddDbContext

我正在使用public class EntityDbContext : DbContext, IUnitOfWork, IReadEntities, IWriteEntities { // code here } 方法:

Startup.ConfigureServices

并按照SI集成在Startup.Configure方法中对此进行指导:

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

我是否可以通过Crosswire获得Core注册,以便将它们分别插入到目标中?还是应该直接在SI中注册上下文?

== 我在玩三脚架的原始概念:

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

尝试使用SI进行所有操作,但不确定如何获得3个接口的注册:

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);

1 个答案:

答案 0 :(得分:3)

Am I able to get the Core registration over crosswire to plugin to the target for each of them or should I just be registering the context directly in SI?

Both options are feasible. You can chose to register the DbContext directly into Simple Injector. This would typically be the most obvious choice as your DbContext is an application component. Application components should typically be registered in your application container (i.e. Simple Injector) instead of in the framework's registration system (i.e. ServiceCollection).

When it comes to registering DbContext, however, there is some tight integration with the ASP.NET Core configuration system. This can make it more straightforward to do the registration there and simply cross-wire from Simple Injector. That lets the configuration system stay in control over the creation and destruction of the DbContext. This becomes especially valuable when doing things like DbContext pooling, as this pooling functionality is tightly coupled with this configuration and registration API.

Typically, both options are pretty straightforward, but because your DbContext implements multiple interfaces that you want to register seperately, this causes your registrations to become more complicated. This would have been the case as well in case you're using the built-in DI Container as well, so this is not specific to Simple Injector.

In your case, doing the registrations purely in Simple Injector would look like this:

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);

In case you chose to cross-wire your DbContext from the .NET Core configuration system, your configuration would look as follows:

// 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);

If you wouldn't be using Simple Injector, but purely .NET Core's built-in DI Container, the registration would look as follows:

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>());