Ninject PerRequest 注入
我有一个使用 Ninject.Web.Mvc2 和存储库模式(基于实体框架模型构建)的 MVC 2.0 应用程序。我正在尝试创建一个新的 ObjectContext,该上下文仅在请求期间有效。我试图通过以下方式实现这一点:
protected override IKernel CreateKernel(){
var kernel = new StandardKernel();
kernel.Load(Assembly.GetExecutingAssembly());
return kernel;
}
protected override void OnApplicationStarted()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
}
然后我没有办法保持这个足够通用,所以我开始在 BeginRequest 中工作:
protected void Application_BeginRequest()
{
string EntityConnectionString = ConfigurationManager.ConnectionStrings["Entities"].ConnectionString;
HttpContext.Current.Items.Add(_PerRequestContextObjectKey, new EntityFrameworkContextWrapper(EntityConnectionString));
this.Kernel.Bind<IUserRepository>().To<UserRepository>().WithConstructorArgument("ContextWrapper", HttpContext.Current.Items[_PerRequestContextObjectKey]);
}
Wrapper 类只是一个通用对象,用于包含我想在末尾杀死的任何内容。要求。在这种特定情况下,我使用它来创建新的 ObjectContext 并实现 IDisposable,这样我就可以执行以下操作:
protected void Application_EndRequest()
{
foreach (var Item in HttpContext.Current.Items)
{
if (Item.GetType() == typeof(IPerRequestLifetimeObjectWrapper))
{
(Item as IPerRequestLifetimeObjectWrapper).Dispose();
}
}
}
我确信这不是执行此操作的最漂亮的方式,但此时我正在尝试继续前进,因为我我花了很多时间“学习”所有这些东西。
然后像这样注入我的控制器:
public class AdminUserController : Controller
{
// Mark for Ninject
[Inject] public IUserRepository _userRepo { get; set; }
public ViewResult Index( )
{
return View(_userRepo.Get);
}
public ViewResult Edit(Guid UserUID)
{
return View(_userRepo.GetById(UserUID));
}
}
我的存储库也被注入:
[Inject]
public UserRepository(EntityFrameworkContextWrapper ContextWrapper )
// Mark for Ninject Dependency Injection
// Must receive Wrapper that contains active ObjectContext
{
_db = ContextWrapper.Entities; //Not actually named this, just easier for typing right now
}
当我的控制器第一次调用我的 UserRepository 对象内的 Get 方法时,它工作得很好。如果我点击刷新(或者我猜回发),_db 为 Null。当我尝试单步执行调试器时,我发现在调用 Application_BeginRequest() 之前调用了 Controller Index() 方法。我以为我已经了解了“管道”(我习惯于从 WebForms 调用页面生命周期),但现在我有点迷失了。有人可以详细说明我的大脑有一些电线交叉的地方吗?就像我说的,这可能不是最漂亮的方法,但我只有大约一周半的时间来学习 MVC、DI with Ninject、Repository 和 Entity Framework,所以请不要觉得你在贬低对我来说,如果我似乎破坏了一些非常基本的东西。
I have a MVC 2.0 application using Ninject.Web.Mvc2 and a repository pattern (built over an entity framework model ). I am trying to create a new ObjectContext that will only live for the duration of the request. I am attempting to accomplish this in the following manner:
protected override IKernel CreateKernel(){
var kernel = new StandardKernel();
kernel.Load(Assembly.GetExecutingAssembly());
return kernel;
}
protected override void OnApplicationStarted()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
}
I then ran out of ideas for keeping this generic enough so I set to work in the BeginRequest:
protected void Application_BeginRequest()
{
string EntityConnectionString = ConfigurationManager.ConnectionStrings["Entities"].ConnectionString;
HttpContext.Current.Items.Add(_PerRequestContextObjectKey, new EntityFrameworkContextWrapper(EntityConnectionString));
this.Kernel.Bind<IUserRepository>().To<UserRepository>().WithConstructorArgument("ContextWrapper", HttpContext.Current.Items[_PerRequestContextObjectKey]);
}
The Wrapper class is just a generic object for including anything I want to kill at the end of request. In this specific case, I use it to create my new ObjectContext and also implement IDisposable so I can do the following:
protected void Application_EndRequest()
{
foreach (var Item in HttpContext.Current.Items)
{
if (Item.GetType() == typeof(IPerRequestLifetimeObjectWrapper))
{
(Item as IPerRequestLifetimeObjectWrapper).Dispose();
}
}
}
I'm sure it's not the prettiest way of doing this, but at this point I'm trying to get moving since I've spent so much time "learning" all this stuff.
My Controller is then injected like so:
public class AdminUserController : Controller
{
// Mark for Ninject
[Inject] public IUserRepository _userRepo { get; set; }
public ViewResult Index( )
{
return View(_userRepo.Get);
}
public ViewResult Edit(Guid UserUID)
{
return View(_userRepo.GetById(UserUID));
}
}
and my Repository gets injected as well:
[Inject]
public UserRepository(EntityFrameworkContextWrapper ContextWrapper )
// Mark for Ninject Dependency Injection
// Must receive Wrapper that contains active ObjectContext
{
_db = ContextWrapper.Entities; //Not actually named this, just easier for typing right now
}
When my Controller calls the Get method inside my UserRepository object the first time it works great. If I hit refresh ( or I'm guessing postback as well ), _db is Null. When I try to step through the debugger, I find that the Controller Index( ) method is being called before a Application_BeginRequest() is called. I thought I had an understanding of the "pipeline" ( I'm used to calling things page lifecycle from WebForms ), but now I'm a bit lost. Can someone elaborate on where my brain has some wires crossed? Like I said, this probably isn't the prettiest method, but I've only had about a week and a half to learn MVC, DI with Ninject, Repository, and Entity Framework so please don't feel like you're talking down to me if it seems like I broke something very basic.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
为什么不直接使用 InRequestScope 呢?您要做的就是为每个请求添加一个新的绑定。这将导致严重的问题。
请参阅 https://github.com/ ninject/ninject.web.mvc/wiki/Unit-of-work-pattern-with-nhibernate
这是 NHilbernate,但你可以用 EntityFramework 做同样的事情
Why don't you simply use InRequestScope? What you do is adding a new binding for each request. This will lead to severe problems.
See https://github.com/ninject/ninject.web.mvc/wiki/Unit-of-work-pattern-with-nhibernate
It's NHilbernate but you can do the same with EntityFramework