我应该如何在 MVC 控制器中实例化数据上下文(实体 fw):
- a) 作为类中的属性
- b) 作为类中的一个字段
- c) 作为 Action 中的变量
- d) 使用 Repository 模式抽象出你的 DbContext
在 WebForms 中我会使用 c),因为 b) 会跨事件维护 db 对象状态,这通常不是我想要的。
我实际上从未使用过a)。
我应该如何在 MVC 控制器中实例化数据上下文(实体 fw):
在 WebForms 中我会使用 c),因为 b) 会跨事件维护 db 对象状态,这通常不是我想要的。
我实际上从未使用过a)。
您可能应该使用repository pattern
withdependency injection
通过构造函数传入上下文,
并且使用它您将不得不使用像Unity这样的收费来在constructor
我想首先说我 100% 同意@jrummell,因为 DbContext 应该被实例化。但是,如果您不打算这样做,我将使用私有只读字段并提供两个构造函数:
public MyController() : this(new DbContext()) { }
public MyController(DbContext context)
{
this._dbContext = context;
}
这样您仍然可以注入 DbContext 进行测试。
有一个私有变量,它是您的存储库接口的对象,并在您的构造函数中实例化它。您现在可以在所有操作方法中使用它
public class ItemsController : Controller
{
private IRepositary repo;
public ItemsController()
{
repo = new Repositary(new YourDBContext());
}
public ActionResult Edit(int id)
{
var item=repo.GetItemById(id);
//if needed, map to your view model and return that to the view
// instead of model object to the view
return View(item);
}
}
推荐的方法是使用与持久性无关的数据访问模式,例如存储库模式。基本思想是创建特定于控制器的接口,以抽象出您的数据访问。
public interface ICatalogRepository : IRepository
{
Category GetCategory(int id);
Product GetProduct(int id);
void Add(Product product);
IEnumerable<Category> Categories { get; }
IEnumerable<Supplier> Suppliers { get; }
}
public class CatalogRepository : ICatalogRepository
{
private YourDbContext _db;
public CatalogRepository(YourDbContext db)
{
_db = db;
}
public Category GetCategory(int id)
{
return _db.Categories.Find(id);
}
/* ... */
}
然后你会在你的控制器中使用一个实例ICatalogRepository
——它不会有任何实体框架的知识。有关完整示例,请参阅在 ASP.NET MVC 中使用按请求工作单元模式。
除非这是一个非常小的应用程序或只有少数用户;或者应用程序的生命周期很短,我永远不会将任何数据访问“类似”的代码放在 UI 层中。您刚刚做出了会影响应用程序的可维护性和可测试性的设计决策。
我喜欢使用带有依赖注入的存储库模式的想法 - 这已被证明非常有效。事实上,我目前使用的应用程序每月处理超过 110 亿个 Web 请求,使用这种模式针对 7 个不同的 MySQL 数据库实例。
另一个建议,在 UI 下实现一个服务/业务层。这一层的职责之一是为业务处理和数据库事务提供 API。我通常在业务层实现存储库,但它为实际的数据库特定事务引用并使用数据访问层组件。通过这种方式,您可以在业务层中抽象出数据访问——这是一件好事,因为长期存在的应用程序会在数据访问中发生许多变化。有了这个很好的抽象,您可以使用实体框架或任何其他数据库技术,如 NoSQL。此外,使用 DI,接口/抽象类允许您将“存储库”的实例注入业务组件 - 这肯定会提高应用程序的可测试性:
希望这可以帮助。