Лучшим решением было бы использовать Единицу работы , чтобы обернуть контекст данных, а также управлять временем жизни соединения и позволить вам работать с несколькими репозитариями (если вы были склонны к отказу этот путь).
Краткое описание реализации:
- Создайте интерфейс (
IUnitOfWork
), который предоставляет свойства для ваших DbSet
, а также один метод с именем Commit
- Создать реализацию (
EntityFrameworkUnitOfWork
), реализуя по мере необходимости. Коммит просто вызывает 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's pushed to DB
}
catch (Exception exc)
{
ModelState.AddError("UhOh", exc.ToString());
}
}
}
И еще один вопрос: что делает время жизни в контексте HTTP?
Объекты в DI-talk имеют параметры управления областью действия, которые включают в себя поток, сеанс, http-запрос, одиночный вызов и т. Д.
HTTP-контекстная область является рекомендуемой настройкой для веб-приложений. Это означает «создать контекст, когда поступит HTTP-запрос, и избавиться от него, когда запрос завершится».