C#模拟DbContext属性调试显值但触发空引用异常问题
调试DbContext属性时的NullReference异常问题
问题现象
- 调试悬停DbContext容器类时,Persons属性显示存在值(以
Castle.Proxies.开头),且Results View中显示包含一个元素的List(符合预期)。 - 直接引用该属性时,悬停显示为NULL,调用操作会触发
NullReferenceException。
容器类定义
public interface IBrokerContext : IDisposable { DbSet<Agents> Agents { get; set; } IDbContextTransactionProxy BeginTransaction(); } public class BrokerContext : ApplicationDbContext, IBrokerContext { public new DbSet<Agents> Agents { get; set; } ... }
BrokerContext作为ApplicationDbContext的代理/适配器,用于模拟BeginTransaction()方法。
场景说明
业务代码中使用ApplicationDbContext类型的_db实例,该实例包含BrokerContext中声明的集合。测试时尝试构造BrokerContext的模拟对象,传入被测试类以覆盖ApplicationDbContext,从而控制BeginTransaction()的行为。
执行mockDb.Object.Agents = mockAgentSet.Object赋值后,调试视图显示_db.Agents有值,但引用await _db.Agents时却返回null!
被覆盖的DbContext定义
public class ApplicationDbContext : IdentityDbContext<ApplicationUser> { public virtual DbSet<Agents> Agents { get; set; } ... }
问题原因
核心是**new关键字隐藏基类成员**的特性导致的:
- BrokerContext中用
new声明的Agents属性,仅隐藏了基类ApplicationDbContext的同名属性,并未重写。 - 业务代码里的
_db是ApplicationDbContext编译时类型,访问_db.Agents时,实际调用的是基类的virtual属性,而非BrokerContext里的新属性。 - 调试器显示的是实例运行时类型(BrokerContext)的成员,因此能看到赋值后的新属性值,但代码执行遵循编译时类型的访问规则,基类属性未被赋值,所以返回null。
解决方法
方法1:重写基类属性(推荐)
去掉BrokerContext中的new关键字,改用override重写基类的virtual属性,确保编译时和运行时的属性访问一致:
public class BrokerContext : ApplicationDbContext, IBrokerContext { public override DbSet<Agents> Agents { get; set; } ... }
方法2:调整业务代码的依赖类型
将业务代码中_db的类型改为IBrokerContext,直接访问接口定义的Agents属性,对应到BrokerContext的实现:
// 业务代码中修改依赖注入的类型 private readonly IBrokerContext _db; public YourService(IBrokerContext db) { _db = db; }
内容的提问来源于stack exchange,提问作者HelloWorld
相关产品推荐
相关产品推荐

