更好的方法是:为DbContext创建自己的包装器或在Controller中使用DbContext

时间:2016-01-06 09:00:39

标签: c# asp.net-core asp.net-core-mvc entity-framework-core

在我的项目中,我使用实体框架7 asp.net mvc 6 \ asp.net 5 。我想为自己的模型创建CRUD

我怎样才能做得更好:

  1. 使用控制器中的dbcontext。 在下面的link作者解释说这种方式更好,但它是否适合控制器?
  2. 制作自己的包装纸。 一些Best practices写了关于什么是最好的自己的存储库。
  3. 我不打算在其他方面改变ef,所以不要介意,即使有一个强大的连接来访问特定实现的数据 我知道在ef7中dbcontext立即实现了工作单元和存储库模式。

4 个答案:

答案 0 :(得分:4)

您的问题的答案主要是基于意见的。没有人可以明确地说'#34;一种方式比另一种方式更好"直到很多其他问题得到解答。您项目的规模/范围/预算是多少?有多少开发人员会参与其中?它只有(基于视图的)MVC控制器,还是它有(基于数据的)API控制器?如果是后者,MVC和API动作方法之间会有多少重叠,如果有的话?是否有任何非网络客户端,如WPF?您打算如何测试应用程序?

实体框架是一种数据访问层(DAL)工具。控制器是HTTP客户端请求&响应处理工具。除非您的应用程序是纯CRUD(这是值得怀疑的),否则在您通过HTTP接收Web请求和将请求的数据保存到a之间时,您可能需要进行某种业务逻辑处理。使用EF的数据库(需要字段X,如果为字段Y提供数据,则还必须为字段Z提供数据等)。因此,如果您直接在控制器中使用EF代码,这意味着您的业务处理逻辑几乎肯定会与控制器一起出现在控制器中。

我们这些在使用.NET开发非平凡应用程序方面具有相当丰富经验的人倾向于发展出这样的观点,即控制器中既不存在业务也不存在数据访问逻辑,因为在实现这样的设计时会出现某些困难。例如,当你把web / http请求&响应逻辑,以及业务逻辑和数据访问逻辑到控制器,您最终必须从控制器操作本身测试所有这些应用程序方面(如果您关心SOLID设计,这是明显违反单一责任原则) 。另外,让我们假设您使用返回视图的控制器开发传统的MVC应用程序,然后决定将应用程序扩展到其他客户端,如iOS / android / WPF /或其他一些不了解您的MVC的客户端观点。如果您决定实施一组基于WebAPI数据的辅助控制器操作,那么您将至少在两个位置复制业务和数据访问逻辑。

但是,这并没有决定保持所有业务和控制器中的数据访问逻辑本质上更糟糕"而不是替代设计。在设计Web应用程序的体系结构时,您做出的任何决定都将具有优势和劣势。无论您选择哪条路线,总会有权衡。将所有应用程序代码保存在控制器中的优点包括降低成本,降低复杂性,从而缩短产品上市时间。对于非常简单的应用程序来说,过度设计复杂的体系结构是没有意义的。不幸的是,我个人从未有过开发一个简单的应用程序的乐趣,所以我在"一般意见"在控制器中保存业务和数据访问代码的船可能不会#34;一个很好的长期设计决定。

如果您真的对替代品感兴趣,我建议您reading these two articles。它们是关于如何实施命令的良好入门读物。控制器可以使用的查询(CQRS)模式。 EF确实实现了开箱即用的存储库和工作单元模式,但这并不一定意味着您需要" wrap"它是为了将数据访问代码移到控制器之外。祝你的项目做出这些决定。

public async Task<ActionResult> Index() {
    var user = await query.Execute(new UserById(1));
    return View(user);
}

答案 1 :(得分:3)

通常我更喜欢使用Repository模式和UnitOfWork模式(http://www.asp.net/mvc/overview/older-versions/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application) - 我在UnitOfWork实例对象中实例化DbContext,然后在存储库中注入DbContext。之后我在控制器中实例化UnitOfWork,控制器对DbContext一无所知:

public ActionResult Index()
{
    var user = unitOfWork.UsersRepository.GetById(1); // unitOfWork is dependency injected using Unity or Ninject or some other framework
    return View(user);
}

答案 2 :(得分:2)

这取决于应用程序的生命周期。

如果多年>将使用,扩展和更改,那么我会说创建包装是一个不错的选择。

如果它是小应用程序,并且如您所说,您不打算将 EntityFramework 更改为另一个 ORM ,那么让自己免于创建包装器的工作,并在控制器中直接使用

答案 3 :(得分:1)

对此没有明确的答案。这一切都取决于你想要做什么。 如果你想要代码可维护性,我建议使用包装器。