| Реалізація одного з інструментів налагодження 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 int declare @Column_name char(100) declare TableCur cursor local fast_forward for -- Декларація курсору select [name],[id] from sysobjects where xtype='U' and status>0 and name<>'Log1CforSQL' -- Запит по всім таблиця в поточної БД крім тієї куди пишеться балка open TableCur -- Відкриття крсора fetch TableCur into @Table_name,@id while (@@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 Update AS set nocount on declare @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_name while (@@fetch_status<>-1) begin select @str =rtrim(@str)+' if update('+@Column_name+') begin insert 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_name end select @str =rtrim(@str)+' set nocount off' close ColumnCur deallocate 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 DELETE AS set nocount on declare @Izm1CObject char(1000) select @Izm1CObject=Izm1CObject from BufferIzm1CObject where spid=@@spid insert 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 INSERT AS set nocount on declare @Izm1CObject char(1000) select @Izm1CObject=Izm1CObject from BufferIzm1CObject where spid=@@spid insert 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_name end close TableCur deallocate TableCur
Автор статті - Сердюк В.І. |
| « Пред. | След. » |
|---|


