用户作为 ASP Net Core 中的范围服务 - 不好的做法?
Posted
技术标签:
【中文标题】用户作为 ASP Net Core 中的范围服务 - 不好的做法?【英文标题】:User as scoped service in ASP Net Core - a bad practice? 【发布时间】:2021-03-19 07:43:46 【问题描述】:在我的 ASP Net Core 应用程序中,我需要经常访问和编辑存储在数据库中的用户相关数据。一般来说,我的方法如下:
将Microsoft.AspNetCore.Components.Authorization.AuthenticationStateProvider
注入可以操作数据的作用域服务中(让我们调用该服务UserEditService
)
从提供的AuthenticationState
和AuthenticationState.User.Identity.Name
获取当前用户的用户名
注入Microsoft.AspNetCore.Identity.UserManager<AppUser>
并使用它按名称从数据库中加载用户。
将AppUser
实例的引用保存在UserEditService
中
操作并保存所述实例
问题是我几乎在我的一些服务中复制并粘贴了相同的代码,我想知道将AppUser
对象作为范围服务加载到应用程序中是否不是一个更好的主意,然后将其注入所有需要用户访问的服务中。我还没有找到人们这样做的项目,这让我觉得这可能是一种不好的做法。
是这样吗?如果是这样,为什么?有没有更好的方法来管理 ASPNetCore 中的用户相关数据?
【问题讨论】:
ASP.NET Core 已经将用户数据作为范围服务进行管理。AuthenticationState.User.Identity.Name
仅在单个请求的范围内有意义。 DbContext 实例默认是作用域的
I haven't found projects where people do that
相反,所有使用 ASP.NET Core Identity 的项目都使用范围服务,因为 Identity 仅适用于请求的范围。所有 good 教程都展示了使用 AddDbContext
用作作用域服务的 DbContext 实例,它为您提供了“每请求事务”语义:如果您不想持久化更改,请不要调用SaveChanges
.
我想我不清楚。我问的是使用 AppUser
对象本身作为范围服务,而不是 DbContext。
如果AppUser
是一个数据对象,最好将它的检索隐藏在抽象后面(例如IAppUserProvider
),而不是将该对象注入应用程序组件的构造函数中。 This article 更详细地描述了为什么会这样以及替代方案是什么。
另外,如果有人可以给我点个赞,那就太棒了。多年来我一直在使用 Stack Overflow,但我很少发布任何内容,甚至无法在一个好的答案上点个赞,这很烦人。
【参考方案1】:
由于AppUser
包含运行时数据,尽管当然可以将其注入其消费者的构造函数中,但在对象构造期间注入运行时数据是一些令人不安的缺点。它
会导致歧义,使 Composition Root 复杂化并承担额外的责任,并使得验证 DI 配置的正确性变得异常困难。相反,让运行时数据流过构造对象图的方法调用。
而是更喜欢注入允许在运行时检索 AppUser
的抽象,例如使用如下抽象:
interface IAppUserProvider
AppUser Current get;
有关缺点的更详细讨论,请查看我的this article。 (引自那篇文章)
也就是说,尽管这种方法有缺点,但这本身并不意味着它是一种不好的做法或反模式。这是因为有多种方法可以查看运行时数据的使用情况。可以使用两种相互竞争的组合模型;一种是首选将运行时数据捕获到组件中,另一种是首选将运行时数据存储在对象图外部。你可以阅读更多关于这些竞争模型here。
【讨论】:
以上是关于用户作为 ASP Net Core 中的范围服务 - 不好的做法?的主要内容,如果未能解决你的问题,请参考以下文章
Ninject 中的 .NET Core DI 范围生命周期
如何把asp.net core的文件作为服务在windows下面部署
ASP.NET Core Web 应用程序作为 Azure 服务总线使用者/接收器