使用依赖注入
正如其他人所说并且可能会重申的那样,“正确的方式”通常被认为是依赖注入。
在我最近的项目中,我已经组织了一些事情,所以我几乎完成了这个项目,而 DI 非常轻松,我自己做(而不是使用注射器)。其中一个主要因素是相当严格地遵守这种结构:
WebProject
| |
| DataServices
| | |
ViewModels EntityModels
在一个工作单元期间对所有数据服务的访问通过单个 DataServiceFactory 实例发生,这需要一个 MyDbContext 实例。另一个因素是完全 RESTful 的应用程序设计 - 这意味着我不必在我的代码中散布持久性功能。
没有依赖注入
也就是说,也许 DI 在这个项目中不适合你。也许:
- 您不打算编写单元测试
- 您需要更多时间来了解 DI
- 您的项目结构已经深度集成了 EF
在 ASP.NET MVC 中,工作单元通常与请求生命周期完全一致 - 即 HttpContext.Current。因此,您可以根据请求懒惰地实例化存储库“单例”,而不是使用 DI。这是一个以当前上下文作为后备存储的经典单例模式,用于保存您的DbContext:
public class RepositoryProxy {
private static HttpContext Ctx { get { return HttpContext.Current; } }
private static Guid repoGuid = typeof(MyDbContext).GUID;
public static MyDbContext Context {
get {
MyDbContext repo = Ctx.Items[repoGuid];
if (repo == null) {
repo = new MyDbContext();
Ctx.Items[repoGuid] = result;
}
return repo;
}
}
public static void SaveIfContext() {
MyDbContext repo = Ctx.Items[repoGuid];
if (repo != null) repo.SaveChanges();
}
}
如果你觉得特别懒惰,你也可以自动SaveChanges(当然,你仍然需要手动调用它来检查副作用,比如检索新项目的 id):
public abstract class ExtendedController : Controller {
protected MyDbContext Context {
get { return RepositoryProxy.Context; }
}
protected override void OnActionExecuted(ActionExecutedContext filterContext) {
RepositoryProxy.SaveIfContext();
base.OnActionExecuted(filterContext);
}
}