RCravens tiene unas excelentes perspectivas. Me gustaría mostrarle cómo puede implementar sus sugerencias.
Sería bueno empezar por definir una interfaz para la clase de acceso de datos para implementar:
public interface IPostRepository
{
IEnumerable<Post> GetMostRecentPosts(int blogId);
}
luego implementar una clase de datos. Los contextos de Entity Framework son baratos de construir, y puede obtener un comportamiento incoherente cuando no se deshace de ellos, por lo que me parece que generalmente es mejor extraer de la memoria los datos que desea y luego eliminar el contexto.
public class PostRepository : IPostRepository
{
public IEnumerable<Post> GetMostRecentPosts(int blogId)
{
// A using statement makes sure the context is disposed quickly.
using(var context = new BlogContext())
{
return context.Posts
.Where(p => p.UserId == userId)
.OrderByDescending(p => p.TimeStamp)
.Take(10)
// ToList ensures the values are in memory before disposing the context
.ToList();
}
}
}
Ahora su controlador puede aceptar uno de estos repositorios como un argumento del constructor:
public class BlogController : Controller
{
private IPostRepository _postRepository;
public BlogController(IPostRepository postRepository)
{
_postRepository = postRepository;
}
public ActionResult Index(int blogId)
{
var posts = _postRepository.GetMostRecentPosts(blogId);
var model = new PostsModel { Posts = posts };
if(!posts.Any()) {model.Message = "This blog doesn't have any posts yet";}
return View("Posts", model);
}
}
MVC le permite utilizar su propia fábrica de controlador en lugar del defecto, por lo que puede especificar que el COI un marco como Ninject decide cómo se crean los Controladores. Puede configurar su marco de inyección para saber que cuando solicita un IPostRepository debe crear un objeto PostRepository.
Una gran ventaja de este enfoque es que hace que sus controladores sean comprobables por la unidad. Por ejemplo, si usted quiere asegurarse de que su modelo consigue un mensaje cuando no hay mensajes, se puede utilizar un marco de burla como Moq para establecer un escenario en el que sus declaraciones de repositorio no hay mensajes:
var repositoryMock = new Mock<IPostRepository>();
repositoryMock.Setup(r => r.GetMostRecentPosts(1))
.Returns(Enumerable.Empty<Post>());
var controller = new BlogController(repositoryMock.Object);
var result = (ViewResult)controller.Index(1);
Assert.IsFalse(string.IsNullOrEmpty(result.Model.Message));
Esto hace es fácil probar el comportamiento específico que está esperando de las acciones de su controlador, sin necesidad de configurar su base de datos ni nada especial como ese. Las pruebas unitarias como esta son fáciles de escribir, deterministas (su estado de aprobación/falla se basa en el código, no en los contenidos de la base de datos), y rápido (a menudo puede ejecutar miles de estos en un segundo).
¿Necesita este objeto solo para un controlador? –
Puede ser que deba usar el patrón singleton con instancia privada static y la propiedad de carga lenta de la instancia. –