ASP.Net 5升级至7后userManager.FindByNameAsync()抛出空值异常
问题:ASP.NET 7升级后调用
userManager.FindByNameAsync()抛出SqlNullValueException 异常现象
- 从ASP.NET 5升级到ASP.NET 7后,调用
userManager.FindByNameAsync("Admin")时抛出SqlNullValueException,提示"Data is Null. This method or property cannot be called on Null values." - 该方法在ASP.NET 5中正常运行,传入参数正确,但执行时直接报错终止调试
- 目标用户由
userManager.CreateAsync()创建
关键代码片段
User模型
namespace API.Models { public class User : IdentityUser<int> { public string FirstName { get; set; } //********** Visa Info********** public string ClientName { get; set; } public string BankName { get; set; } public int AccountNumber { get; set; } public string Section { get; set; } public int CardNumber { get; set; } public string CardName { get; set; } public int WalletNumber { get; set; } public string lastName { get; set; } public string address { get; set; } public string ImageID { get; set; } public int TotalProfits { get; set; } = 0; public int WithdrawnProfits { get; set; } = 0; public virtual ICollection<Product> Products { get; set; } public virtual ICollection<Order> Orders { get; set; } public ICollection<UserRole> UserRoles { get; set; } public ICollection<WithdrawRequest> WithdrawRequests { get; set; } public virtual ICollection<UserBill> UserBills { get; set; } } }
调用方法代码
private async Task CreateAdmin() { var admin = await _userManager.FindByNameAsync("Admin"); if (admin == null) { var newUser = new User { Email = "admin@admin.com", UserName = "Admin", PhoneNumber = "0796544854", EmailConfirmed = true }; var createAdmin = await _userManager.CreateAsync(newUser, "1234"); if (createAdmin.Succeeded) { if (await _roleManager.RoleExistsAsync("Admin")) await _userManager.AddToRoleAsync(newUser, "Admin"); } var newShippCompany = new ShippingCompany { Id = 1, companyName = "Not Attached", companyPhone = null }; await _souqlyRepo.Add(newShippCompany); await _souqlyRepo.SaveAll(); } }
完整异常栈
{System.Data.SqlTypes.SqlNullValueException: Data is Null. This method or property cannot be called on Null values. at Microsoft.Data.SqlClient.SqlBuffer.ThrowIfNull() at Microsoft.Data.SqlClient.SqlBuffer.get_String() at Microsoft.Data.SqlClient.SqlDataReader.GetString(Int32 i) at lambda_method42(Closure, QueryContext, DbDataReader, ResultContext, SingleQueryResultCoordinator) at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.MoveNextAsync() 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.FindByNameAsync(String userName) at API.Controllers.AuthController.CreateAdmin() in /Users/ahmedgamal/projects/API/Controllers/AuthController.cs:line 84 at API.Controllers.AuthController.Login(UserForLogin userForLogin) in /Users/ahmedgamal/projects/API/Controllers/AuthController.cs:line 149 at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(ActionContext actionContext, IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope) at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger) at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context) at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context) at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext) at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider) at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context) HEADERS ======= Accept: */* Connection: keep-alive Host: localhost:5077 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 Accept-Encoding: gzip, deflate, br Accept-Language: en-US,en;q=0.9 Content-Type: application/json-patch+json Cookie: _xsrf=2|7ddc8933|478e981c349410ca2e05fa7b50dcaeee|1671139281; username-localhost-8888="2|1:0|10:1671456298|23:username-localhost-8888|44:NjA1OTkxOTgzZjFhNDE1MWFhOTIxNWQ3ZDczZjU1MjY=|5ae71afcdb82e897faa88c8158ab4ccb4edfbe7e4478f2e6dc88926938171b11"; .AspNetCore.Antiforgery._EomAn3AoJg=CfDJ8Oe9S8Poye1KncOFEtdCmBpov-Z4Szk20KKrAQTFIPoPKPabF-KF8zohP-BZVw8pL_FKLxPvrlxXrZt5K5SBF3YB9-5Lul_q0outcr2kZgyc4glteG-JGf8j0_pq2-a0_DN9WupHrzZo3igvLzqBsoQ; .AspNetCore.Session=CfDJ8Oe9S8Poye1KncOFEtdCmBr0c19qm2tGMZe7b6rkQbgsvt77HALStTx0XC86brZHEp8kf6YdM46RUT1wt0K6Wfa7mMXMXHE58ap382sIuQOtujORzTAnlBVLypOYMuJTwj%2BLmJ4lrUHWyY98ViOI9UdtLv1N6Nifn4%2BfUZE2I9QM Origin: http://localhost:5077 Referer: http://localhost:5077/swagger/index.html Content-Length: 116 sec-ch-ua: "Not?A_Brand";v="8", "Chromium";v="108", "Google Chrome";v="108" sec-ch-ua-mobile: ?0 sec-ch-ua-platform: "macOS" Sec-Fetch-Site: same-origin Sec-Fetch-Mode: cors Sec-Fetch-Dest: empty }
原因分析
- 值类型字段的Null兼容性问题:User模型中
AccountNumber、CardNumber、WalletNumber为非可空int类型,但数据库中这些字段存在Null值。ASP.NET 7对应的EF Core 7.0对值类型的Null处理更严格,读取Null值到非可空值类型时直接抛出异常;而ASP.NET 5使用的EF Core 5.0会默认将Null转换为值类型默认值(如0),不会报错。 - 数据与模型不匹配:升级后数据库结构未同步,或旧数据中存在这些值类型字段为Null的记录,导致查询时无法完成映射。
解决方法
方法1:修改模型字段为可空类型
将User模型中的非可空int字段改为可空int?,允许数据库Null值映射到模型:
public int? AccountNumber { get; set; } public int? CardNumber { get; set; } public int? WalletNumber { get; set; }
修改后生成并执行数据库迁移,更新表结构允许这些字段为Null。
方法2:填充数据库中的Null值
如果业务要求这些字段不能为Null,需检查数据库中已有用户记录,将这些int类型字段的Null值填充为合理默认值(如0),确保模型与数据一致。
方法3:调整EF Core配置
检查DbContext中是否对这些字段设置了IsRequired(),若业务允许,移除该配置或改为IsRequired(false)。
额外优化
创建用户时补充这些值类型字段的默认值(当前CreateAdmin方法中未设置这些字段,导致数据库中为Null),后续新增用户时添加必填校验或默认值赋值逻辑。
内容的提问来源于stack exchange,提问作者Ahmed Gamal
相关产品推荐
相关产品推荐

