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

从IdentityServer4升级到Duende 6.2后崩溃:序列包含多个元素

问题背景与异常信息

我正在将现有项目从.NET Core 2.2 + IdentityServer4 2.4逐步升级到.NET 7 + Duende IdentityServer 6.2.0:先升级到IdentityServer4 3.0、4.0,为PersistedGrantDbContext和ConfigurationDbContext执行对应版本的迁移,再迁移到Duende 6.2并执行最终迁移。调用connect/token端点时出现如下异常:

System.InvalidOperationException: Sequence contains more than one element.
   at Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor.SingleOrDefaultAsync[TSource](IAsyncEnumerable`1 asyncEnumerable, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor.SingleOrDefaultAsync[TSource](IAsyncEnumerable`1 asyncEnumerable, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Identity.UserManager`1.FindByEmailAsync(String email)
   at Microsoft.AspNetCore.Identity.UserValidator`1.ValidateEmail(UserManager`1 manager, TUser user, List`1 errors)
   at Microsoft.AspNetCore.Identity.UserValidator`1.ValidateAsync(UserManager`1 manager, TUser user)
   at Microsoft.AspNetCore.Identity.UserManager`1.ValidateUserAsync(TUser user)
   at Microsoft.AspNetCore.Identity.UserManager`1.UpdateUserAsync(TUser user)
   at Microsoft.AspNetCore.Identity.UserManager`1.CheckPasswordAsync(TUser user, String password)
   at Microsoft.AspNetCore.Identity.SignInManager`1.CheckPasswordSignInAsync(TUser user, String password, Boolean lockoutOnFailure)
   at Duende.IdentityServer.AspNetIdentity.ResourceOwnerPasswordValidator`1.ValidateAsync(ResourceOwnerPasswordValidationContext context) in /_/src/AspNetIdentity/ResourceOwnerPasswordValidator.cs:line 52
   at Duende.IdentityServer.Validation.TokenRequestValidator.ValidateResourceOwnerCredentialRequestAsync(NameValueCollection parameters) in /_/src/IdentityServer/Validation/Default/TokenRequestValidator.cs:line 500
   at Duende.IdentityServer.Validation.TokenRequestValidator.RunValidationAsync(Func`2 validationFunc, NameValueCollection parameters) in /_/src/IdentityServer/Validation/Default/TokenRequestValidator.cs:line 189
   at Duende.IdentityServer.Validation.TokenRequestValidator.ValidateRequestAsync(NameValueCollection parameters, ClientSecretValidationResult clientValidationResult) in /_/src/IdentityServer/Validation/Default/TokenRequestValidator.cs:line 174
   at Duende.IdentityServer.Endpoints.TokenEndpoint.ProcessTokenRequestAsync(HttpContext context) in /_/src/IdentityServer/Endpoints/TokenEndpoint.cs:line 98
   at Duende.IdentityServer.Endpoints.TokenEndpoint.ProcessAsync(HttpContext context) in /_/src/IdentityServer/Endpoints/TokenEndpoint.cs:line 75
   at Duende.IdentityServer.Hosting.IdentityServerMiddleware.Invoke(HttpContext context, IdentityServerOptions options, IEndpointRouter router, IUserSession userSession, IEventService events, IIssuerNameService issuerNameService, ISessionCoordinationService sessionCoordinationService) in /_/src/IdentityServer/Hosting/IdentityServerMiddleware.cs:line 101
   at Duende.IdentityServer.Hosting.IdentityServerMiddleware.Invoke(HttpContext context, IdentityServerOptions options, IEndpointRouter router, IUserSession userSession, IEventService events, IIssuerNameService issuerNameService, ISessionCoordinationService sessionCoordinationService) in /_/src/IdentityServer/Hosting/IdentityServerMiddleware.cs:line 117
   at Duende.IdentityServer.Hosting.MutualTlsEndpointMiddleware.Invoke(HttpContext context, IAuthenticationSchemeProvider schemes) in /_/src/IdentityServer/Hosting/MutualTlsEndpointMiddleware.cs:line 94
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
   at Duende.IdentityServer.Hosting.DynamicProviders.DynamicSchemeAuthenticationMiddleware.Invoke(HttpContext context) in /_/src/IdentityServer/Hosting/DynamicProviders/DynamicSchemes/DynamicSchemeAuthenticationMiddleware.cs:line 47
   at Duende.IdentityServer.Hosting.BaseUrlMiddleware.Invoke(HttpContext context) in /_/src/IdentityServer/Hosting/BaseUrlMiddleware.cs:line 27
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)

相关配置与依赖

Startup.cs配置

services.AddIdentityServer()
         .AddConfigurationStore(options =>
         {
            options.ConfigureDbContext = builder => builder.UseSqlServer(connectionString, sql => sql.MigrationsAssembly(migrationsAssembly));
         })
         .AddOperationalStore(options =>
         {
             options.ConfigureDbContext = builder => builder.UseSqlServer(connectionString, sql => sql.MigrationsAssembly(migrationsAssembly));

             options.EnableTokenCleanup = true;
             options.TokenCleanupInterval = 30;
         })
         .AddInMemoryApiScopes(IdentityServerConfig.GetApiScopes())
         .AddAspNetIdentity<ApplicationUser>()
         .AddExtensionGrantValidator<TokenGrantValidator>()
         .AddProfileService<ProfileService>();

主项目依赖包

<PackageReference Include="Duende.IdentityServer" Version="6.2.0" />
    <PackageReference Include="Duende.IdentityServer.AspNetIdentity" Version="6.2.0" />
    <PackageReference Include="Duende.IdentityServer.EntityFramework" Version="6.2.0" />
    <PackageReference Include="IdentityServer4.AccessTokenValidation" Version="3.0.1" />
  
    <PackageReference Include="Microsoft.AspNetCore.JsonPatch" Version="7.0.1" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc.TagHelpers" Version="2.2.0" />
    <PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.1" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.1" />

引用项目依赖包

<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="7.0.1" />
    <PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.1" />
    <PackageReference Include="NLog" Version="5.1.0" />
    <PackageReference Include="SqlBulkTools.NetStandard" Version="2.1.30" />
    <PackageReference Include="StackExchange.Redis" Version="2.1.30" />
    <PackageReference Include="WindowsAzure.Storage" Version="9.3.3" />

核心疑问

我理解Sequence contains more than one element错误的含义,但该异常发生在中间件内部,请问该如何调试排查此类SDK或中间件中的异常?


排查与解决方法

一、当前异常的直接解决

从堆栈跟踪可以明确,异常触发点是UserManager.FindByEmailAsync——ASP.NET Identity默认要求邮箱唯一,数据库中存在多个邮箱相同的用户记录,导致查询返回多条结果,触发SingleOrDefault的异常。

  • 执行SQL查询找出重复数据:
    SELECT Email, COUNT(*) 
    FROM AspNetUsers 
    GROUP BY Email 
    HAVING COUNT(*) > 1
    
  • 清理重复记录(保留有效用户,删除冗余数据),同时确保AspNetUsers表的Email字段存在唯一约束,避免后续再出现重复。

二、中间件/SDK内部异常的通用调试方法

1. 启用详细日志定位参数

在appsettings.json中调整日志级别,输出SDK内部的详细调用信息:

"Logging": {
  "LogLevel": {
    "Default": "Information",
    "Microsoft.AspNetCore.Identity": "Debug",
    "Duende.IdentityServer": "Debug"
  }
}

通过日志可以获取当前请求的用户邮箱、客户端信息等关键参数,快速锁定问题数据。

2. 替换默认服务插入调试逻辑

对于ASP.NET Identity或Duende的内置服务,可以自定义子类重写关键方法,添加日志或断点:
比如自定义用户验证器:

public class CustomUserValidator<TUser> : UserValidator<TUser> where TUser : class
{
    public CustomUserValidator(IdentityErrorDescriber errors = null) : base(errors) { }

    public override async Task<IdentityResult> ValidateAsync(UserManager<TUser> manager, TUser user)
    {
        var email = await manager.GetEmailAsync(user);
        var userId = await manager.GetUserIdAsync(user);
        // 输出调试信息
        Console.WriteLine($"Validating user ID: {userId}, Email: {email}");
        
        var result = await base.ValidateAsync(manager, user);
        return result;
    }
}

然后在Startup中替换默认验证器:

services.AddIdentity<ApplicationUser, IdentityRole>()
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddUserValidator<CustomUserValidator<ApplicationUser>>();

3. 关闭“仅我的代码”调试SDK源码

在Visual Studio中关闭“仅我的代码”选项,直接进入SDK内部断点调试:

  • 打开工具 -> 选项 -> 调试 -> 常规
  • 取消勾选“启用仅我的代码”
  • 重启调试,异常抛出时可以单步执行进入UserManager、Duende中间件的源码,查看具体执行逻辑和数据。

4. 检查迁移与数据库约束

确认升级过程中所有IdentityServer/Duende的迁移脚本都正确执行,重点检查用户表的约束:

  • 查看AspNetUsers表是否存在Email字段的唯一索引
  • 验证PersistedGrantDbContext和ConfigurationDbContext的迁移是否完整,没有遗漏的约束或字段变更

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 17:16:06