
问题解答传Entity vs 传ObjectId先把你的场景前提说清楚你现在这套XDataParserNJ全部传入Entity entity前提调用方必须已经在打开的事务范围内拿到这个EntityOpenMode.ForRead事务没有释放实体对象没有Dispose。1、传Entity方案的优点你说的少一层事务打开确实成立上层已经打开事务拿到实体直接把实体引用向下传递工具内部不需要再new Transaction、不需要GetObject代码简洁减少重复写事务样板代码读取XData本身只需要ForRead不会修改实体读取场景下性能、内存都没问题你现在的读取逻辑只读XData不修改实体这套读取代码本身设计是可以这么写的能正常工作。2、致命风险点必须重视坑都出在调用方不是Parser内部风险不在XDataParserNJ内部风险在调用者忘记约束传入已经失效的Entity。什么情况下Entity会失效、直接崩溃事务tr.Commit()/tr.Abort()之后事务销毁你还拿着外面的Entity引用再调用GetDictionary(entity)直接报ObjectDisposedExceptionusing事务块结束Entity超出生命周期对象已经被回收多线程场景、CAD事件回调把Entity存到类成员变量隔一段时间再去调用读取。现象调试的时候在同一个事务内调用一切正常代码跑一段时间偶现崩溃很难复现。传ObjectId的优势在哪里//输入ObjectId工具内部自己开事务读取 Dictionarystring,string GetDictionary(ObjectId entId)工具函数内部自己负责GetObject using(transaction)调用方无论怎么传都不会传进来一个已经销毁的实体调用方不用关心当前是否处在事务里随时拿Id就可以调用鲁棒性更高代价就是内部每次会新建一次读取事务仅仅ForRead开销很小管网几十上百实体完全无压力。3、分场景给结论✅【读取场景你现在XDataParserNJ这套读取】只读取XData不修改实体可以继续使用Entity入参但是要强制约定调用契约契约必须写在注释上/// summary /// 获取实体XData键值字典 /// 【调用约束】传入的entity必须来自当前未提交/未释放的事务OpenMode.ForRead事务不能提前Dispose /// 禁止把Entity保存到成员变量、跨事务调用跨事务请使用ObjectId版本重载 /// /summary /// param nameentity事务中打开的实体/param /// returns/returns public override Dictionarystring, string GetDictionary(Entity entity)适合上层已经在事务内部循环遍历实体直接向下传递实体追求少写事务代码。⚠️【写入XData场景强烈不建议传Entity】写入XData需要OpenMode.ForWrite如果你上层传进来一个ForRead打开的Entity工具内部没办法把它升级成写你要么上层必须ForWrite打开要么工具内部要重新GetObject那实体参数就失去意义。写入XData建议全部使用ObjectId作为入参工具内部自己开启事务ForWrite打开实体控制完整生命周期。✨折中方案推荐工程上的写法两套重载都实现现有版本传入Entity仅限同事务内调用用于循环批量读取增加一个ObjectId对外公开入口内部自己开事务拿到Entity再调用现有逻辑。public Dictionarystring, string GetDictionary(ObjectId entityId) { using(var tr entityId.Database.TransactionManager.StartTransaction()) { var ent tr.GetObject(entityId, OpenMode.ForRead) as Entity; var dict GetDictionary(ent); tr.Commit(); return dict; } }这样循环批量读取的时候上层拿到Entity直接调用第一个重载省事务其他零散场景手里只有ObjectId直接调用Id版本不用关心事务4、回到你现在的XDataParserNJ现状总结当前读取逻辑功能没问题是可行的设计隐患不在Parser内部在于调用方违反契约传入已经释放的Entity写XData那一侧一定不要照搬Entity入参优先ObjectId建议增加ObjectId的重载做对外安全入口防止外部调用者踩坑。顺带确认你的XData写入规则对齐读取代码你的读取规则XData AppName1001(应用程序名)组码1000存储字符串格式key:value分隔符来自PipeFieldConfig.Instance.FieldDelimiter一个1000组码存一组key:value多个字段就多条1000。写入的时候要严格对齐先清除旧的该AppName下全部XData再批量追加一组一组1000的key:value字符串不要拼接成一个大字符串塞单个1000否则读取解析会出错。接下来我们就基于这套规则写XData写入工具输入ObjectId Dictionarystring,string写入这套格式的XData。需要我直接输出写入工具代码吗