You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Blazor与EF Core:DbContext多线程并发及组件重复加载问题

Blazor组件导航时加载两次,OnInitializedAsync执行两次及相关数据库错误的解决过程

问题现象

  • 导航至/MySettings组件时,组件重复加载两次,OnInitializedAsync()方法随之执行两次
  • 将_Host.cshtml的渲染模式修改为Server(<component type="typeof(App)" render-mode="Server" />)后,触发数据库连接错误:

Error: System.InvalidOperationException: There is already an open DataReader associated with this Connection which must be closed first.
at Microsoft.Data.SqlClient.SqlCommand.<>c.b__208_0(Task1 result) at System.Threading.Tasks.ContinuationResultTaskFromResultTask2.InnerInvoke()
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)

相关代码

组件代码(MySettings.razor)

@page "/MySettings"
@using eKurser_Blazor.Data.Services;
@using eKurser_Blazor.DataDB;
@inject UserService UserService
@inject AuthenticationStateProvider AuthenticationStateProvider

<h1>Get profile</h1>

@if (ErrorMessage != null)
{
    <div class="alert alert-danger">@ErrorMessage</div>
}

<form>
    <div class="form-group">
        <label for="firstName">Fname</label>
        <input type="text" class="form-control" id="firstName" @bind="@Fname" @value="@Fname">
    </div>
    <div class="form-group">
        <label for="lastName">Lname</label>
        <input type="text" class="form-control" id="lastName" @bind="@Lname" @value="@Lname">
    </div>
    <div class="form-group">
        <label for="email">E-mail</label>
        <input type="email" class="form-control" id="email" @bind="@Email" @value="@Email">
    </div>

</form>

重复执行的OnInitializedAsync代码

protected override async Task OnInitializedAsync()
{
    var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
    var user = authState.User;
    string userIdClaim = user.FindFirst("UserID")?.Value;

    if (!string.IsNullOrEmpty(userIdClaim))
    {
        var _user = await UserService.GetUserByIdAsync(userIdClaim);
        if (_user != null)
        {

        }
    }
}

UserService.cs代码

public class UserService
{
    private readonly MyDbContext _dbContext;

    public UserService(MyDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    public async Task<TblUser> AuthenticateAsync(string email, string password)
    {
        if (string.IsNullOrEmpty(email) || string.IsNullOrEmpty(password))
        {
            return null;
        }

        TblUser user = null;

        try
        {
            user = await _dbContext.TblUsers.SingleOrDefaultAsync(x => x.Email == email);
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error: {ex.Message}");
            return null;
        }

        if (user == null)
        {
        }

        if (user == null || !PasswordHash.ValidatePassword(password, user.Pwd))
        {
            return null;
        }

        return user;
    }
    public async Task<TblUser> GetUserByIdAsync(string userId)
    {
        if (string.IsNullOrEmpty(userId))
        {
            return null;
        }

        var user = await _dbContext.TblUsers.SingleOrDefaultAsync(x => x.UserId == userId);
        return user;
    }      

    private bool UserExists(string userId)
    {
        return _dbContext.TblUsers.Any(e => e.UserId == userId);
    }
}

Program.cs配置代码

builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddScoped<UserService>();

builder.Services.AddScoped<CustomAuthenticationStateProvider>();
builder.Services.AddScoped<AuthenticationStateProvider>(provider => provider.GetRequiredService<CustomAuthenticationStateProvider>());

var connString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContextFactory<MyDbContext>((DbContextOptionsBuilder option
    ) => option.UseSqlServer(connString));

// Add services to the container.
builder.Services.AddControllersWithViews();

解决步骤与最终结果

  • 更新1:改用IDbContextFactory解决了数据库连接错误,但组件重复加载、导航后认证状态为空的问题仍存在
  • 更新2:通过Blazored.LocalStorage修复认证状态存储,但组件重复加载问题未解决
  • 更新3:修复认证状态逻辑并重启Visual Studio后,所有问题均得到解决

内容的提问来源于stack exchange,提问作者Jonas Johansson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 12:28:35