Сообщество программистов Autodesk в СНГ

ADN Club => Civil 3D API => Тема начата: Дмитрий Загорулькин от 14-11-2019, 18:20:37

Название: ObjectId.IsEffictivelyErased = true у трубы или колодца.
Отправлено: Дмитрий Загорулькин от 14-11-2019, 18:20:37
Здравствуйте!
Моё .NET-приложение создаёт несколько труб и колодцев в Civil 3D 2020. Они создаются в цикле по заранее вычисленным параметрам. Сперва - трубы, потом, на их концах, - колодцы. А потом трубы цепляются к колодцам. Количество - несколько десятков.
И, почему-то, некоторые из них (2-3 штуки) после создания имеют свойство ObjectId.IsEffictivelyErased = true. При этом, объекты на чертеже есть. при попытке посмотреть их свойства через
ARXDBG выскакивает ошибка "ARX ERROR" (см. картинку). Но потом всё равно открывается окно с данными об объекте. Притом, если повторять создание несколько раз, то каждый раз объекты с таким свойством возникаю рандомно. То есть, в первый раз - одни трубы-колодцы, в следующий - другие. Иногда вообще без этого отрабатывает.
Если чертёж сохранить и открыть заново - эти объекты "чинятся", ObjectId.IsEffictivelyErased становится равно false.
В связи с этим, у меня вопросы:
В чём теоретически может быть проблема?
Даёт ли какую-то полезную информацию это сообщение об ошибке ARX?
Может не стоит совсем обращать внимание на значение ObjectId.IsEffictivelyErased и спокойно продолжать открывать объект на чтение-запись в коде .NET?
Название: Re: ObjectId.IsEffictivelyErased = true у трубы или колодца.
Отправлено: Александр Ривилис от 14-11-2019, 18:23:39
Даёт ли какую-то полезную информацию это сообщение об ошибке ARX?
Да. Объект был открыт максимальное количество раз (255) и при этом не был закрыт. Копай в эту сторону.
Название: Re: ObjectId.IsEffictivelyErased = true у трубы или колодца.
Отправлено: Дмитрий Загорулькин от 14-11-2019, 18:25:58
Ох ничего себе! Да, это так просто нельзя оставлять... Спасибо! Буду искать причину.
Название: Re: ObjectId.IsEffictivelyErased = true у трубы или колодца.
Отправлено: Александр Ривилис от 14-11-2019, 18:28:14
Ох ничего себе! Да, это так просто нельзя оставлять... Спасибо! Буду искать причину.
Теоретически это может быть баг в AutoCAD/Civil 3D, но конечно нужно в первую очередь проверять у себя в коде.
Причем с обычной транзакцией это происходить не должно - или ObjectId.Open, или эмуляция транзакции.
Название: Re: ObjectId.IsEffictivelyErased = true у трубы или колодца.
Отправлено: Дмитрий Загорулькин от 14-11-2019, 18:29:41
или ObjectId.Open, или эмуляция транзакции
Да, это у меня есть. Буду проверять.
Название: Re: ObjectId.IsEffictivelyErased = true у трубы или колодца.
Отправлено: Дмитрий Загорулькин от 14-11-2019, 20:12:50
Как оказалось, работу нарушал с виду довольно безобидный метод:
Код - C# [Выбрать]
  1. static T GetOrOpenForWrite<T>(Transaction tr, ObjectId id)where T : DBObject
  2. {
  3.     using (DBObjectCollection allTrObjects = tr.GetAllObjects())
  4.     {
  5.         return allTrObjects
  6.             .Cast<DBObject>()
  7.             .FirstOrDefault(item
  8.                 => item is T dbObject
  9.                 && dbObject.Id.Equals(id)
  10.                 && dbObject.IsWriteEnabled) as T
  11.             ?? tr.GetObject(id, OpenMode.ForWrite) as T;
  12.     }
  13. }
  14.  
Идея его такая. Есть довольно много ObjectId труб и колодцев. Они берутся попарно и с ними производятся манипуляции: открытие, проверка, если проверка пройдена - модификация. И чтобы не открывать дважды один и тот же объект, ищем - не был ли он открыт ранее в этой транзакции? Если да, то берём из списка объектов, открытых в транзакции. Если нет - открываем объект этой транзакцией. Хотя, по сути, как я понимаю, это - уже извращение. Потому что при повторном открытии объекта транзакцией никакого криминала не возникает. Я так понимаю, всё то что в этом методе, транзакция делает внутри себя при открытии объекта. Но мне почему-то захотелось сделать это явно...  :-X
При замене вызова этого метода на простое открытие объекта транзакцией проблема пропадает.