Ответ 1
Лучшим решением было бы использовать Unit of Work, чтобы обернуть контекст данных, а также управлять временем жизни соединения и позволить вам работать с несколькими репозиториями (если вы так склонны идти вниз по этому пути).
Краткое описание реализации:
- Создайте интерфейс (
IUnitOfWork
), который предоставляет свойства дляDbSet
, а также один метод под названием Commit - Создайте реализацию (
EntityFrameworkUnitOfWork
), выполнив при необходимости. Commit просто вызывает SaveChanges в базовом классе (DbContext
), а также обеспечивает хороший крючок для последней минуты. - Ваш контроллер принимает
IUnitOfWork
, используйте DI (желательно), чтобы разрешитьEntityFrameworkUnitOfWork
, с параметром с привязкой к контексту HTTP ( StructureMap подходит для этого) - (необязательно, но рекомендуется) создать репозиторий, который также принимает
IUnitOfWork
, и отработает это через ваш контроллер.
НТН
РЕДАКТИРОВАТЬ - В ответ на комментарии
О, как вы можете работать над созданием записей в нескольких моделях? т.е. создать нового пользователя и новое сообщение в той же транзакции.
Учитывая, что вы используете ASP.NET MVC, ваши контроллеры должны принимать IUnitOfWork
в своем конструкторе.
Вот пример, основанный на том, что вы просили
public SomeController : Controller
{
private IUnitOfWork _unitOfWork;
private IUserRepo _userRepo;
private IPostRepo _postRepo;
public SomeController(IUnitOfWork unitOfWork, IUserRepo userRepo, IPostRepo postRepo)
{
_unitOfWork = unitOfWork; // use DI to resolve EntityFrameworkUnitOfWork
_userRepo = userRepo;
_postRepo = postRepo;
}
[HttpPost]
public ActionResult CreateUserAndPost(User user, Post post)
{
// at this stage, a HTTP request has come in, been resolved to be this Controller
// your DI container would then see this Controller needs a IUnitOfWork, as well
// as two Repositories. DI smarts will resolve each dependency.
// The end result is a single DataContext (wrapped by UoW) shared by all Repos.
try
{
userRepo.Add(user);
postRepo.Add(post);
// nothing has been sent to DB yet, only two objects in EF graph set to EntityState.Added
_unitOfWork.Commit(); // two INSERT pushed to DB
}
catch (Exception exc)
{
ModelState.AddError("UhOh", exc.ToString());
}
}
}
И еще один вопрос: что такое продолжительность жизни, связанная с HTTP-контекстом?
Объекты DI-talk имеют параметры управления областью, которые включают в поток, за сеанс, для каждого запроса HTTP, singleton и т.д.
Контекст HTTP-контекста является рекомендуемым параметром для веб-приложений. Это означает "новый контекст, когда приходит HTTP-запрос и избавляется от него, когда запрос завершен".