#asp.net-mvc-2 #pipeline #ninject-2
#asp.net-mvc-2 #конвейер #ninject-2
Вопрос:
У меня есть приложение MVC 2.0, использующее Ninject.Web.Mvc2 и шаблон репозитория (построенный на модели entity framework). Я пытаюсь создать новый 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]);
}
Класс-оболочка — это просто универсальный объект для включения всего, что я хочу уничтожить в конце запроса. В данном конкретном случае я использую его для создания моего нового 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
}
Когда мой контроллер вызывает метод Get внутри моего объекта UserRepository в первый раз, он отлично работает. Если я нажму refresh (или, я предполагаю, также postback), _db равно нулю. Когда я пытаюсь выполнить пошаговое выполнение в отладчике, я обнаруживаю, что метод Controller Index( ) вызывается перед вызовом Application_BeginRequest(). Я думал, что у меня есть понимание «конвейера» (я привык называть вещи жизненным циклом страницы из WebForms), но теперь я немного заблудился. Может кто-нибудь уточнить, где в моем мозгу пересеклись некоторые провода? Как я уже сказал, это, вероятно, не самый красивый метод, но у меня было всего около полутора недель, чтобы изучить MVC, DI с Ninject, репозиторий и Entity Framework, поэтому, пожалуйста, не думайте, что вы говорите со мной свысока, если кажется, что я нарушил что-то очень простое.
Комментарии:
1. вы не должны
Bind
вводить BeginRequest. Посмотрите на образец и используйте модуль для их размещения или, как минимум, делайте это один раз для каждого HttpApplication
Ответ №1:
Почему бы вам просто не использовать InRequestScope? Что вы делаете, так это добавляете новую привязку для каждого запроса. Это приведет к серьезным проблемам. Смотрите https://github.com/ninject/ninject.web.mvc/wiki/Unit-of-work-pattern-with-nhibernate
Это NHilbernate, но вы можете сделать то же самое с EntityFramework
Комментарии:
1. Я все еще новичок во всем этом, поэтому я не знал об InRequestScope. Я обязательно посмотрю на это. Из того, что я вижу онлайн, на первый взгляд кажется, что это именно то, что мне нужно. Спасибо!