1

当您使用存储库模式开发 ASP.NET 应用程序时,您的每个方法是否创建一个新的实体容器实例(上下文),每个方法都有一个 using 块,或者您是否为容器创建一个类级别/私有实例由任何存储库方法使用,直到存储库本身被处置?除了我在下面提到的之外,还有哪些优点/缺点?有没有办法结合我没有看到的每一个的好处?您的存储库是否实现了 IDisposable,允许您为存储库实例创建 using 块?

多个容器(与单个容器相比)

好处:

  • 防止连接被自动关闭/处理(将在 using 块的末尾关闭)。
  • 有助于迫使您仅将特定视图/视图模型所需的内容拉入内存,并且往返次数更少(尝试延迟加载的任何内容都会出现连接错误)。

缺点:

  • 控制器/视图中子实体的访问仅限于您使用 Include() 调用的内容
  • 对于显示从许多表(许多不同的存储库方法调用)收集的信息的仪表板索引之类的页面,我们将增加创建和处置许多实体容器的开销。
4

3 回答 3

2

如果您在存储库中实例化您的上下文,那么您应该始终在本地进行,并将其包装在 using 语句中。

如果您使用依赖注入来注入上下文,那么当请求完成时,让您的 DI 容器处理对上下文的调用 dispose。

不要将上下文直接实例化为类成员,因为在垃圾回收发生之前,这不会释放上下文资源。如果你这样做了,那么你将需要实现 IDipsosable 来处理上下文,并确保使用你的存储库的任何东西都正确地处理了你的存储库。

于 2012-04-18T18:03:19.113 回答
0

我个人将我的上下文放在我的存储库中的类级别。我这样做的主要原因是因为存储库模式的一个明显优势是我可以轻松地交换存储库并利用不同的后端。请记住 - 存储库模式的目的是您提供一个接口,将数据提供给某些客户端。如果你曾经切换过你的数据源,或者只是想动态地提供一个新的数据源(通过依赖注入),那么如果你在每个方法级别上这样做,你就会产生一个更加困难的问题。

Microsoft 的 MSDN 站点有很好的资料库模式。希望这有助于澄清一些事情。

于 2012-04-18T17:30:28.137 回答
0

我不同意所有四点:

防止连接被自动关闭/处理(将在 using 块的末尾关闭)。

在我看来,如果您在方法级别、存储库实例级别或请求级别处理上下文并不重要。(当然,您必须在单个请求结束时处理上下文 - 通过将存储库方法包装在using语句中或通过IDisposable在存储库类上实现(如您所建议的那样)并将存储库实例包装在using控制器操作中的语句中或通过在控制器构造函数中实例化存储库并将其处置在Dispose覆盖控制器类 - 或者通过在请求开始时实例化上下文并在请求结束时处理它(一些依赖注入容器将有助于完成这项工作)。)为什么要“自动处理”上下文?在桌面应用程序中,每个窗口/视图都有一个可能会打开数小时的上下文是可能且常见的。

有助于迫使您仅将特定视图/视图模型所需的内容拉入内存,并且往返次数更少(尝试延迟加载的任何内容都会出现连接错误)。

老实说,我会通过完全禁用延迟加载来强制执行此操作。在客户端与服务器断开连接的 Web 应用程序中,我看不到延迟加载的任何好处。在您的控制器操作中,您始终知道需要加载什么,并且可以使用急切或显式加载。为了避免内存开销和提高性能,您始终可以禁用 GET 请求的更改跟踪,因为 EF 无论如何都无法跟踪客户端网页上的更改。

控制器/视图中子实体的访问仅限于您使用 Include() 调用的内容

这是一个优势而不是劣势,因为您没有延迟加载带来的意外惊喜。如果您需要稍后在控制器操作中填充子实体,根据某些条件,您可以通过LoadNavigationProperty具有相同甚至新上下文的其他存储库方法(或其他东西)加载它们。

对于显示从许多表(许多不同的存储库方法调用)收集的信息的仪表板索引之类的页面,我们将增加创建和处置许多实体容器的开销。

创建上下文——我不认为我们在谈论成百上千的实例——是一种廉价的操作。我认为这是一种非常理论上的开销,在实践中没有发挥作用。

我已经使用了您在 Web 应用程序中提到的两种方法以及第三种选择,即为每个请求创建一个上下文,并将这个相同的上下文注入到控制器操作中我需要的每个存储库/服务中。他们三个都为我工作。

当然,如果您使用多个上下文,则必须小心在同一个工作单元中完成所有工作,以避免将实体附加到多个上下文,这将导致众所周知的异常。避免这种情况通常不是问题,但需要多加注意,尤其是在处理 POST 请求时。

我最近对每个请求使用上下文,因为它更容易,而且我只是看不到使用非常狭窄的上下文的好处,而且我认为没有理由在整个请求处理中使用多个工作单元。如果我需要多个上下文 - 无论出于何种原因 - 我总是可以创建专门的方法来使用它们自己的上下文而不是请求的“默认上下文”。

于 2012-04-18T17:46:15.660 回答