Revit API предоставляет нам широкие возможности по изменению документов. Одновременно, он ставит нам и некоторые ограничения, чтобы мы случайно ничего не сломали.
Одним из таких ограничений являются транзакции. Обычно мы взаимодействуем с ними, когда раскрываем список последних команд у стрелочки "Отменить":
В чём же состоит ограничение? Мы не можем модифицировать документ вне транзакции. Смысл тут в том, что если мы что-то набедокурим нашим плагином, мы можем легко всё отменить. Давайте проверим: напишем код, который всем элементам на активном виде будет записывать значение Id в параметр "Комментарии".
В данном коде практически всё рассматривалось в предыдущих статьях. Остановлюсь чуть подробнее на поиске параметра.
В данном случае я ищу параметр через метод LookupParameter(), которому передаю строку — точное имя параметра. Он возвращает либо параметр, если найдёт его, либо null, если не найдёт. Поэтому далее я проверяю, что мы получили параметр, а не null, и если так, то с помощью метода Set() записываю значение в виде строки.
Запустим плагин через Addin Manager, и что же мы увидим:
Если запустить плагин из Ревита, то увидим примерно тоже самое:
В общем, не надо быть знатоком английского уровня C1: Исключение "Попытка изменить модель вне транзакции" означает, что мы эту транзакцию забыли. Исправим код:
Что я сделал: добавил выражение
using (Transaction t = new Transaction(doc, "Моя первая транзакция"))
И обернул весь код по получению и изменению параметра в фигурные скобки.
Методы Start() и Commit() начинают и завершают транзакцию, соответственно.
Нам необязательно завершать транзакцию. Мы можем её откатить назад (RollBack()). Зачем? Например, так можно вычислить площадь проёмов в стене: взять площадь стены, удалить все проёмы, взять новую площадь и откатить транзакцию.
В данном случае я специально поставил транзакцию внутри цикла (правильнее было окружить весь цикл транзакцией), чтобы получить следующий результат:
35 транзакций за одно действие. Не очень удобно (особенно если вышла ошибка). Что же делать?
Во-первых, нет никакой необходимости начинать транзакцию внутри каждой итерации цикла. Мы можем вынести её перед циклом, начать до старта цикла и завершить после. Транзакция будет одна и её легко можно будет отменить через Ctrl-Z.
Но иногда нам требуется завершить транзакцию и начать новую. Например, мы создали элемент и хотим что-то с ним сделать дальше. Это невозможно: пока мы не завершим транзакцию, Revit будет думать, что элемента нет в базе данных. Тогда мы можем воспользоваться группой транзакций:
Все транзакции соберутся в одну — результат достигнут.
А на этом всё! Приглашаю вас в свой телеграм-канал о Revit API и до новых встреч!