В AutoCAD 2018.1 метод UpgradeOpen приводит к фатальной ошибке внутри транзакции
Вопрос: Я обнаружил, что если использовать метод UpgradeOpen внутри транзакции, в которой этот объект открыт для чтения, то это приводит к фатальной ошибке. Пример кода, приводящий к такой ошибке:
- using (Transaction tr = db.TransactionManager.StartTransaction())
- {
- LayerTable lt = tr.GetObject(db.LayerTableId, OpenMode.ForWrite);
- foreach (ObjectId LayId in lt)
- {
- LayerTableRecord lay = tr.GetObject(LayId, OpenMode.ForRead);
- if (lay.IsDependent)
- {
- lay.UpgradeOpen();
- lay.IsLocked = true;
- lay.IsFrozen = true;
- }
- }
- tr.Commit();
- }
В предыдущих версиях AutoCAD и в AutoCAD 2018 до 2018.1 этот код нормально работал. Что не так?
Ответ: Метод UpgradeOpen () - это оболочка для C ++ метода AcDbObject::upgradeOpen (), которая предназначена для механизма open/close, а не для механизма транзакций. Поскольку вы работаете с транзакцией и это не транзакция open/close, вместо использования UpgradeOpen () вы должны сделать еще один вызов tr.GetObject (), но делайте его с OpenMode.ForWrite а не с OpenMode.ForRead. Таким образом, открытый для записи объект будет частью транзакции.
Смешение механизмов open/close с обычными транзакциями для одного и того же объекта одновременно является ненадежным и может привести к проблемам, описанным выше.
Если заменить db.TransactionManager.StartTransaction() на db.TransactionManager.StartOpenCloseTransaction(), то можно безболезненно использовать UpgradeOpen с объектом, открытым в такой транзакции.
Если перед завершением обычной транзакции вызвать DowngradeOpen, для объекта, для которого вызывали UpgradeOpen, то это тоже предотвращает фатальную ошибку.
Обсуждение: http://adn-cis.org/forum/index.php?topic=7943
Опубликовано 05.08.2017