Asp Net Mvc中的SOLID原则,Repository模式和EntityFramework缓存

时间:2017-01-20 17:42:23

标签: .net asp.net-mvc entity-framework repository-pattern solid-principles

我有一个使用实体图案的visual studio解决方案。我有一个IRepository(Crud实现),IDbFactory(由存储库使用),IUnitOfWork。我也有服务,他们使用存储库来构建自定义查询和复杂的数据库操作。我正在使用Ninject的IoC模式。 在web mvc控制器中,我只使用服务来访问数据库。 存储库接收构建EntityFramework Context的IDbFactory。 我有一些问题:

  • 在服务中,当我必须访问两个表来加入它们时,我应该使用两个存储库,调用它们的GetAll()方法。在这种情况下,两个存储库应共享相同的EntityFramework Context。
  • 前一个案例表明DbContext应该由All repositories共享,所以我可以在不同存储库的服务中加入IQueryables。
  • 为了实现这个目标,我在IoC容器中配置了单独范围内的DbContext。因此,每个存储库共享相同的DbContext。
  • 此解决方案的问题是DbContext具有缓存。因此,当外部进程(与Web项目不同)更改我的数据时,DbContext没有意识到它,并且Web项目有时不会显示真实数据。
  • 我读到了在每个存储库调用中销毁DbContext,但我不能这样做因为每个存储库都应该使用相同的DbContext

我的项目结构有问题吗?这是我必须在存储库层中修复的东西?我该怎么办?该项目正处于开发阶段,因此我可以更改数据访问架构。我喜欢在控制器中使用IQueryables,因此数据网格中的用户过滤器会生成sql查询。

2 个答案:

答案 0 :(得分:4)

那么,就你所说的问题而言,你的项目结构没有任何问题。问题源于使用Singleton范围。相反,您应该将Web范围用于Web应用程序。这可确保您获得每个请求的新上下文,因此不同请求之间甚至不同客户端之间不会重叠,这可能非常危险。

也就是说,您的项目结构过度设计。存储库/工作模式单元用于低级数据访问。 ORM与Entity Framework一样,处理所有这些,实际上,Entity Framework已经实现了这些模式。 DbContext是工作单元,每个DbSet都是一个存储库。在此基础上添加您自己的存储库/工作单元层是多余且不必要的。您的服务应直接使用您的Entity Framework上下文。即使这样,也可能不需要拥有多项服务,这取决于他们的工作。如果它们都使用相同的数据源(即实体框架上下文),特别是如果它们都与相同的实体框架上下文一起使用,那么它们应该全部归为一个。

在我自己的个人项目中,我使用单个“服务”类,每个唯一的上下文实例使用泛型方法。通用方法允许我使用属于该上下文的任何实体,而无需新建“服务”类的其他实例。通过确保一切实现一个或多个接口并使用依赖注入来满足接口约束,底层数据层完全被排除在外。我有一个series of posts如果你有兴趣可以更详细。

我说这一切都是因为你似乎过分关注模式和“最佳实践”。这些只是指南。他们就像在自行车上训练轮子。它们都基于良好代码设计的各种原则。学习并应用原则,不要担心检查某种设计模式列表中的所有框。

有趣的是,Stack Overflow的核心代码库实际上避开了许多模式(甚至是依赖注入),因为它们专注于原始性能,而某些设计模式在应用时实际上会阻碍性能。关键是应用程序的设计方式应该基于特定应用程序的需求。设计模式应该只应用于与应用程序需求一致的程度,而不仅仅是因为您认为自己应该这样做。

答案 1 :(得分:0)

首先,DbContext的生命周期应该持续整个业务部门,在MVC应用程序中,这是每个HttpRequest。它从发送请求开始提供事务,以便用户接收响应。

其次,您不应该在基础存储库中拥有GetAll()函数。这是非常错误的解决方案,它可能会影响应用程序的性能。您应该创建如下函数:GetByQuery(Func<T, bool> whereQuery, int skip, int take)其中T是实体类的泛型类型。或者,您可以添加用于排序的参数。

也许您应该考虑存储库模式的辞职?你的项目有多大?是否有可能在未来改变数据存储?如果没有,您可以直接在服务中的DbContext上操作。实体框架是存储库模式和UnitOfWork的一种实现。

相关问题