SOLID 原则、存储库模式和 EntityFramework 在 Asp Net Mvc 中的缓存

SOLID principles, Repository pattern and EntityFramework cache in Asp Net Mvc

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

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

嗯,就你在这里陈述的问题而言,你的项目结构没有任何问题。问题源于使用 Singleton 作用域。您应该为 Web 应用程序使用 Request 范围。这样可以确保您获得每个请求的新上下文,因此不同请求甚至不同客户端之间不会出现重叠,这是非常危险的。

也就是说,您的项目结构是 over-engineered。 repository/unit 工作模式用于 low-level 数据访问。像 Entity Framework 这样的 ORM 可以处理所有这些,事实上,Entity Framework 已经实现了这些模式。 DbContext 是工作单元,每个 DbSet 是一个存储库。在此之上添加您自己的 repository/unit 工作层是多余且不必要的。您的服务应直接利用您的 Entity Framework 上下文。即便如此,拥有多个服务也可能是不必要的,这取决于它们的作用。如果它们都使用相同的数据源(即 Entity Framework 上下文),特别是如果它们都使用 same Entity Framework 上下文,那么它们真的应该都是合二为一。

在我自己的个人项目中,我使用单个 "service" class 和每个唯一上下文实例的通用方法。通用方法让我可以使用属于该上下文的任何实体,而无需新建 "service" class 的其他实例。通过确保一切都实现一个或多个接口并使用依赖注入来满足接口约束,底层数据层被完全分解出来。如果您有兴趣,我有一个 series of posts 可以更详细地介绍。

我之所以这么说,是因为您似乎过分关注模式和 "best practices"。这些只是 指南 。它们就像自行车上的训练轮。它们都基于良好代码设计的各种原则。学习并应用原则,不要担心选中某种设计模式列表中的所有复选框。

有趣的是,Stack Overflow 的核心代码库实际上避开了一些模式(甚至是依赖注入),因为它们 laser-focused 是关于原始性能的,而一些设计模式在应用时实际上会阻碍性能。关键是应用程序的设计方式应基于特定应用程序的需求。设计模式应仅在符合您的应用程序需求的情况下应用,而不仅仅是因为您认为您应该这样做。

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

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

也许你应该考虑放弃存储库模式?你的项目有多大?将来是否有可能更改数据存储?如果没有,你可以在你的服务中直接对 DbContext 进行操作。 Entity Framework 是存储库模式和 UnitOfWork 的一种实现。