ASP.NET Core API服务生命周期

3
我在我的ASP.NET Core(2.1)应用程序中有一个需要是单例的服务,因为我有一些需要在整个应用程序生命周期中保留在内存中的信息。这个服务依赖于一些不需要是单例的库,并且我想将它们定义为瞬态,但是ASP.NET Core不喜欢您将瞬态依赖项注入到单例服务中。我可以有点理解为什么,虽然我还是对这方面的东西比较新。但我的问题是:如何正确处理这种情况?我可以将我的库变成单例来满足ASP.NET Core的要求。或者我可以尝试使用服务提供程序在需要时获取库。但我正在寻找“最佳实践”方法。任何建议将不胜感激。谢谢!

单例模式的定义是始终只实例化一次。您如何想象可以注入瞬态构造函数参数?瞬态服务“每次请求时都会创建”,但对于单例模式,它们只会被请求一次。 - maccettura
1
也许您可以添加一些关于该服务的信息?这样我们就可以建议更合适的方法。 - Camilo Terevinto
ASP.NET Core不喜欢将短暂的依赖项注入到单例服务中。为什么呢?据我所知,ASP.NET Core完全支持这种方法?您是否遇到了任何异常?如果是,请发布异常详细信息。 - Steven
1个回答

4

正如@CamiloTerevinto在评论中所指出的,如果不知道你实际在做什么,很难给出明确的指导。但是我可以告诉你一些通用的事情。

首先,单例有两种形式:一种是非常简单,没有多个副本的必要;另一种是非常复杂,拥有多个副本会带来负担。在这两种极端之间的任何东西都应该是请求范围或瞬态。重要的是,在内存中保留数据并不是使用单例范围的有效理由。您可以从任何生命周期的对象中使用内存缓存(甚至更好:分布式缓存)。需要在对象上具有长期状态几乎总是坏类设计的信号。

其次,具有讽刺意味的是,如果有什么东西应该具有单例范围,那么应该是您的存储库。存储库通常需要数据库连接,并且应该尽可能长时间存在。

然而,不要只是将存储库设置为单例并结束。首先停下来评估一下当前的单例类是否实际上应该在该范围内。然后,根据您的应用程序,将存储库设置为请求范围可能是更好的选择,这意味着您仍然无法直接注入它们。


只是一个小注释:仓库实际上应该依赖于某个 DbContext(它持有数据库连接),这意味着 DbContext 应该是单例的,而仓库本身可以是瞬态的或作用域的(可能是瞬态的,因为它们是无状态的)。 - dee zg
1
不应该在存储库中依赖于 DbContext,因为在这种情况下甚至不应该使用存储库。存储库模式的唯一有效用途是处理低级数据访问,例如直接 SQL 查询。像 Entity Framework 这样的 ORM 就是 您的数据层。 - Chris Pratt
嗯,这很难想象。现实世界的例子:您拥有ddd项目和cosmosdb,您在其中存储数据。您不使用任何ORM。您有存储库(在域中定义为接口)。cosmosdb客户端连接应该是单例的。如果不将dbClient注入存储库实现,您会如何处理? - dee zg
这个应用程序是一个“服务器”应用程序,通过对各种内部机器进行网络调用来获取数据,因此在这种情况下使用dbcontext不是问题。我明白你的意思,可以使用缓存代替。我认为目前将数据保留在内存中是使服务成为单例的唯一原因。我会再看一下并尝试使用缓存代替。谢谢! - Dennis
@deezg 数据库客户端就是您的“连接”。在这种情况下,您只需使用cosmosdb客户端而不是ADO.NET的SqlClient即可。差别不大。那很好。但是,如果您有一个ORM,则该ORM是数据层。将其包装在另一个存储库层中毫无意义,实际上只会增加应用程序的熵。 - Chris Pratt
@ChrisPratt 我完全同意。我说的是非ORM情况。其实我不确定ORM情况是从哪里来的 :) - dee zg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接