Сообщество программистов Autodesk в СНГ
ADN Club => AutoCAD .NET API => Тема начата: Дмитрий Загорулькин от 22-07-2013, 21:41:58
-
Здравствуйте!
Имеется метод, в процессе выполнения которого создаются временные объекты, которые затем экспортируются в новый чертеж. Схематично это выглядит так:
Запуск транзакции
Создание новых примитивов
Добавление примитивов в пространство модели и в транзакцию
Копирование примитивов в новый чертеж
Завершение транзакции
Мне нужно, чтобы по завершении метода чертеж вернулся в исходное состояние.
1. Правильно я понимаю, что если транзакцию не подтвердить, то это произойдет автоматически?
2. Достаточно ли просто не добавлять Transaction.Commit() или нужно обязательно вызывать Transaction.Abort()?
3. Нужно ли уничтожать каким-либо образом созданные в транзакции объекты дополнительно?
Спасибо.
-
Сделал перед завершением транзакции Transaction.Abort(). Дополнительно никакого уничтожения создаваемых объектов не выполнял. Вроде работает как надо, пока никаких проблем не обнаружил.
-
Прошу прощения, Александр Ривилис сейчас в отпуске, вернется не раньше понедельника. Думаю, он Вам подскажет ответы на вопросы. Я, к сожалению, не обладаю достаточной квалификацией для этого :(
-
Ан нет, портится чертеж :(. То есть, такой подход не гарантирует откат всего, что внутри транзакции произошло.
-
То есть, такой подход не гарантирует откат всего, что внутри транзакции произошло.
Откатывается только то, что управляется транзакцией.
P.S.: Честно говоря я не понял полную задачу. Например, зачем нужно добавлять примитивы в текущий чертеж?
-
Примитивы получаются из расчленения имеющихся в чертеже (методом Explode). То есть, это некоторый аналог стандартной функции экспорта чертежа, выполненного в вертикальном приложении в обычный AutoCAD с дополнительными необходимыми мне опциями.
Я нашел причину, из-за которой портился чертеж. Я воспользовался методом по вставке определений блоков из библиотеки, разработанным Бушманом Андреем: https://sites.google.com/site/bushmansnetlaboratory/sendbox/stati/blockdefinitionsimport и указал последний параметр DuplicateRecordCloning.Replace. Во вставляемом блоке есть атрибут с текстовым стилем, имеющимся в чертеже. После того, как программа отрабатывала и чертеж сохранялся, из базы данных удалялся этот текстовый стиль. Изменив параметр на DuplicateRecordCloning.Ignore, я избавился от этой ошибки.
А что значит "управляется транзакцией"? Это те объекты, о существовании которых мы сообщаем методом AddNewlyCreatedDBObject?
Или все те объекты, которые создаются/модифицируются с момента запуска до завершения транзакции?
-
А что значит "управляется транзакцией"? Это те объекты, о существовании которых мы сообщаем методом AddNewlyCreatedDBObject?
Или все те объекты, которые создаются/модифицируются с момента запуска до завершения транзакции?
Это те объекты, о которых транзакция знает, т.е.:
а) новые объекты, о которых мы сообщаем в методе AddNewlyCreatedDBObject
б) старые объекты, которые мы открываем методом GetObject транзакции или эквивалентными методами (например ObjectId.GetObject)
В общем чтобы получить список всех объектов, о которых "знает" транзакция, достаточно вызвать её метод GetAllObjects.
-
Спасибо, это очень полезная информация!
В общем, получается так:
- все объекты, добавленные в транзакцию методом AddNewlyCreatedDBObject удаляются, если отменить транзакцию (здесь и далее подразумевается использование метода Abort)
- все объекты, открытые с помощью GetObject транзакции или эквивалентными методами (например ObjectId.GetObject) и модифицированные, если отменить транзакцию, возвращаются в исходное состояние
- метод WblockCloneObjects с параметром DuplicateRecordCloning.Replace не только вставляет/заменяет имеющееся описание блока, но и вставляет/заменяет в чертеже используемый блоком текстовый стиль (а возможно и другую связанную с описанием блока информацию)
- если отменить транзакцию, в рамках которой выполняется этот метод, то удаляется и вставка описания блока, и вставленный текстовый стиль, даже если он присутствовал ранее в чертеже и использовался другими объектами.
Появился в связи с этим еще один вопрос: а знает ли внешняя транзакция об объектах, о которых знает внутренняя транзакция?
-
Или все те объекты, которые создаются/модифицируются с момента запуска до завершения транзакции?
Еще надо иметь в виду объекты которые удаляются, можно подумать об методе
Database.ReclaimMemoryObjectIds(idsCollection), также диспозить объекты
не резиденты для данной Database
-
а знает ли внешняя транзакция об объектах, о которых знает внутренняя транзакция?
Это TopTransaction она в курсе всех изменений :)
-
Появился в связи с этим еще один вопрос: а знает ли внешняя транзакция об объектах, о которых знает внутренняя транзакция?
Не обязана знать. Но если интересно, то можешь поэкспериментировать.
метод WblockCloneObjects с параметром DuplicateRecordCloning.Replace не только вставляет/заменяет имеющееся описание блока, но и вставляет/заменяет в чертеже используемый блоком текстовый стиль (а возможно и другую связанную с описанием блока информацию)
Дело в том, что метод WblockCloneObjects не использует механизм транзакции, и соотвественно транзакции не известны все объекты, которые будут модифицированы при вызове WblockCloneObjects.
P.S.: Мне не нравится вообще использование Transaction.Abort, которая часто во много раз медленнее чем Transaction.Commit. Я бы задумался над изменением алгоритма.
-
Мне не нравится вообще использование Transaction.Abort, которая часто во много раз медленнее чем Transaction.Commit. Я бы задумался над изменением алгоритма.
Согласен, никогда не использую метод Abort, лучше заключать в объекты в блок using {...}
P.S.:Чтобы не сохранять изменения в базе данных можно еще посмотреть флаги
-
Еще надо иметь в виду объекты которые удаляются, можно подумать об методе
Database.ReclaimMemoryObjectIds(idsCollection), также диспозить объекты
не резиденты для данной Database
Объекты я не удаляю, так что мне пока без надобности. Но на будущее учту, спасибо!
Это TopTransaction она в курсе всех изменений
Не обязана знать. Но если интересно, то можешь поэкспериментировать.
Несколько противоречиво :) Ладно, буду испытывать.
P.S.: Мне не нравится вообще использование Transaction.Abort, которая часто во много раз медленнее чем Transaction.Commit. Я бы задумался над изменением алгоритма.
Есть такое, на откат изменений довольно много времени уходит, но это несколько секунд. Предыдущий вариант моей программы был на VisualLISP, и гораздо больше времени занимал. Там, правда, алгоритм совершенно другой.
Согласен, никогда не использую метод Abort
Было очень заманчиво - так просто выполнить откат, без дополнительных телодвижений :) А так, придется запоминать первоначальное состояние изменяемых объектов, а потом его восстанавливать. То есть, кода побольше получится, в варианте с отменой транзакции: просто изменить, в варианте без отмены: запомнить - изменить - восстановить. И при добавлении функционала нужно будет помнить, что изменения в 3 места надо вносить, вместо 1.
P.S.:Чтобы не сохранять изменения в базе данных можно еще посмотреть флаги
Где смотреть? Какие флаги? :)
P.S. Имеется в виду второй параметр метода AddNewlyCreatedDBObject?
-
А так, придется запоминать первоначальное состояние изменяемых объектов, а потом его восстанавливать. То есть, кода побольше получится, в варианте с отменой транзакции: просто изменить, в варианте без отмены: запомнить - изменить - восстановить. И при добавлении функционала нужно будет помнить, что изменения в 3 места надо вносить, вместо 1.
Мне кажется, что при озвученной постановке задачи можно не трогать текущий чертеж, а все действия производить с новым чертежом. Соотвественно ничего "откатывать" в текущем чертеже не придётся.
-
Какие флаги?
Я имел в виду CommandFlags, немного информации здесь:
http://spiderinnet1.typepad.com/.services/blog/6a0153928ee38e970b0153928f11cc970b/search?filter.q=CommandFlags
-
Мне кажется, что при озвученной постановке задачи можно не трогать текущий чертеж, а все действия производить с новым чертежом. Соотвественно ничего "откатывать" в текущем чертеже не придётся.
Тогда придется долго и нудно чистить целевой чертеж от ненужных объектов, потому что в вертикальных решениях есть неразрывная динамическая связь между объектами и при копировании нужных объектов будет цепляться куча ненужных. Причем, я даже до конца не знаю размеры этой кучи...
Я имел в виду CommandFlags
Флаги посмотрел, но отвечающего за сохранность чертежа не обнаружил. Возможно Вы имели в виду флаги блокировки документа, но они его блокируют от изменений другими командами, а не от выполняемой.
Спасибо за консультации! Как время появится, переделаю программу с целью избавления от метода Abort. Попробую вручную удалять создаваемые объекты перед завершением транзакции.