Rus*_*ino 6 ninject unit-of-work repository-pattern entity-framework-5
在我的服务层上,我UnitOfWork在构造函数中注入了一个和两个存储库.工作单元和存储库有一个DbContext我想在两者之间共享的实例.我怎么能用Ninject做到这一点?应考虑哪个范围?
我不在网络应用程序中,所以我无法使用InRequestScope.
我尝试做类似的事情......然而我正在使用DI,我需要我的UoW Dispose并且像这样创建.
using (IUnitOfWork uow = new UnitOfWorkFactory.Create())
{
_testARepository.Insert(a);
_testBRepository.Insert(b);
uow.SaveChanges();
}
Run Code Online (Sandbox Code Playgroud)
编辑:我只是想确定我理解...看看https://github.com/ninject/ninject.extensions.namedscope/wiki/InNamedScope我虽然关于我当前使用Ninject的控制台应用程序架构.
让我们说:
A类是服务层类
B类是一个工作单元,它接受参数接口(IContextFactory)
C类是一个接口参数的存储库(IContextFactory)
这里的想法是能够在2个或更多存储库上执行上下文操作,并使用工作单元来应用更改.
D类是一个上下文工厂(实体框架),它提供了一个实例(保存在容器中)的上下文,它在Class B et C之间共享(并且将用于其他存储库).
上下文工厂将实例保存在他的容器中,所以我不想重复使用这个实例的所有名称,因为上下文需要在服务操作结束时处理..实际上InNamedScope的主要目的是什么?
解决方案是,但我不确定我做得对,服务实例将是transcient,这意味着他们实际上从未处理过?:
Bind<IScsContextFactory>()
.To<ScsContextFactory>()
.InNamedScope("ServiceScope")
.WithConstructorArgument(
"connectionString",
ConfigurationUtility.GetConnectionString());
Bind<IUnitOfWork>().To<ScsUnitOfWork>();
Bind<IAccountRepository>().To<AccountRepository>();
Bind<IBlockedIpRepository>().To<BlockedIpRepository>();
Bind<IAccountService>().To<AccountService>().DefinesNamedScope("ServiceScope");
Bind<IBlockedIpService>().To<BlockedIpService>().DefinesNamedScope("ServiceScope");
Run Code Online (Sandbox Code Playgroud)
更新:这种方法对NuGet当前工作有效,但是在InCallscope实现中存在异常,这在当前的Unstable NuGet包中得到了修复.我会在几天内调整这个答案,以反映一些仔细研究后的最佳方法.注意,构建东西的高级方式将保持完全相同,只需Bind<DbContext>()确定范围的确切细节即可.(提示:CreateNamedScope在不稳定的情况下可以工作,或者可以将命令处理程序设置为DefinesNamedScope.原因我不这样做是因为我希望有一些组合/播放的东西 InRequestScope)
我强烈建议您阅读Ninject.Extensions.NamedScope集成测试(严肃地说,找到它们并阅读并重新阅读它们)
这DbContext 是工作单位所以不需要进一步包装.
由于您希望能够在飞行中拥有多个"请求"并希望在它们之间共享一个工作单元,您需要:
Bind<DbContext>()
.ToMethod( ctx =>
new DbContext(
connectionStringName: ConfigurationUtility.GetConnectionString() ))
.InCallScope();
Run Code Online (Sandbox Code Playgroud)
的InCallScope()意思是说:
kernel.Get() 调用组成的给定对象图(因此在调用范围内),需要一个的每个人DbContext将获得相同的实例.IDisposable.Dispose()将Kernel.Release()在根对象发生时调用(或者Kernel.Components.Get<ICache>().Clear()如果不是则发生根则调用.InCallScope())应该没有理由使用InNamedScope()和DefinesNamedScope(); 您没有尝试从默认池/父级/分组中排除的长期对象.
如果您执行上述操作,您应该能够:
var command = kernel.Get<ICommand>();
try {
command.Execute();
} finally {
kernel.Components.Get<ICache>().Clear( command ); // Dispose of DbContext happens here
}
Run Code Online (Sandbox Code Playgroud)
Command实现如下:
class Command : ICommand {
readonly IAccountRepository _ar;
readonly IBlockedIpRepository _br;
readonly DbContext _ctx;
public Command(IAccountRepository ar, IBlockedIpRepository br, DbContext ctx){
_ar = ar;
_br = br;
_ctx = ctx;
}
void ICommand.Execute(){
_ar.Insert(a);
_br.Insert(b);
_ctx.saveChanges();
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,一般来说,我以这种方式避免使用隐含的工作单元,而是表现它的创建和Disposal.这使得Command看起来像这样:
class Command : ICommand {
readonly IAccountService _as;
readonly IBlockedIpService _bs;
readonly Func<DbContext> _createContext;
public Command(IAccountService @as, IBlockedIpServices bs, Func<DbContext> createContext){
_as = @as;
_bs = bs;
_createContext = createContext;
}
void ICommand.Execute(){
using(var ctx = _createContext()) {
_ar.InsertA(ctx);
_br.InsertB(ctx);
ctx.saveChanges();
}
}
Run Code Online (Sandbox Code Playgroud)
这不涉及的使用.InCallScope()上Bind<DbContext>()(但要求存在Ninject.Extensions.Factory的FactoryModule合成Func<DbContext>,从一个简单的Bind<DbContext>().
| 归档时间: |
|
| 查看次数: |
6521 次 |
| 最近记录: |