Azure Durable Function的Durable Entity触发空引用异常问题
根因分析
本次System.NullReferenceException异常的核心触发原因是orchestrationStatus属性在Durable Entity反序列化后被赋值为null,调用Add方法时触发空引用,具体原因如下:
你在类上指定了[JsonObject(MemberSerialization = MemberSerialization.OptIn)],该规则要求只有显式标记[JsonProperty]的属性才会参与序列化/反序列化。当Durable Entity首次创建、或者从持久化存储中恢复时,如果存储中不存在该属性的历史值,Newtonsoft.Json的反序列化逻辑会直接覆盖属性的默认初始化值为null,你写的= new List<string>()初始化逻辑不会生效。
注:如果是调用Set方法传入的code参数为null,往List中Add空值不会触发空引用异常,可直接排除该场景
排查步骤
- 在
Set方法第一行添加断点,调试确认this.orchestrationStatus的值是否为null,验证上述根因 - 查看Durable Entity的持久化存储(默认是Azure Storage表),确认对应实体记录的
orchestrationStatus字段是否存储为空
解决方案
可任选以下任意一种方案修复:
方案1:添加非空保护逻辑
修改Set方法,调用前先判断集合是否为空,为空则初始化:
public Task Set(string code) { this.orchestrationStatus ??= new List<string>(); this.orchestrationStatus.Add(code); return Task.CompletedTask; }
也可以直接给JsonProperty添加默认值处理配置,避免反序列化覆盖初始化值:
[JsonProperty("orchestrationStatus", DefaultValueHandling = DefaultValueHandling.Populate)] public List<string> orchestrationStatus { get; set; } = new List<string>();
方案2:移除OptIn序列化配置
如果没有特殊的序列化裁剪要求,直接删除类上的[JsonObject(MemberSerialization = MemberSerialization.OptIn)]注解即可,Durable Entity默认序列化规则会自动保留属性的初始化值,不会出现反序列化后为空的问题。
方案3:将集合属性改为只读
修改属性为只读,避免反序列化时直接替换整个集合实例:
[JsonProperty("orchestrationStatus")] public List<string> orchestrationStatus { get; } = new List<string>();
只读属性的集合在反序列化时会往已有的实例中追加元素,不会覆盖替换集合实例,也就不会被赋值为null。
内容的提问来源于stack exchange,提问作者Jonas

