【问题标题】:Dependency injected UserManager causes concurrency issue: How to make UserManager use different DbContext?依赖注入的 UserManager 导致并发问题:How to make UserManager use different DbContext?
【发布时间】:2023-01-18 12:30:52
【问题描述】:

在带有 EF Core 和 MS Identity 的 Blazor 服务器端应用程序中,我遇到了一个在上一个操作完成之前,在此上下文实例上启动了第二个操作错误。我可以将其追溯到 MS Identity UserManager,他似乎对所有 Blazor 组件使用相同的DbContext

我的父组件和一些子组件使用UserManager。因为 - 根据我的理解 - 每个组件都在一个单独的线程中运行,每个组件应该使用不同的 DbContext 来防止此类并发问题。

我使用依赖注入获取每个组件中的UserManager,不幸的是,我不知道要检查UserManager使用了哪个DbContext,但是每个组件实例中的UserManager的哈希码是相同的,强烈表明多个 Blazor 组件共享同一个 DbContext,这会导致并发问题。

作为解决方法和测试我的结论是否正确,我使用 SemaphoreSlim 在不同的 Blazor 组件中同步 UserManager 的使用,并发问题消失了。所以我确信注入的UserManagers 共享一个DbContext

我根据 this SO post 使用工厂为 MS Identity 注册了 DbContext 的“新”实例

services.AddTransient<myContext>(p => p.GetRequiredService<IDbContextFactory<myContext>>().CreateDbContext());

在这里,我预料到了问题:MS Identity 仅获取、分别使用 DbContext 而不是 DbContextFactory,因此在注入 UserManager 时它必须使用相同的 DbContext

有没有办法让UserManager每次注入时都使用“新鲜”DbContext

【问题讨论】:

  • 我提交了这个issue,但它在没有解决方案的情况下被关闭了。

标签: asp.net asp.net-identity


【解决方案1】:

我发现了一些可能有帮助的东西。我在尝试注入 usermanager 以获取用户表的用户角色时遇到了这个问题。我找到了this 帖子。我使用继承组件基础,然后使用 Service.GetUserRolesAsync(user)

我能够遍历用户管理器并获取所有角色而不会导致并发异常。

这是帖子内容的副本。

@page "/"
@inherits OwningComponentBase<UserManager<IdentityUser>>
<h1>Hello, world!</h1>

number of users: @Users.Count()
<button @onclick="@(async () => await Add())">click me. I work if you use Sqlite</button>

<ul>
@foreach(var user in Users) 
{
    <li>@user.UserName</li>
}
</ul>

@code {
    IQueryable<IdentityUser> Users;

    protected override void OnInitialized()
    {
        Users = Service.Users;
    }

    public async Task Add()
    {
        await Service.CreateAsync(new IdentityUser { UserName = $"test_{Guid.NewGuid().ToString()}" });
    }
}

【讨论】:

    猜你喜欢
    • 2015-06-17
    • 2017-08-02
    • 2018-10-01
    • 2016-09-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多