看看如何使用数据库上下文池的示例,我发现它是设计用于ServiceCollection
的:
var serviceProvider = new ServiceCollection()
.AddDbContextPool<AdventureWorksContext>(options => { //options })
.BuildServiceProvider();
但是简单喷射器呢?是否可以在Simple Injector容器中注册数据库池?
p.s。我的应用程序不是ASP.NET MVC,只是一种DAL
答案 0 :(得分:5)
在ASP.NET Core中集成Simple Injector时,会将框架和第三方组件保留在.NET Core配置系统中。这意味着启用Entity Framework Core上下文池的过程与Microsoft记录的完全相同:
services.AddDbContextPool<BloggingContext>(
options => options.UseSqlServer(connectionString));
但是,与简单注入器does not replace the built-in configuration system一样,您将必须instruct简单注入器才能从.NET Core配置系统自动加载缺少的注册信息(例如DbContext
)。可以通过使用EnableSimpleInjectorCrossWiring
和AutoCrossWireAspNetComponents
扩展方法来完成,如此处所示。
private SimpleInjector.Container container;
public void ConfigureServices(IServiceCollection services) {
...
services.EnableSimpleInjectorCrossWiring(this.container);
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env) {
...
container.AutoCrossWireAspNetComponents(app);
}
使用此设置,BloggingContext
可以注入到从简单注入器解析的任何组件中,而BloggingContext
由实体框架池化。
不幸的是,当涉及到在.NET Core控制台应用程序中使用Entity Framework Core上下文池时,涉及的内容更多。这是因为上下文池与新的MS.DI抽象机制高度集成,而Simple Injector的交叉接线功能目前需要ASP.NET Core(这是我们在未来版本中might improve所采用的功能)。
当前可以在.NET Core控制台应用程序中设置EF上下文池,如下所示:
static void Main(string[] args)
{
var container = new Container();
container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();
// Register stuff
RegisterBloggingContext(container);
container.Verify();
// Start using Simple Injector as usual:
using (AsyncScopedLifestyle.BeginScope(container))
{
var c = container.GetInstance<SomeComponentDependingOnBloggingContext>();
}
}
// Magic starts here:
private static void RegisterBloggingContext(Container container)
{
// Build an IServiceProvider with DbContext pooling and resolve a scope factory.
var scopeFactory = new ServiceCollection()
.AddDbContextPool<BloggingContext>(o => o.UseSqlServer(connectionString))
.BuildServiceProvider(validateScopes: true)
.GetRequiredService<IServiceScopeFactory>();
// Use that scope factory to register an IServiceScope into Simple Injector
container.Register<IServiceScope>(scopeFactory.CreateScope, Lifestyle.Scoped);
// Cross wire the DbContext by resolving the IServiceScope and requesting the
// DbContext from that scope.
container.Register(() => container.GetInstance<IServiceScope>().ServiceProvider
.GetService<BloggingContext>(),
Lifestyle.Scoped);
}
此代码的作用是允许EF将其组件注册到MS.DI ServiceCollection
类中。使用该服务集合,可以构建一个IServiceProvider
(MS.DI容器),并从该容器中请求一个IServiceScopeFactory
。
该IServiceScopeFactory
用于注册IServiceScope
。这是MS.DI的范围界定机制。通过在Simple Injector中注册它,MS.DI范围将由Simple Injector管理。这意味着,当放置简单注入器Scope
时,IServiceScope
(因为IServiceScope
实现IDisposable
)也将随之存在,并且已注册的DbContext
将与发送回池(在处理DbContext
时会发生这种情况)。
最后一部分是DbContext
本身的“交叉布线”。通过注册将首先从Simple Injector请求IServiceScope
的委托来完成。同样,由于IServiceScope
是从Simple Injector解析的,因此它也将由Simple Injector处置(因为IServiceScope
实现了IDisposable
)。使用解析的IServiceScope
,可以从该MS.DI范围请求DbContext
。
最后,DbContext的生存期由MS.DI范围管理,但该范围由Simple Injector的范围管理。
这有点令人讨厌,但不幸的是,EF Core的上下文池已深度集成到服务收集模型中。
如果您要构建库(即非启动项目),请停止正在执行的操作。仅应用程序的启动程序集应具有Composition Root,并且只有合成根目录应使用DI容器(例如,简单注入器或MS.DI的`ServiceCollection)。您应用程序中的所有其他库都应忽略(可能)容器的存在:
如果使用DI容器,则“合成根”应该是唯一使用DI容器的地方。在合成根目录之外使用DI容器会导致服务定位器反模式(source)
答案 1 :(得分:0)
您可以使用
container.Register(() =>
serviceProvider.GetRequiredService<AdventureWorksContext>());
让ServiceProvider根据请求解决依赖关系。
答案 2 :(得分:0)
除了@Steven的出色答案之外,这是他的控制台应用程序答案,但使用array (
0 => '',
1 => '8',
2 => '8',
3 => '8',
4 => '8',
5 => '8',
6 => '1',
7 => '1000',
8 => '2020',
)
具有上下文(隐式)。
UseInternalServiceProvider
Demo,您想使用var services = new ServiceCollection();
services.AddEntityFrameworkSqlServer();
services.AddSingleton<Microsoft.Extensions.Logging.ILoggerFactory>(new Microsoft.Extensions.Logging.LoggerFactory());
services.AddSingleton<IInterface>(new MyImplemenation());
services.AddDbContextPool<EFViewAndManyToManyDb>(optionsBuilder => {
optionsBuilder.UseSqlServer("");
});
services.AddSimpleInjector(container);
services
.BuildServiceProvider(validateScopes: true)
.UseSimpleInjector(container);
。 TLDR:如果您的UseInternalServiceProvider
具有依赖项,例如DbContext
。您还需要添加IInterface
Nuget程序包。