Можно ли работать с Entity получив из функции

Автор Тема: Можно ли работать с Entity получив из функции  (Прочитано 13198 раз)

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

Оффлайн avc

  • ADN Club
  • *****
  • Сообщений: 805
  • Карма: 166
    • Мои плагины к Автокаду
Ну что ж. Проверил. Тестовая функция открывает объект по Id и возвращает его Layer (вполне себе полезная функциональность в 3 строки). Тестовый черетж из первых попавшихся под руку плоских объектов - 448шт.
Открываем объект на чтение.
    В одной транзакции - 0.009сек, в новых транзакциях - 0.214сек
Открываем объект на запись.
    В одной транзакции - 0.023сек, в новых транзакциях - 0.272сек
Открываем объект на запись и абортим каждую транзакцию.
    В одной транзакции - 0.012сек (странно!), в новых транзакциях - 1.713сек

Может и не катастрофа, но если так делать на каждом шагу - пользователь не обрадуется.

Оффлайн Андрей Бушман

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
вполне себе полезная функциональность в 3 строки
А без транзакций? Кроме того, не видя твоего кода сложно судить о том, насколько оптимально ты выполняешь те или иные операции.

Оффлайн avc

  • ADN Club
  • *****
  • Сообщений: 805
  • Карма: 166
    • Мои плагины к Автокаду
А без транзакций я не умею. У меня ObjectId.GetObject выдает невнятный эксцепшн
А код и смотреть нечего:
Код - C# [Выбрать]
  1.     private static string _getLayer(ObjectId id)
  2.     {
  3.       string ret;
  4.       Document doc = AcadApp.DocumentManager.MdiActiveDocument;
  5.       using (Transaction tr = doc.Database.TransactionManager.StartTransaction())
  6.       {
  7.         Entity en = tr.GetObject(id, OpenMode.ForRead) as Entity;
  8.         ret = en.Layer;
  9.         tr.Commit();
  10.       }
  11.       return ret;
  12.     }

Оффлайн Андрей Бушман

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
А без транзакций я не умею. У меня ObjectId.GetObject выдает невнятный эксцепшн
http://bushman-andrey.blogspot.ru/2013/01/database-autocad.html

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Document doc = AcadApp.DocumentManager.MdiActiveDocument;
      using (Transaction tr = doc.Database
Зачем? Есть же id.Database

Оффлайн avc

  • ADN Club
  • *****
  • Сообщений: 805
  • Карма: 166
    • Мои плагины к Автокаду

Оффлайн avc

  • ADN Club
  • *****
  • Сообщений: 805
  • Карма: 166
    • Мои плагины к Автокаду
Вот так не работает:
Код - C# [Выбрать]
  1.     [CommandMethod("VT", CommandFlags.Redraw)]
  2.     public static void VT()
  3.     {
  4.       try
  5.       {
  6.         Document doc = AcadApp.DocumentManager.MdiActiveDocument;
  7.         Editor ed = doc.Editor;
  8.         // получить предвыделенные объекты или запросить ввод
  9.         ObjectId[] sel = CnsAcad.Select("Выберите объекты для проверки", false, true);
  10.         if (sel == null) return;
  11. // первый способ
  12.         DateTime n = DateTime.Now;
  13.         string ret = "";
  14.         int counter = 0;
  15.         using (doc.LockDocument())
  16.         using (Transaction tr = doc.Database.TransactionManager.StartTransaction())
  17.         {
  18.           foreach (ObjectId id in sel)
  19.           {
  20.             Entity en = tr.GetObject(id, OpenMode.ForRead) as Entity;
  21.             ret += en.Layer; // просто так. для теста
  22.             counter++;
  23.           }
  24.           tr.Commit();
  25.           }
  26.         ed.WriteMessage("Счетчик: " + counter.ToString() + " время: " + (DateTime.Now - n).TotalSeconds.ToString());
  27.  
  28. // второй способ
  29.         n = DateTime.Now;
  30.         ret = "";
  31.         counter = 0;
  32.         using (doc.LockDocument()) // можно убрать в данном случае. ни на что не влияет
  33.         foreach (ObjectId id in sel)
  34.         {
  35.           ret += _getLayer(id);
  36.           counter++;
  37.         }
  38.         ed.WriteMessage("Счетчик: " + counter.ToString() + " время: " + (DateTime.Now - n).TotalSeconds.ToString());
  39.       }
  40.       catch (System.Exception ex) { ed.WriteMessage(ex.Message); }
  41.     }
  42.  
  43.     private static string _getLayer(ObjectId id)
  44.     {
  45.       using (Entity en = id.GetObject(OpenMode.ForRead) as Entity) // вот тут стабильно "Object reference not set to an instance of an object."
  46.         return en.Layer;
  47.     }
  48.  

Заметил, что я DateTime.Now вызывал до селекта объектов а это лишние 5мс. так что разница времени еще больше

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
А если, все же, прочитать статью Андрея? Ссылка в сообщении #19.
Еще можно мое творение глянуть:

Оффлайн avc

  • ADN Club
  • *****
  • Сообщений: 805
  • Карма: 166
    • Мои плагины к Автокаду
Перечитал статью в 6ой раз. Заметил наконец в чем прикол - вместо GetObject используется Open.
Теперь не сбоит. Хотя где-то я точно видел, что использует народ именно ObjectId.GetObject... Не сам же я такое придумал :)

Итого для открытия только на чтение:
Одна транзакция - не более 0.01сек
448 транзакций с коммитом - 0.34сек
Без транзакций вообще - 0.29сек

Вывод: для массовых процедур транзакцию надо открывать и надо передавать во все функции. Вооот

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Хотя где-то я точно видел, что использует народ именно ObjectId.GetObject... Не сам же я такое придумал
Это как раз, чтобы транзакцию не передавать во вспомогательные методы. Смотрите видео, в общем. Неохота по 100 раз одно и то же повторять :)

Оффлайн avc

  • ADN Club
  • *****
  • Сообщений: 805
  • Карма: 166
    • Мои плагины к Автокаду
Ну а разница между явными транзакциями и скрытыми не столь велика, что б на нее ориентироваться. Меня слегка напрягает, что Open помечен 'ObjectId.Open(OpenMode)" является устаревшим: 'For advanced use only. Use GetObject instead'. Есть же какая-то причина, что его так пометили


Оффлайн avc

  • ADN Club
  • *****
  • Сообщений: 805
  • Карма: 166
    • Мои плагины к Автокаду
Неохота по 100 раз одно и то же повторять
Самое обидное, что я это знал, читал, но напроч забыл, т.к. ни разу не использовал. Ну не удержать все в голове, извиняйте...

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Так можно еще по форуму поискать. Эта тема уже довольно избита. И Александр Наумович и Андрей Андреевич здесь уже несколько раз на подобные вопросы отвечали.

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
А без транзакций я не умею. У меня ObjectId.GetObject выдает невнятный эксцепшн
Это тоже самое, что с транзакцией, но используется TopTransaction. Если ни одна транзакция не запущена - то само-собой возникнет исключение.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Меня слегка напрягает, что Open помечен 'ObjectId.Open(OpenMode)" является устаревшим: 'For advanced use only. Use GetObject instead'. Есть же какая-то причина, что его так пометили
Разницу между устаревшим и "For advanced use only" чувствуешь? Если на каждый Open не будет Close - гарантированный Fatal Error. Поэтому в большистве случаев используется конструкция типа
Код - C# [Выбрать]
  1. using (Entity en = id.Open(...) as Entity)
  2. {
  3.   // Здесь работаем с en
  4. }
en.Dispose при завершении using автоматом вызывает en.Close
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение