为何Linq查询用户数据的代码会间歇性抛出NullReferenceException异常
异常根本原因
你遇到的间歇性空引用异常,核心问题出在静态DbContext的线程安全问题:
DbContext本身设计为非线程安全类型,你的代码把Entities实例定义为Repository的静态变量,所有请求会共享同一个DbContext实例。ASP.NET Web API 每个请求对应独立线程,多个请求并发操作同一个DbContext时,会导致其内部的连接状态、实体跟踪状态被其他线程篡改,执行查询时就会随机触发空引用异常。这也是你调试时单独执行该行代码不会报错的原因:调试是单线程场景,不存在并发冲突。- 额外存在一个严重业务隐患:
BaseApiController中的CurrentUser被定义为静态变量,会在所有请求之间共享,会出现不同用户的请求互相覆盖用户信息的串号问题。
修复方案
- 移除静态
DbContext实例,改为每次操作数据库时创建新的DbContext实例,或通过依赖注入框架为每个请求注入独立的DbContext实例。 - 将
CurrentUser改为控制器实例属性,每个请求对应独立的用户信息存储。 - 调整
UserToken方法,每次查询使用独立的DbContext:
public static tUser UserToken(string token) { string username = ExtractUserName(token); if (string.IsNullOrEmpty(username)) return null; try { // 每次查询单独创建DbContext,查询结束自动释放资源 using(var db = new Entities(ConfigurationManager.AppSettings["ConnectionString"].ToString())) { tUser user = db.tUsers.Where(u => u.UserName == username && u.IsDeleted == false).FirstOrDefault(); return user; } } catch (Exception ex) { // 建议此处增加异常日志记录,方便后续排查问题 return null; } }
内容的提问来源于stack exchange,提问作者mitchsnitchel
相关产品推荐
相关产品推荐

