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

Blazor WebAssembly中FluentValidation注入DbContext的依赖解析异常问题

解决方案:Blazor WASM中Blazored.FluentValidation依赖DbContext的验证器注入问题

问题根源

Blazored.FluentValidation默认使用无参构造创建验证器实例,而你的自定义验证器依赖GymDbContext,DI容器无法自动将服务注入到验证器中,导致抛出"Unable to resolve service for type 'DbContext'"异常。

具体解决步骤

1. 自定义验证器工厂

实现IValidatorFactory接口,让验证器能从DI容器中获取实例:

using FluentValidation;
using Microsoft.Extensions.DependencyInjection;

public class ServiceProviderValidatorFactory : IValidatorFactory
{
    private readonly IServiceProvider _serviceProvider;

    public ServiceProviderValidatorFactory(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    public IValidator<T> GetValidator<T>()
    {
        return _serviceProvider.GetService<IValidator<T>>();
    }

    public IValidator GetValidator(Type type)
    {
        var validatorType = typeof(IValidator<>).MakeGenericType(type);
        return (IValidator)_serviceProvider.GetService(validatorType);
    }
}

2. 注册DI服务

在Program.cs中完成DbContext、验证器和自定义工厂的注册:

// 注册DbContext工厂(Blazor WASM推荐用工厂模式管理DbContext生命周期)
builder.Services.AddDbContextFactory<GymDbContext>(options =>
    options.UseSqlite("Data Source=gym.db")); // 替换为你的数据库配置

// 注册自定义验证器
builder.Services.AddScoped<IValidator<YourModel>, YourModelValidator>();

// 注册自定义验证器工厂
builder.Services.AddScoped<IValidatorFactory, ServiceProviderValidatorFactory>();

// 配置Blazored.FluentValidation使用自定义工厂
builder.Services.AddBlazoredFluentValidation(config =>
{
    config.ValidatorFactoryType = typeof(ServiceProviderValidatorFactory);
});

3. 编写带DbContext依赖的验证器

通过构造函数注入IDbContextFactory<GymDbContext>(避免长期持有DbContext实例),实现唯一性校验:

using FluentValidation;
using Microsoft.EntityFrameworkCore;

public class YourModelValidator : AbstractValidator<YourModel>
{
    private readonly IDbContextFactory<GymDbContext> _dbContextFactory;

    public YourModelValidator(IDbContextFactory<GymDbContext> dbContextFactory)
    {
        _dbContextFactory = dbContextFactory;

        // 邮箱唯一性校验
        RuleFor(x => x.Email)
            .NotEmpty()
            .EmailAddress()
            .MustAsync(async (email, cancellation) => 
            {
                using var dbContext = _dbContextFactory.CreateDbContext();
                return !await dbContext.Users.AnyAsync(u => u.Email == email, cancellation);
            })
            .WithMessage("邮箱已存在");

        // 手机号唯一性校验
        RuleFor(x => x.PhoneNumber)
            .NotEmpty()
            .MustAsync(async (phone, cancellation) => 
            {
                using var dbContext = _dbContextFactory.CreateDbContext();
                return !await dbContext.Users.AnyAsync(u => u.PhoneNumber == phone, cancellation);
            })
            .WithMessage("手机号已存在");

        // PESEL唯一性校验
        RuleFor(x => x.PESEL)
            .NotEmpty()
            .MustAsync(async (pesel, cancellation) => 
            {
                using var dbContext = _dbContextFactory.CreateDbContext();
                return !await dbContext.Users.AnyAsync(u => u.PESEL == pesel, cancellation);
            })
            .WithMessage("PESEL已存在");
    }
}

关键注意点

  • Blazor WASM中不要直接注入DbContext实例,必须用IDbContextFactory创建短期实例,避免内存泄漏和上下文状态问题。
  • 确保验证器和DbContext工厂都注册为Scoped生命周期,和Blazor组件的生命周期匹配。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 02:55:17