“scoped lifetime for a service” 在 Blazor (server) 中是什么意思?

huangapple go评论62阅读模式
英文:

What does scoped lifetime for a service mean in Blazor (server)?

问题

这是关于Blazor(服务器端)的内容。

根据这份文档,在Blazor(服务器端)中,服务的会话范围意味着:

当在客户端之间导航时,作用域服务不会重新构建,其中与服务器的通信是通过用户电路的SignalR连接进行的,而不是通过HTTP请求进行的。

这篇博客文章中(似乎很有知识):

它为每个所谓的“电路”创建一个范围。当新的浏览器选项卡通过底层SignalR传输连接到Blazor服务器时,会创建一个电路,并在浏览器选项卡再次关闭(或者如果连接丢失并在指定时间范围内无法重新连接)时终止。

但在这个Microsoft Q&A中,它说:

如果这是有关Blazor服务器的问题,那么作用域的行为就像单例。官方文档涵盖了服务生命周期的工作原理。

我认为单例是跨所有电路/会话的相同对象。文档如下:

DI创建服务的单个实例。需要单例服务的所有组件都会收到该服务的相同实例。

当然,“所有组件”可以意味着单个电路/会话中的所有组件。或者它可以意味着所有电路/会话中的所有组件。我可以理解,如果“所有组件”是每个电路/会话的话,那么对于大多数(或所有)用例来说,作用域就与单例相同。但如果单例是跨所有电路/会话的单个实例,那么它们是不同的 - 很不同。

那么在Blazor服务器上,作用域和单例服务到底是怎么回事?


总结

关于这个问题的讨论变得情感化(我不喜欢看到这种情况),在下面的两个答案中有很多有价值的讨论。所以我不想对他们表示不尊重,但我要在这里总结答案。

单例将在每次调用时返回相同的实例。在这里有一个很好的用例,获取地点(比如科罗拉多州博尔德)的销售税率。这个信息对每个用户都是相同的。

作用域将为每个SignalR电路(在Blazor服务器中通常称为作用域)返回不同的实例。在电路的生命周期内,它将继续向该电路/会话返回相同的实例。在这里有一个很好的例子,这是一个购物车。

可能会导致一些混淆的是,无论是单例服务还是作用域服务,它们都会在电路的生命周期内返回相同的实例。从这个角度来看,它们是相同的。

但如果有两个电路连接到您的服务器,那么单例将向两者都返回相同的实例,而作用域服务将向每个电路/会话返回不同的实例。从这个角度来看,它们非常不同。

英文:

This is for Blazor (server).

According to this documentation, session scope for a service in Blazor (server side) means:

> Scoped services aren't reconstructed when navigating among components
> on the client, where the communication to the server takes place over
> the SignalR connection of the user's circuit, not via HTTP requests.

And in this blog article (seems to be knowledgable):

> It creates a scope for each so-called “circuit”. A circuit is created
> when a new browser tab connects to the Blazor server via the
> underlying SignalR transport, and it is terminated when the browser
> tab is closed again (or if the connection is lost and fails to
> reconnect within a specified time frame).

But in this Microsoft Q&A it says:

> If this is a Blazor Server question then scoped behaves like a
> singleton. The official documentation covers how service life time
> works..

I think a singleton is the same object across all circuits/sessions. The documentation is as follows.

> DI creates a single instance of the service. All components requiring
> a Singleton service receive the same instance of the service.

Of course "all components" can mean all components in a single circuit/session. Or it can mean all components across all circuits/sessions. I can see how if the "all components" is per circuit/session, then scoped is the same as singleton for most (all) use cases. But if singleton is a single instance across ever circuit/session, then they differ - a lot.

So what exactly is going on for scoped & singleton services on Blazor server?


Summary

The discussion on this got emotional (which I hate to see) and there is a lot of valuable discussion of this question in the two answers below. So no disrespect to them but I am going to summarize the answer here.

A singleton will return the same instance on every call. Good example of a use here, getting the sales tax rate for a location (like Boulder, Colorado). That information is the same for every user.

A scoped will return a different instance for each SignalR circuit (often referred to as scope in Blazor server). For the life of a circuit it will keep returning the same instance to that circuit/session. Good example here is a shopping cart.

What can lead to some confusion - both a singleton and scoped service will return the same instance for the life of the circuit. In that way they are identical.

But if there are two circuits to your server, the singleton will return the same instance to both while the scoped service will return a different instance to each. In this way they are very different.

答案1

得分: 3

将3个文档引用放在一起,您应该阅读:

  • 任何会话通过SignalR连接到Blazor服务器
  • 当会话启动时,将为该会话创建一个新范围

从现在开始,我们可以将会话和范围视为相同,因为每个会话都有自己的范围,将在会话结束之前保持不变。

  • 在范围内(在这个上下文中等同于会话),具有范围或单例生命周期的服务之间没有区别,因为我们将从ServiceProvider中再次获取相同的实例。

这就是所谓的“范围”行为像单例,并且您还应考虑第一部分“如果这是Blazor Server问题,那么”。似乎大多数Blazor Server问题都必须在会话的上下文中处理,因为每个会话都有自己的范围,而且永远不会更改...

这与普通的ASP.NET服务器不同,您在每个请求中都会获得一个新的范围。

我猜最常见的问题是DbContext,因为它是一个范围服务,在ASP.NET中,您在每个请求中都有一个干净的新上下文。但是在Blazor Server中,现在可能会出现副作用,因为它不再是新的和干净的,而且可能来自当前会话中较旧的使用而变得不干净。

英文:

Putting all 3 doc cites together, you should read:

  • Any session connects to a Blazor server via SignalR
  • When the session starts a new scope for that session is created

From now on we can treat session and scope as the same, because each session has its own scope that will survive until the session ends.

  • Within a scope (which in this context is equal to session) there is no difference between services with a scoped or singleton lifetime, as we will get for both the same instance from the ServiceProvider again and again.

That what is meant be scoped behaves like a singleton, and you should also consider the first part If this is a Blazor Server question then. Seems most Blazor Server questions has to be treated in the context of a session, and because each session has its own scoped, which never changes ...

That is different to normal ASP.NET Server, where you get a new scope for each request.

I guess the most problems came up with DbContext as that is as scoped service and in ASP.NET you have a clean fresh context on every request. But with Blazor Server you can now have side effects because it is not fresh and clean anymore and maybe dirty from an older use within the current session.

答案2

得分: 2

以下是翻译好的部分:

"Scoped"服务的持久性取决于用户保持其连接的时间,即它们与连接相关联。它们是与该连接唯一关联的(基本上是浏览器标签在打开状态时)。

"Singleton"服务永久存在,并被所有人共享。这使您可以向所有连接的用户发送消息,或允许多个用户在一个群组中进行聊天。

对于游戏服务器的典型用法是拥有一个处理游戏房间和游戏实例的"Singleton"服务,以及为每个用户订阅它的"Scoped"服务。

在学习Blazor时可能有点令人困惑,因为当您在开发机器上独自工作时,无论是哪一种服务,您的体验都会完全相同,除非您在多个标签/浏览器上打开您的网站。

英文:

What's going on is that they differ a lot.

Scoped services persist so long as a user keeps their circuit, i.e. they are connected. They are unique to that connection (basically, that browser tab while it is open).

Singleton services persist forever, and are shared by everyone. This allows you, for example, to send a message to all connected users, or to allow chat between multiple users in a group.

A typical usage for a game server would be to have a Singleton service to handle game rooms and game instances, and a Scoped service for each user which subscribes to it.

It's a little confusing when learning Blazor, because when you're alone on a dev machine, your experience of both will be exactly the same unless you open your site on multiple tabs / browsers.

huangapple
  • 本文由 发表于 2023年5月8日 00:37:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/76195106.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定