RCravens hat einige ausgezeichnete Einblicke. Ich möchte zeigen, wie Sie seine Vorschläge umsetzen können.
Es wäre gut, durch die Festlegung einer Schnittstelle für die Datenzugriffsklasse zu beginnen zu implementieren:
public interface IPostRepository
{
IEnumerable<Post> GetMostRecentPosts(int blogId);
}
Dann eine Datenklasse implementieren. Entity Framework-Kontexte sind kostengünstig zu erstellen, und Sie können inkonsistentes Verhalten erhalten, wenn Sie nicht über sie verfügen. Daher ist es in der Regel besser, die gewünschten Daten in den Speicher zu übernehmen und den Kontext zu entfernen.
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();
}
}
}
Jetzt Ihr Controller eine dieser Repositories als Konstruktor Argument akzeptieren:
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 Sie Ihre eigene Controller Factory anstelle des Standard verwendet werden kann, so dass Sie, dass Ihre IoC angeben Framework wie Ninject entscheidet, wie Controller erstellt werden. Sie können Ihr Injection-Framework so einrichten, dass es bei der Anforderung eines IPostRepository ein PostRepository-Objekt erstellt.
Ein großer Vorteil dieses Ansatzes besteht darin, dass Ihre Controller Einheit-testbar werden. Zum Beispiel, wenn Sie sicherstellen möchten, dass Ihr Modell eine Nachricht bekommt, wenn es keine Beiträge sind, können Sie einen Mockframework wie Moq verwenden, um ein Szenario einzurichten, in denen das Repository lieferte keine Beiträge:
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));
Dies macht Es ist einfach, das spezifische Verhalten zu testen, das Sie von Ihren Controller-Aktionen erwarten, ohne dass Sie Ihre Datenbank oder etwas Spezielles einrichten müssen. Unit-Tests wie diese sind einfach zu schreiben, deterministisch (ihr Pass/Fail-Status basiert auf dem Code, nicht auf dem Datenbank-Inhalt) und schnell (Sie können oft Tausende von diesen in einer Sekunde ausführen).
Benötigen Sie dieses Objekt nur für einen Controller? –
Möglicherweise sollten Sie Singleton Muster mit privaten statischen Instanz und lazy loading verwenden, um Eigenschaft für die Instanz zu erhalten. –