Перебор всех объектов

Автор Тема: Перебор всех объектов  (Прочитано 1309 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн Дмитрий Загорулькин

  • ADN
  • *
  • Сообщений: 1727
  • Карма: 426
  • LISP/C#, AutoCAD/Civil 3D
  • Skype: zagor_dmtr
Re: Перебор всех объектов
« Ответ #30 : 13-10-2018, 15:38:54 »
Моя СУБДшная натура категорически против отказа от транзакций, там где они возможны.
Я так понимаю, что это не те транзакции, что в СУБД. Общее у них только название. А по факту, получился инструмент, который на начальных этапах освоения API сильно упрощает жизнь, а в дальнейшем - может её сильно испортить.
где транзакция длинная - заводил отдельную, где мелочевка - передаю теперь свыше в параметрах или полях классов.
В том-то и дело. Я так понимаю, что есть некоторые вспомогательные методы, которые выполняют обработку переданных данных. Пока они вызываются из командных методов, всё работает вроде как надо. Но впоследствии эти же методы возможно понадобится вызывать из различных событий, из методов Overrule и тд и тп, то есть, в тех случаях, когда транзакция может испортить работу AutoCAD, приводя к Fatal Error. Отлавливание таких ошибок - очень непростое дело.
Я для себя пришёл к такому решению: если пишется "библиотечный" метод, лучше, чтобы в нём не было транзакций. Либо передаю уже открытый объект(на чтение, на запись), либо открываю внутри метода объект с помощью ObjectId.Open или OpenCloseTransaction.GetObject.

Оффлайн avc

  • ADN Club
  • ****
  • Сообщений: 394
  • Карма: 72
    • Мои плагины к Автокаду
Re: Перебор всех объектов
« Ответ #31 : 13-10-2018, 16:31:01 »
это не те транзакции, что в СУБД
Почему же не те - принцип как раз тот: изоляция изменений до коммита транзакции, откат всех изменений целиком. На ранних этапах (да и теперь) они конечно сильно УСЛОЖНЯЮТ жизнь, удлиняют код. В сравнении со всякими VBA. Но повышают дуракоустойчивость кода. В обработчиках событий транзакции у меня живут прекрасно и им там самое место. ИМХО. Нельзя сказать наверняка, но похоже больше фаталов от смешивания подходов - часть методов безтранзакционные, часть используют toptransaction не явно и влетают на чужие транзакции, которые внезапно комитятся, а открытые объекты остаются в вашем коде... и гуд-бай Автокад... API позволяет намешать такой винегрет, что мама не горюй. А примеры, понадерганные из форумов, этому только способствуют. И, как тут только что выяснилось, примеры с принципиальными ошибками пишут даже гуру. 

Оффлайн Дмитрий Загорулькин

  • ADN
  • *
  • Сообщений: 1727
  • Карма: 426
  • LISP/C#, AutoCAD/Civil 3D
  • Skype: zagor_dmtr
Re: Перебор всех объектов
« Ответ #32 : 13-10-2018, 17:14:34 »
Как один из недавних примеров: http://adn-cis.org/forum/index.php?topic=7829.0
Цитировать
Казалось бы, никакой проблемы - используем транзакцию и радуемся. Но! При обработке больших чертежей, в какой-то случайный момент вываливается исключение System.AccessViolationException без указания места, в котором это исключение возникло. Без транзакции исключений не возникает
Если поискать по форуму, можно найти ещё несколько тем, где обсуждается необходимость отказа от транзакций в определённых случаях.

Оффлайн avc

  • ADN Club
  • ****
  • Сообщений: 394
  • Карма: 72
    • Мои плагины к Автокаду
Re: Перебор всех объектов
« Ответ #33 : 13-10-2018, 17:27:48 »
Вроде как раз примеры того, как не надо смешивать транзакции и доступ к БД без транзакций. К тем же записям! Уж если где-то получаете объекты без транзакций, то делайте так везде и будет все хорошо. Если, конечно, справитесь с тем, чтоб все вовремя даунгрейдить и диспозить. Другое дело, что никто так не делает, у всех в коде каша. Тотально у всех, у меня тоже. А потом делается вывод, что это транзакции виноваты. Не верю! Если б MS SQL такое позволял, он бы тоже падал когда попало как Автокад.

Оффлайн Дмитрий Загорулькин

  • ADN
  • *
  • Сообщений: 1727
  • Карма: 426
  • LISP/C#, AutoCAD/Civil 3D
  • Skype: zagor_dmtr
Re: Перебор всех объектов
« Ответ #34 : 13-10-2018, 17:32:19 »
Не верю!
Ну ок. Я поделился своим опытом. Перенимать его или нет - дело хозяйское.  ;)

Оффлайн avc

  • ADN Club
  • ****
  • Сообщений: 394
  • Карма: 72
    • Мои плагины к Автокаду
Re: Перебор всех объектов
« Ответ #35 : 13-10-2018, 17:33:52 »
Не могу не согласиться. Случаи бывают разные. А истина всегда ускользает. Продолжаем оптимизировать код.... Каждый по своему....

Оффлайн simson43Автор темы

  • ADN OPEN
  • ****
  • Сообщений: 253
  • Карма: 2
Re: Перебор всех объектов
« Ответ #36 : 13-10-2018, 22:01:40 »
Попробуйте использовать вот этот код:
Код - C# [Выбрать]
if (objId.ObjectClass.IsDerivedFrom(RXObject.GetClass(typeof(MText))))
Проблема!
внешняя ссылка для него это блок и он залазит в нее (если я ищу блоки).

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 8795
  • Карма: 1088
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Перебор всех объектов
« Ответ #37 : 14-10-2018, 02:06:56 »
Проблема!
внешняя ссылка для него это блок и он залазит в нее (если я ищу блоки).
Кто куда залазит???
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Владимир Шу

  • ADN Club
  • ****
  • Сообщений: 422
  • Карма: 97
    • ПГСу Бложик
Re: Перебор всех объектов
« Ответ #38 : 14-10-2018, 08:43:21 »
Проблема!
внешняя ссылка для него это блок и он залазит в нее (если я ищу блоки).
Почему проблема? Внешняя ссылка и есть блок, внутри автокада очень многое можно привести к блоку (таблицы, размеры, выноски и т.д.).
Если Вам не нужны XRef, то и фильтруйте их: BlockTableRecord.IsFromExternalReference

Все еще не понимаю где проблема...

Оффлайн simson43Автор темы

  • ADN OPEN
  • ****
  • Сообщений: 253
  • Карма: 2
Re: Перебор всех объектов
« Ответ #39 : 14-10-2018, 08:57:47 »
Я просто не знал что так много всего подходит под определение блока. Придется фильтровать все что не нужно.
Спасибо

Оффлайн simson43Автор темы

  • ADN OPEN
  • ****
  • Сообщений: 253
  • Карма: 2
Re: Перебор всех объектов
« Ответ #40 : 14-10-2018, 12:24:04 »
Если Вам не нужны XRef, то и фильтруйте их: BlockTableRecord.IsFromExternalReference
т е для проверки придется открыть блок через транзакцию и дополнительно получать так же через транзакцию BlockTableRecord полученного блока?
« Последнее редактирование: 14-10-2018, 14:25:15 от simson43 »

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 8795
  • Карма: 1088
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Перебор всех объектов
« Ответ #41 : 14-10-2018, 16:44:06 »
Если Вам не нужны XRef, то и фильтруйте их: BlockTableRecord.IsFromExternalReference
т е для проверки придется открыть блок через транзакцию и дополнительно получать так же через транзакцию BlockTableRecord полученного блока?
Угу.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Владимир Шу

  • ADN Club
  • ****
  • Сообщений: 422
  • Карма: 97
    • ПГСу Бложик
Re: Перебор всех объектов
« Ответ #42 : 15-10-2018, 07:41:06 »
т е для проверки придется открыть блок через транзакцию и дополнительно получать так же через транзакцию BlockTableRecord полученного блока?
Можно и так, но ИМХО, проще написать метод расширения для ObjectId и проверять сразу в условии.

Что то вроде:
Код - C# [Выбрать]
  1.     public static class BlockReferenceHelper
  2.     {
  3.         public static bool IsXRef(this Db.ObjectId id)
  4.         {
  5.             bool ret = false;
  6.             if (id.ObjectClass.IsDerivedFrom(Rtm.RXClass.GetClass(typeof(Db.BlockReference))))
  7.             {
  8.                 Db.BlockReference br = id.Open(Db.OpenMode.ForRead) as Db.BlockReference;
  9.                 Db.BlockTableRecord btr = br.BlockTableRecord.Open(Db.OpenMode.ForRead) as Db.BlockTableRecord;
  10.                 ret = btr.IsFromExternalReference;
  11.  
  12.                 br.Close();
  13.                 br.Dispose();
  14.  
  15.                 btr.Close();
  16.                 btr.Dispose();
  17.             }
  18.             return ret;
  19.         }
  20.     }

И далее уже в своем коде:
Код - C# [Выбрать]
  1. if (Id.IsXRef())
  2. {
  3.  // тут какой то свой код
  4. }

PS.
За код, особо сильно не пинайте, "чукча не писатель, чукча читатель"

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 8795
  • Карма: 1088
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Перебор всех объектов
« Ответ #43 : 17-10-2018, 17:04:18 »
PS.
За код, особо сильно не пинайте, "чукча не писатель, чукча читатель"
Всё-таки слегка "пну" по поводу Close и Dispose. Если !ObjectId.IsNull (а это наш случай), то Dispose вызывает Close. Так что вызывать и Close и Dispose не следует. Если ObjectId.IsNull то Close вызвать нельзя.
Лучше всего в этом коде использовать using:
Код - C# [Выбрать]
  1. using (Db.BlockReference br = id.Open(Db.OpenMode.ForRead) as Db.BlockReference)
  2. using (Db.BlockTableRecord btr = br.BlockTableRecord.Open(Db.OpenMode.ForRead) as Db.BlockTableRecord)
  3. {
  4.     ret = btr.IsFromExternalReference;
  5. }
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение