AspNet Mvc中的SOLID原理,Repository模式和EntityFramework缓存 [英] SOLID principles, Repository pattern and EntityFramework cache in Asp Net Mvc

查看:183
本文介绍了AspNet Mvc中的SOLID原理,Repository模式和EntityFramework缓存的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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




  • 在一个服务中,当我必须访问两个表进行加入时,我应该使用两个存储库,调用它们的GetAll()方法。在这种情况下,两个存储库应该共享相同的EntityFramework上下文。

  • 以前的情况表明,DbContext应该由所有存储库共享,因此我可以在不同的存储库中的服务中加入IQueryable。

  • 为了实现我在IoC容器中配置的目标,DbContext在单例范围内。所以每个存储库共享相同的DbContext。

  • 这个解决方案的问题是DbContext有一个缓存。所以当外部进程(与Web项目不同)改变了我的数据时,DbContext没有意识到这一点,而且Web项目有时不会显示真实数据。

  • 我读到关于摧毁DbContext在每个存储库调用,但我不能这样做,因为每个存储库应该使用相同的DbContext



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

解决方案

在这里,您的项目结构没有任何错误。该问题源自使用Singleton范围。您应该使用请求范围,而不是Web应用程序。这样可以确保每个请求都能获得一个新的上下文,所以不同的请求甚至不同的客户端都不会有重叠,这可能是非常危险的。



您的项目结构过度设计。存储库/工作单元用于低级数据访问。一个ORM,像实体框架,处理所有这些,实际上,实体框架已经实现了这些模式。 DbContext 是工作单元,每个 DbSet 是一个存储库。添加自己的存储库/工作单元之上是冗余和不必要的。您的服务应直接使用您的实体框架上下文。即使如此,具有多个服务也可能是不必要的,这取决于他们做什么。如果他们都使用相同的数据源(即实体框架上下文),特别是如果他们都使用相同的实体框架上下文,那么它们应该真的被卷入一个。



在我自己的个人项目中,我使用一个单一的服务类,每个唯一的上下文实例都有通用的方法。通用方法让我可以使用属于该上下文的任何实体,而无需新增service类的其他实例。通过确保一切实现一个或多个接口并使用依赖注入来满足接口约束,底层数据层被完全考虑在内。我有一个一系列的帖子,如果你有兴趣,会有更详细的说明。 p>

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



有趣的是, Stack Overflow的核心代码库实际上避开了许多模式(甚至是依赖注入),因为它们是针对原始性能的激光焦点,而某些设计模式在应用时实际上阻碍了性能。关键是应用程序的设计应该根据具体应用程序的需要而定。设计模式只能适用于与应用程序需求一致的功能,而不仅仅是因为您认为自己应用。


I have a visual studio solution using solid pattern. I have a IRepository (Crud implementation), IDbFactory (used by a repository), IUnitOfWork. I also have services, who uses repositories to build custom querys and complex database operation. I am using also IoC pattern with Ninject. In a web mvc controller I use only services to access to database. A repository receive a IDbFactory who build a EntityFramework Context. I have some problems:

  • In a service when i have to access to two tables for join them i should use two repositories, calling the GetAll() method of both of them. In this case both repositories should share the same EntityFramework Context.
  • The previous case indicates me that the DbContext should be shared by All repositories, so I can join IQueryables in a service from different repositories.
  • To a accomplish this goal I configured in the IoC container, the DbContext in singleton scope. So every repository shares the same DbContext.
  • The problem with this solution is that the DbContext have a cache. So, when a external process (different to the web project) changes my data the DbContext do not realize it, and the Web project do not shows real data sometimes.
  • I read about destroy the DbContext in every repository call, but i cant do this because every repository should use the same DbContext

I there something wrong with my Project structure? This is something i must fix in the repository layer? What shoul I do? The project is in developing stage, so I can change the data access architecture. I like use IQueryables in the controller so users filters in data grids produce sql querys.

解决方案

Well, in terms of your stated issue here, there's nothing wrong with your project structure. The problem derives from using a Singleton scope. You should be using Request scope, instead, for a web application. This ensures that you get a new context with each request, so there will not be overlap between different requests and even different clients, which can be extremely dangerous.

That said, your project structure is over-engineered. The repository/unit of work patterns are intended for low-level data access. An ORM, like Entity Framework, handles all that, and in fact, Entity Framework already implements these patterns. The DbContext is the unit of work and each DbSet is a repository. Adding your own repository/unit of work layer on top of this is redundant and unnecessary. Your services should utilize your Entity Framework context directly. Even then, having a plurality of services is probably unnecessary as well, depending on what they do. If they all work with the same data source (i.e. an Entity Framework context) and particularly if they all work with the same Entity Framework context, then they should really all be rolled into one.

In my own personal projects, I utilize a single "service" class with generic methods per unique context instance. The generic methods let me work with any entity belonging to that context without having to new up additional instances of the "service" class. By ensuring that everything implements one or more interfaces and using dependency injection to satisfy interface constraints, the underlying data layer is completely factored out. I have a series of posts that goes into greater detail if you're interested.

I say all this because it seems you're overly focused on patterns and "best practices". Those are just guides. They're like training wheels on a bicycle. They're all based on various principles of good code design. Learn and apply the principles and don't worry about checking all the boxes on some sort of list of design patterns.

As an interesting aside, Stack Overflow's core codebase actually eschews a number of patterns (even dependency injection) because they're laser-focused on raw performance, and some design patterns, when applied, actually hinder performance. The point is that how an application is designed should be based on the needs of the particular application. Design patterns should only be applied in as much as they are congruent with the needs of your application, not just because you think you're supposed to.

这篇关于AspNet Mvc中的SOLID原理,Repository模式和EntityFramework缓存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆