使用Mapster时循环引用引发栈溢出导致进程终止如何解决
Mapster默认采用递归遍历属性的逻辑执行对象映射,当TSource或TDestination的类结构存在双向关联引用时(例如:父对象持有子对象属性,子对象又持有指向父对象的属性),递归映射逻辑会在两个关联对象之间无限循环执行,没有终止条件,最终调用栈深度超过运行时限制,触发栈溢出异常,导致进程直接终止。
启用Mapster内置的引用保留配置
全局生效配置:TypeAdapterConfig.GlobalSettings.Default.PreserveReference(true);
仅针对指定映射对生效配置:TypeAdapterConfig<TSource, TDestination>.NewConfig().PreserveReference(true);
开启该配置后,Mapster会在映射过程中跟踪已处理过的对象引用,遇到重复引用时直接返回已生成的映射结果,不再重复递归遍历,直接阻断循环链路。手动忽略导致循环的关联属性
如果你不需要映射循环链路中的某部分属性,可以通过配置忽略对应的属性,切断循环路径,示例配置:TypeAdapterConfig<TSource, TDestination>.NewConfig() .Ignore(dest => dest.CircularNavigationProperty);该方案适合无需使用循环关联属性的业务场景,配置灵活度高。
使用投影方法替代直接Adapt调用
如果映射的源对象是EF Core等ORM框架的查询结果,可直接调用ProjectTo<TDestination>()方法完成映射,该方法会在数据库查询层面完成字段映射,不会加载关联的循环导航属性,既可以避免循环引用问题,性能也优于内存对象递归映射。调整DTO结构消除循环引用
业务层DTO设计时尽量遵循单向引用原则,不要和数据库实体保持完全一致的双向关联结构,例如仅保留父对象指向子对象的属性,删除子对象中指向父对象的关联属性,从数据结构层面直接消除循环引用的可能,是长期最优的解决方案。
内容的提问来源于stack exchange,提问作者e03050

