|
|
|||||||||||||||||||||||||||||
|
Дополнительный инструмент для работы с базой данных чертежаИсточник: bushmansnetlaboratory
В процессе работы над чертежом порой возникают ситуации, когда для получения нужного набора примитивов необходимо выполнить итерацию по всей базе данных документа и выбрать такие объекты, которые отвечают некоторому, обозначенному нами условию, или же требуется выполнить определённое действие над любым, нужным нам набором примитивов имеющимся в чертеже объектами. Например, нам может потребоваться прочитать имеющиеся у всех имеющихся объектов их расширенные данные (XRecord). Или же требуется выбрать такие элементы, которые для своего отображения используют некий, интересующий нас текстовый стиль. Итерация по всей базе данных требуется не так часто, однако порой без неё либо не обойтись, либо иные решения могут оказаться более сложными в плане их реализации.
В данной статье будет создан статический класс, содержащий в себе методы расширения для класса Autodesk.AutoCAD.DatabaseServices.Database. Сразу хочу акцентировать внимание на том, что использовать обозначенный функционал рекомендуется к месту (см. ниже разделы о целесообразности/нецелесообразности использования), а не применять везде подряд, т.к. порой процесс итерации по базе данных может оказаться затратным по времени.
Примечание Справедливости ради замечу, что при разовом использовании падение производительности будет не существенное (на извлечение 700 000 объектов уходит около 0,5 секунды для чертежа, объёмом 51 Мб), но если использовать его везде где можно, то в результате по полсекунды может набраться ощутимое падение скорости. Назначение класса Класс предназначен для извлечения информации из базы данных чертежа и, в случае необходимости, редактирования существующих в ней объектов. В реализации всех методов из обработки исключаются объекты, идентификаторы которых отвечают хотя бы одному из перечисленных ниже условий:
Я умышленно устанавливаю такие ограничения, т.к. это своего рода защита от ошибки, которая может возникнуть в случае использования некорректного ObjectId.
Целесообразность использования Некоторые методы интерфейса, выполняющие итерацию по БД, целесообразно использовать в таких случаях, когда нужный набор объектов невозможно получить, не выполнив итерации по всей базе данных чертежа, либо иные решения могут оказаться более сложными в плане их реализации. Прочие методы, выполняющие работу над определённым набором объектов, могут применяться везде, где это удобно разработчику.
Пример нецелесообразного использования Например, если нужно получить перечень всех имеющихся листов (Layouts) чертежа, то использовать для этого методы, обозначенные в Bushman.AutoCAD.Common.IDBSearcher и выполняющие итерацию по всей БД можно, но это не будет целесообразным решением, т.к. в этом случае процесс выборки нужного набора займёт больше времени, чем если выполнить запрос напрямую из таблицы Autodesk.AutoCAD.DatabaseServices.BlockTable, считав нужные записи Autodesk.AutoCAD.DatabaseServices.BlockTableRecord. Дело в том, что Bushman.AutoCAD.Common.IDBSearcher в цикле перебирает все примитивы базы данных, причём чем больше примитивов в базе данных, тем дольше будет выполняться поиск (что собственно и логично), в то время как непосредственная итерация по записям Autodesk.AutoCAD.DatabaseServices.BlockTableRecord выполнится быстрее (см. примечание в начале страницы).
Пример целесообразного использования Например, если требуется получить все объекты, использующие текстовый стиль (т.е. однострочный/многострочный текст, атрибуты, размерные стили, стили мультивыносок, размеры, мультивыноски, табличные стили, таблицы, типы линий и т.д.). Это может потребоваться например тогда, когда нужно переназначить таким объектам другой текстовый стиль, а старый удалить. Поскольку в AutoCAD существует множество классов, использующих текстовый стиль и их объекты хранятся в разных местах БД, с разными уровнями вложенности, то последовательная итерация по всем объектам чертежа оправдана и соответственно использование Bushman.AutoCAD.Common.IDBSearcher целесообразно.
Определяемся с набором нужного функционала Для начала давайте определимся с необходимым нам функционалом. Итак, мною был сформирован следующий набор пожеланий:
Теперь давайте напишем код придуманного нами выше интерфейса.
Код интерфейса IDBSearcher
Обратите внимание на то, что методу GetAllObjects в качестве параметра передаётся экземпляр DBObjectStatus - это перечисление, написанное нами для удобства. Код перечисления такой:
Код DBObjectStatus
Теперь необходимо написать реализацию интерфейса IDBSearcher. Забегая вперёд хочу отметить, что мы рассмотрим три способа проверки ObjectId на предмет его существования в Database. Поэтому сначала нами будет создан абстрактный класс DBSearcher, реализующий интерфейс IDBSearcher, а уже на его основе мы построим несколько классов, выполняющих одну и ту же задачу, но отличающиеся друг от друга только способом проверки на валидность.
Для чего это делается, зачем нам писать несколько вариантов решения? Дело в том, что мы проанализируем все варианты и выберем тот, который обладает наибольшей производительностью. Наличие промежуточного звена в виде абстрактного класса DBSearcher обусловлено желанием вынести общий код в одно место, дабы не дублировать его во всех конечных реализациях. Кроме того, если нам потребуется внести изменение, которое должно отразиться на всех наших вариантах, то достаточно будет внести это изменение в одном месте и оно будет подхвачено везде. Итак, давайте приступим к написаниюDBSearcher.
Ссылки по теме
|
|