La mejor solución sería utilizar una unidad de trabajo para ajustar el contexto de datos, así como administrar la vida útil de la conexión y permitirle trabajar con múltiples repositorios (si estaba dispuesto a seguir ese camino) .
Resumen de la ejecución:
- crear una interfaz (
IUnitOfWork
) que expone las propiedades de sus DbSet
's, así como un método llamado Commit
- Crear una aplicación (
EntityFrameworkUnitOfWork
), implementando según sea necesario. Commit simplemente llama a SaveChanges en la clase base (DbContext
), y también proporciona un buen enganche para la lógica de último minuto.
- Su controlador acepta una
IUnitOfWork
, utilizar DI (preferentemente) para resolver una EntityFrameworkUnitOfWork
, con un HTTP-marco con ámbito vida entorno (StructureMap es bueno para esto)
- (opcional, pero recomendado) crear un repositorio que también toma el
IUnitOfWork
, y funciona a través de su controlador.
HTH
EDITAR - En respuesta a los comentarios
Oh, ¿cómo se puede hacer un trabajo que implica la creación de registros en varios modelos, entonces? es decir, crear un nuevo usuario y una nueva publicación en la misma transacción.
Dado que usa ASP.NET MVC, los controladores deben aceptar un IUnitOfWork
en su constructor.
He aquí un ejemplo, basado en lo que has pedido
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());
}
}
}
Y una última pregunta, ¿qué hacer con ámbito curso de la vida del HTTP-contexto?
objetos en DI-talk tienen configuración de administración de alcance que incluyen por hilo, por sesión, por la petición http, Singleton, etc.
HTTP-marco con ámbito es el ajuste recomendado para aplicaciones web. Significa "actualizar un contexto cuando aparece una solicitud HTTP y deshacerse de él cuando finaliza la solicitud".
Además, cuando utiliza UnitOfWork con un ORM, debe tener en cuenta que si falla una confirmación, entonces necesita un nuevo Contexto/Unidad de Trabajo http://lavinski.tumblr.com/post/9114111237/object-relational-mapper -exceptions –