Как наиболее правильно и безопасно применять?Второй вариант. Первый вариант совсем небезопасный, так еще и неграмотно записан и .Dispose() не нужен. Это тоже самое что дважды вызвать .Close()
Нужно ли выполнять Commit для такой транзакции, если объекты не изменяются?Во втором варианте у тебя нет никакой транзакции, так что .Commit() не нужен. Да и кому ты будешь его делать?
А ограничения какие-то должны быть, потому что, когда я просто изменил в своем коде Transaction на OpenCloseTransaction, а StartTransaction на StartOpenCloseTransaction, у меня программа стала вызывать фатальную ошибку в AutoCAD (Civil 3D - может это важно). Вернул все обратно - ошибка пропала. Причем в режиме отладки эта ошибка не отлавливается :(Скорее всего у тебя что-то в коде некорректно.
Да и кому ты будешь его делать?Не знаю... Метод есть же :)
Не знаю... Метод есть же :)Метод есть у транзакции, а транзакции у тебя нет!
Commit вообще не надо использовать, или не надо использовать только когда не меняю объектов?Commit - это метод транзакции. У Entity/DBObject таких методов нет.
Метод есть у транзакции, а транзакции у тебя нет!Андрею надо поправить пример 3.1 http://bushman-andrey.blogspot.ru/2013/01/database-autocad.html?
Скорее всего у тебя что-то в коде некорректно.Там было внутри использование еще одной транзакции во вспомогательном методе. Я ее тоже заменил на OpenCloseTransaction, ошибка больше не выскакивает. Получается, что совместное использование OpenCloseTransaction и Transaction может приводить к конфликтам?
Commit - это метод транзакции. У Entity/DBObject таких методов нет.Я имел в виду, нужно ли вызывать этот метод для OpenCloseTransaction?
Из примеров:Спасибо! Буду изучать/пробовать.
Я имел в виду, нужно ли вызывать этот метод для OpenCloseTransaction?В этом случае - да. Но код второго примера у тебя без транзакции - на это я и отвечал.
Получается, что совместное использование OpenCloseTransaction и Transaction может приводить к конфликтам?Да. Так лучше не делать.
Андрею надо поправить пример 3.1 http://bushman-andrey.blogspot.ru/2013/01/database-autocad.html?Там всё в порядке - у него есть транзакция.
Андрею надо поправить пример 3.1 http://bushman-andrey.blogspot.ru/2013/01/database-autocad.html?Какая хорошая статья! Почему-то я ее поиском не нашел, хотя помнил, что у Андрея что-то такое было... Спасибо!
Еще, похоже, что метод ObjectId.GetObject не работает, если запущена не транзакция, а ее эмуляция с помощью OpenCloseTransaction.Да. ObjectId.GetObject требует чтобы была запущена реальная транзакция.
Интересно, Вы это опытным путем установили (255 открывали на чтение? :) ) или где-то есть материалы по этому вопросу?Autodesk ObjectARX for AutoCAD 20XX: Developer Guide->ObjectARX Introductory Concepts->Database Objects->Opening and Closing Database Objects
И можно ли как-то проверить, что объект уже открыт на чтение или запись?Да:
А нет ли случайно каких-то ограничений по использованию методов UpgradeOpen и SwapIdWith при открытии объектов без транзакции?У тебя возникла проблема? Тогда уточни какая. Возможно она комплексная.
Получается, что если объект открыт на чтение или запись без использования транзакции, то метод SwapIdWith выдает ошибку (тот объект, id которого используется как аргумент otherId). Сейчас проверяю эту мысль.Ну вообще-то этот объект должен быть закрыт. Обычное правило - если передается ObjectId, то объект должен быть закрыт.
Обычное правило - если передается ObjectId, то объект должен быть закрыт.Спасибо, учту на будущее!
А с обычной транзакцией "прокатывало" подсунуть ObjectId открытого объекта :)Обычная транзакция разбаловала программистов. Но иногда это выходит боком так, что найти причину бага становится очень непростой проблемой.
Не обязательно, т.к.:Я имел в виду, нужно ли вызывать этот метод для OpenCloseTransaction?В этом случае - да.
Обратите внимание, что у Transaction и у OpenCloseTransaction похожее использование, но разное действие по умолчанию:
у Transaction, по умолчанию вызывается метод Abort(), тем самым отменяя все изменения, а у OpenCloseTransaction по умолчанию вызывается метод Close(), тем самым наоборот - сохраняя все выполненные изменения.
Надо же какое совпадение! Сегодня часа 2 бился над проблемой - почему Civil 3D валится на определенной операции. В итоге, добавление метода Commit в транзакцию (а точнее - обеспечение его 100% вызова в любой ситуации) решило проблему.Видеодемонстрация (видео длинное получилось, т.к. загружается Civil небыстро):https://screencast.autodesk.com/main/details/fec694d8-ab7e-4793-a262-d8feb3ae6680
1. Вложенный блок using (в которой инициализируеся pView) здесь лишний.А вот это точно.
Ха. Хотя я был уверен, что Андрей Бушман прав, но оказалось что это не так.Обозначенную информацию я взял не с потолка, а из блогов Автодеск. Вы хотите сказать не "сделали", а "переделали"? Если "да", то в какой версии Автокада это произошло. Сам проверить не могу, т.к. в ближайшие несколько дней доступа к Автокаду у меня нет.
...
Т.е. поведение OpenCloseTransaction сделали подобным поведению обычной Transaction.
Уберу эту конструкцию, хотя, думаю, что на работе кода это никак не скажется.Это 100% лишняя конструкция, которая приводит или к повторному .Close объекта или к последовательному вызову .Abort, а затем .Close объекта, что мягко говоря плохо.
Т.е. поведение OpenCloseTransaction сделали подобным поведению обычной TransactionСейчас проверил в 2009-м Acade - поведение аналогичное. Ищу в Интернете источник информации, где я прочитал об этом "отличии"...
Обратите внимание, что у Transaction и у OpenCloseTransaction похожее использование, но разное действие по умолчанию:Зачёркнута ошибочная информация, выяснилось здесь (http://adn-cis.org/forum/index.php?topic=940.msg4166#msg4166).
у Transaction, по умолчанию вызывается метод Abort(), тем самым отменяя все изменения, а у OpenCloseTransaction по умолчанию вызывается метод Close(), тем самым наоборот - сохраняя все выполненные изменения.
Может такое быть?Да. И именно потому что:
внутри метода, где используется StartOpenCloseTransaction() вызывается метод где используется StartTransaction().Возьми себе за правило:
Вызов метода из метода считается вложением?Нет конечно. Вложенная транзакция, это когда одна транзакция уже работает, а ты в это время создаёшь новую.
2) Не использовать вложенные OpenCloseTransaction.А если я использую вложенные только для открытия на чтение?
А если я использую вложенные только для открытия на чтение?Правильный подход! :) Если уровень вложенности не превышает 255 (эту цифру мы уже с тобой обсуждали), то всё нормально.
Замени:Пробывал, результат один - StartTransaction() - работает, StartOpenCloseTransaction() - не работает
1)Код - C# [Выбрать]на
BlockTable bt = (BlockTable)acDb.BlockTableId.GetObject(OpenMode.ForWrite);Код - C# [Выбрать]2)
BlockTable bt = (BlockTable)acDb.BlockTableId.GetObject(OpenMode.ForRead);Код - C# [Выбрать]на
BlockTableRecord btrFind = (BlockTableRecord)bt[name].GetObject(OpenMode.ForWrite);Код - C# [Выбрать]
BlockTableRecord btrFind = (BlockTableRecord)bt[name].GetObject(OpenMode.ForRead);
Строки #11 и #20 в коде и сообщения #12 и #13 в этой теме ;)А это в моей ситуации самое разумное объяснение
А это в моей ситуации самое разумное объяснениеДа. Я как-то не обратил внимание. Тем не менее исправить нужно и то, и другое.
StartOpenCloseTransaction() в несколько раз шустрее чем StartTransaction()Ой ли? Зависит от конкретной ситуации.
Андрей, как продвигается идея с написанием книги по AutoCAD .Net API? Лично у меня она стала бы настольной.Да я вроде как и не собирался этого делать. Опубликованный мною опрос лишь выявил, что интерес к книгам по данной теме стремится практически к нулю.
Там есть и глава по AutoCAD .NET API. Если бы позволял объём страниц и время, то можно было бы включить туда и материал по модульному, а так же автономному тестированию .NET плагинов AutoCAD с использованием Gallio и NUnit но в виду обозначенных ограничений материал остался за бортом.А я вот, все надеюсь на статью по этой теме...
А я вот, все надеюсь на статью по этой теме...Материал есть, всё никак "руки не дойдут" до его оформления.
Интересно, почему так?Думаешь без подготовленного тестового примера с этим можно разобраться? ;)
Но это же что получается, из транзакции одной базы получаем объект другой базы? Как такое возможно?А как возможно, что в событии одной базы (sender as Database) в качестве исходной фигурирует совсем другая база (e.IdMapping.OriginalDatabase) ? ;)
Вообще, хороший вопрос, какая из двух баз (исходная или целевая) генерирует это событие?Генерирует та, которая sender
А я вот, все надеюсь на статью по этой теме...Пример исходного кода модульных тестов, компилирующихся для платформ Gallio и NUnit выложен здесь (http://bushman-andrey.blogspot.ru/2015/03/testcase-nunit-gallio.html). Там же дана и ссылка на архив с HTML-файлами отчётов, автоматически сгенерированных в процессе пакетного запуска тестов в AutoCAD 2009-2015.
Прочитав первый раз мало что понял. Видимо еще не дорос. Буду изучать.Я не запрещаю задавать конструктивные вопросы по теме. :) Хорошую книгу о том, как грамотно создавать автономные и интеграционные тесты, в т.ч. и под такие закрытые системы как AutoCAD, я указывал здесь (http://adn-cis.org/forum/index.php?topic=400.0), в п.21.