Категории каталога
Каталог / Бизнес / Автоматизация предприятий / 1C / Реализация одного из инструментов отладки 1С Предприятие 8.0

Реализация одного из инструментов отладки 1С Предприятие 8.0

Данная статья описывает реализацию одного из инструментов тестирования и отладки. Рассматривается это на примере идентификации внутренней структуры базы данных 1С Предприятие 8.0.(SQL) для произвольной конфигурации.

Дано : Произвольная конфигурация на базе 1С Предприятие 8.0. (SQL)

Цель : Максимально автоматизировать процесс идентификации внутренней структуры к объектам на уровне приложения.

Реализация :Для начала необходимо понять, как это можно было бы сделать вручную. Очевидно, брать в руки профайлер настраивать трейсы. Изменяя объекты приложения сопоставлять данные в трейсах с соответствующими изменениями объектов. В общем, этот процесс не сложный, но довольно таки трудоемкий и рутинный. На помощь в автоматизации этого процесса нам приходят триггера MSSQL и возможность их динамического создания. Кроме этого, имея возможность определения структуры метаданных как в 1С, так и в MS SQL(системных объектов) мы получаем весь необходимый инструментарий.

Итак, алгоритм автоматизации заключается в выполнении следующих пунктов:

1) Создаем триггера на все объекты MSSQL базы. В реализации триггера указывается запись в отдельную таблицу следующих значений : ИмяТаблицы, ИмяИзмененногоПоля, PK или уникальный индекс измененной записи, ЗначениеИзВременнойТаблицы. В переменную ЗначениеИзВременнойТаблицы будет передаваться из 1С соответствующее изменению в объекте 1С. Собственно говоря, система этих триггеров это есть фактически одна из систем логирования в БД.

2) Реализуем функцию, которая будет передавать в MSSQL значение изменения в объекте 1С. Передавать мы должны таким образом что бы затем можно было получить это значение и присвоить переменной ЗначениеИзВременнойТаблицы в вышеописанной системе триггеров.

3) Организуем циклом перебор метаданных в 1С. Производим последовательное изменение объектов 1С.Передаем в переменную ЗначениеИзВременнойТаблицы конкретное изменение объекта. Передать значение в ЗначениеИзВременнойТаблицы необходимо до выполнения команды изменяющей объект для того что бы триггер получил информацию о том какой объект 1С его вызвал и какие изменения в этом объекте произошли. Собственно говоря, в этом пункте и заключается одна из сложностей не позволяющая этот алгоритм сделать полностью универсальным. Дело в том, что 1С использует агрегацию данных и кроме этого логика изменений зависит от текущего состояния объекта. Если мы изменим, значение одного реквизита в случае, когда документ уже существует в базе и когда этот документ создается впервые в результате получим различный набор команд к SQL серверу. С агрегацией аналогичная ситуация. Предположим у нас есть два одинаковых документа с разницей по дате в год, осуществляющих линейное движение по регистрам(для упрощения без обработки всякой логики). Так вот в случае проведения первого документа мы получим одно количество изменений по агрегационным записям, а случае проведения второго другое количество.

Реализовав подобную систему на выходе, мы получим соответствие объектов 1С к объектам MS SQL. Конечно, нужно понимать, что информация в полученной таблице довольно таки сыра и потребует некоторой обработки. Кроме этого можно составить последовательность операций с метаданными и соответствующую обработку результирующей таблицы, что бы определить автоматически для этой конфигурации внутреннюю структуру данных. Неважно будем мы заново создавать или удалять эту конфигурацию, в какой последовательности создавать в конфигураторе объекты метаданных - подобная система однозначно определит соответствие. Но важно понимать следующее - для любой произвольно взятой конфигурации эта система работать не будет. Точнее она будет работать, но если для этой конфигурации придумать свою систему изменения объектов на основании метаданных и обработки результирующей таблицы. Но этого по большому счету и не нужно. Подобная система это инструмент. С помощью этого инструмента специалист довольно быстро разберется с любой интересующей его структурой.

Ниже я приведу несложный код для автоматической генерации триггеров на БД.

declare @str char(8000)declare @Table_name char(100)declare @id intdeclare @Column_name char(100)declare TableCur cursor local fast_forward for -- Декларация курсораselect [name],[id] from sysobjectswhere xtype='U' and status>0 and name<>'Log1CforSQL' -- Запрос по всем таблица в текущей БД кроме той куда пишется логopen TableCur -- Открытие крсораfetch TableCur into @Table_name,@idwhile (@@fetch_status<>-1) -- Цикл по курсоруbegin set @str='if exists (select * from dbo.sysobjects where id = object_id(N''[dbo].[TR_U_'+rtrim(@Table_name)+']'') and OBJECTPROPERTY(id, N''IsTrigger'') = 1)drop trigger [dbo].[TR_U_'+rtrim(@Table_name)+']' -- удаляем если он уже существуетexec (@str) select @str='CREATE TRIGGER [TR_U_'+rtrim(@Table_name)+'] ON [dbo].['+rtrim(@Table_name)+'] FOR UpdateAS set nocount ondeclare @Izm1CObject char(1000)select @Izm1CObject=Izm1CObject from BufferIzm1CObject where spid=@@spid 'declare ColumnCur cursor local fast_forward for select [name] from syscolumns -- Запрос по списку колонок конкретной таблицыwhere [id] = @id open ColumnCur -- Открытие курсораfetch ColumnCur into @Column_namewhile (@@fetch_status<>-1) begin select @str =rtrim(@str)+' if update('+@Column_name+')begininsert into Log1CforSQL(TableName,ColumnName,Izm1CObject,Type)values('''+rtrim(@Table_name)+''','''+rtrim(@Column_name)+''',@Izm1CObject,''U'') end'--Вообще то признак update не гарантирует того что поле изменилось(в 7.7. так и происходило)--поэтому здесь необходимо сравнивать deleted и inserted , данный вариант - некоторое упрощениеfetch ColumnCur into @Column_nameendselect @str =rtrim(@str)+' set nocount off'close ColumnCurdeallocate ColumnCur--Создание триггеров на удаление и вставку. --Если текст для создания триггера будет более 8000 символо то этот алгоритм работать не бдет--Вообще то для этих случаев необходимо создавать текст триггера через временную таблицу например-- В данном случае так реализованно для простоты пониманияexec (@str)set @str='if exists (select * from dbo.sysobjects where id = object_id(N''[dbo].[TR_D_'+rtrim(@Table_name)+']'') and OBJECTPROPERTY(id, N''IsTrigger'') = 1)drop trigger [dbo].[TR_D_'+rtrim(@Table_name)+']' -- удаляем если он уже существуетexec (@str)select @str= 'CREATE TRIGGER [TR_D_'+rtrim(@Table_name)+'] ON [dbo].['+rtrim(@Table_name)+'] FOR DELETEAS set nocount ondeclare @Izm1CObject char(1000)select @Izm1CObject=Izm1CObject from BufferIzm1CObject where spid=@@spidinsert into Log1CforSQL(TableName,ColumnName,Izm1CObject,Type) values('''+rtrim(@Table_name)+''',''ALL'',@Izm1CObject,''D'') set nocount off'exec (@str) -- создаем триггерset @str='if exists (select * from dbo.sysobjects where id = object_id(N''[dbo].[TR_I_'+rtrim(@Table_name)+']'') and OBJECTPROPERTY(id, N''IsTrigger'') = 1)drop trigger [dbo].[TR_I_'+rtrim(@Table_name)+']' -- удаляем если он уже существуетexec (@str) select @str= 'CREATE TRIGGER [TR_I_'+rtrim(@Table_name)+'] ON [dbo].['+rtrim(@Table_name)+'] FOR INSERTAS set nocount ondeclare @Izm1CObject char(1000)select @Izm1CObject=Izm1CObject from BufferIzm1CObject where spid=@@spidinsert into Log1CforSQL(TableName,ColumnName,Izm1CObject,Type) values('''+rtrim(@Table_name)+''',''ALL'',@Izm1CObject,''I'') set nocount off'exec (@str)-- создаем триггерfetch TableCur into @Table_name,@id -- Передача названия таблицы из курсора в переменную @Table_nameendclose TableCurdeallocate TableCur

 

Автор статьи - Сердюк В.И.
http://www.serduk.ru/

Материал предоставлен: Клерк.РУ

Реклама:
Где заказать рерайтинг текстов узнай на сайте eTXT.ru