用户作为 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) 从提供的AuthenticationStateAuthenticationState.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 允许 CORS 中的 IP 范围

如何把asp.net core的文件作为服务在windows下面部署

ASP.NET Core Web 应用程序作为 Azure 服务总线使用者/接收器

ASP.NET Core Razor 页面中的变量范围和 HTML 标记

将数组作为命令行参数传递给 Asp.Net Core