C#控制器转换为DrugInteractionDTO时出现空引用异常求助
解决C#控制器转换DrugInteractionDTO时的空引用错误
问题原因
你遇到的Object reference not set to an instance of an object错误,本质是关联实体未被加载:
_context.DrugInteractions.FindAsync(id)只会加载DrugInteraction本身的属性,不会自动加载其导航属性AntifungalAgent和InteractingDrug;- 直接返回原始对象时,ASP.NET Core在序列化过程中可能触发了延迟加载(若你的DbContext开启了该功能),但转换DTO时是直接访问子属性,此时关联实体为null,就会抛出空引用异常。
解决方案
方案1:显式加载关联实体(推荐)
使用EF Core的Include方法,在查询时主动加载需要的导航属性,替换FindAsync为FirstOrDefaultAsync(因为FindAsync不支持链式调用Include):
[HttpGet("interaction/{id}")] public async Task<ActionResult<DrugInteractionDTO>> getInteractionDetails(int id) { var interaction = await _context.DrugInteractions .Include(i => i.AntifungalAgent) // 加载关联的抗真菌药物 .Include(i => i.InteractingDrug) // 加载关联的相互作用药物 .FirstOrDefaultAsync(i => i.ID == id); if(interaction == null) { return NotFound(); } // 额外校验关联实体是否存在,避免数据库中关联字段为空的情况 if (interaction.AntifungalAgent == null) { return BadRequest("关联的抗真菌药物信息不存在"); } if (interaction.InteractingDrug == null) { return BadRequest("关联的相互作用药物信息不存在"); } return new DrugInteractionDTO { Severity = interaction.Severity, SeverityAsString = interaction.Severity.ToString(), ProDetailedInformation = interaction.ProDetailedInformation, BasicDetailedInformation = interaction.BasicDetailedInformation, Antifungal = interaction.AntifungalAgent.Name, InteractingDrug = interaction.InteractingDrug.GenericName, ID = interaction.ID }; }
方案2:开启延迟加载(不推荐,存在性能风险)
如果你的DbContext未开启延迟加载,可以通过以下方式开启:
- 确保实体类的导航属性标记为
virtual:
public class DrugInteraction { // 其他属性... public virtual AntifungalAgent AntifungalAgent { get; set; } public virtual InteractingDrug InteractingDrug { get; set; } }
- 在DbContext的构造函数中配置延迟加载:
public YourDbContext(DbContextOptions<YourDbContext> options) : base(options) { ChangeTracker.LazyLoadingEnabled = true; }
注意:延迟加载会导致N+1查询问题(加载主实体后,每个子实体都会触发单独查询),仅在小数据量场景下临时使用。
方案3:检查数据库数据完整性
确认数据库中DrugInteractions表对应ID的记录,其AntifungalAgentId和InteractingDrugId字段是否关联了有效的、存在的记录。如果关联字段为null或指向不存在的记录,即使加载了导航属性,也会出现null引用。
内容的提问来源于stack exchange,提问作者Danny Jebb
相关产品推荐
相关产品推荐

