|
Обмен с внешней MySQL (решено) | ☑ | ||
---|---|---|---|---|
0
Gsoom2010
30.01.13
✎
19:56
|
Около года назад ( v8: Синхронизация с внешней MySQL ) я потратил массу времени на поиск ответа на вопрос как связать 1С и MySQL. В результате поисков использовал костыль о котором писать не имеет смысла. На днях как мне кажется подобрал не плохое решение этого вопроса, надеюсь кому-нибудь пригодится.
|
|||
1
Gsoom2010
30.01.13
✎
19:56
|
Алгоритм работы следующий:
План обмена регистрирует новые данные, процедура в плане обмена выбирает новые данные, выполняет прямое подключение к MySQL и выполняет запросы. После выполнения запросов происходит сброс регистрации для объектов. Для подключения к MySQL использована внешняя компонента v7mysql.dll В моём примере представлена односторонняя загрузка данных в MySQL, при необходимости реализация обратного процесса не составит труда. В моём примере я не стал использовать пакетную загрузку запросов через INSERT INTO VALUES по той причине, что для моей задачи контроль исполнения каждого запроса гораздо важнее скорости их выполнения. План обмена содержит реквизиты: Сервер Логин Пароль Порт БД В MySQL у объектов есть поля вида ref или registrar_ref, они содержат идентификаторы объектов 1С. Для документов и справочников поле ref - PRIMARY KEY. Для элементов регистра сведений поле id - AUTO INCRIMENT PRIMARY KEY. |
|||
2
Gsoom2010
30.01.13
✎
19:57
|
Собственно сама процедура из модуля плана обмена:
// Процедура выполняет обмен данными с удалённой MsSQL для выбранного узла Процедура WebВыполнитьСинхронизацию(УзелОбмена) Экспорт Сообщить("<============================================================>"); Сообщить("" + ТекущаяДата() + " - WEB синхронизация для узла: " + Строка(ЭтотОбъект) + ""); // Загружаем компоненту Попытка ЗагрузитьВнешнююКомпоненту("v7mysql.dll"); Исключение Сообщить("Ошибка! Не обнаружена компонента v7mysql.dll!"); Возврат; КонецПопытки; // Создаём временную таблицу для парсинга и обработки запросов к объекту ТаблицаОбъектов = Новый ТаблицаЗначений; // Содержит ссылку на объект обмена ТаблицаОбъектов.Колонки.Добавить("Объект"); // Содержит массив SQL запросов ТаблицаОбъектов.Колонки.Добавить("МассивЗапросов"); ////////////////////////////////////// // Парсинг объектов плана обмена // ////////////////////////////////////// ВремяПарсингаНачало = ТекущаяДата(); // Получаем изменения в узле ВыборкаИзменений = ПланыОбмена.ВыбратьИзменения(УзелОбмена, УзелОбмена.НомерОтправленного + 1); ТипДанныхУдаления = Тип("УдалениеОбъекта"); // Перебираем элементы плана обмена Пока ВыборкаИзменений.Следующий() Цикл // В массиве харянятся запросы для объекта МассивЗапросов = Новый Массив; // Получаем измененный элемент Данные = ВыборкаИзменений.Получить(); // Данные должны существовать Если Данные = Неопределено Тогда Продолжить; КонецЕсли; // Проверяем объект на удаление ЭтоУдаление = (ТипДанныхУдаления = ТипЗнч(Данные)); // Получаем объект Если ЭтоУдаление тогда Объект = Данные.Ссылка; Иначе Объект = Данные; КонецЕсли; // Определяем тип объекта МетаданныеОбъекта = Объект.Метаданные(); // Заполняем массив запросов для объекта Попытка // Документ (один объект один документ) Если МетаданныеОбъекта = Метаданные.Документы.ИмяДокумента тогда Если ЭтоУдаление тогда МассивЗапросов.Добавить("DELETE FROM `" + БД + "`.`tablename1` WHERE `ref` = '" + Объект.Ссылка.УникальныйИдентификатор() + "'"); Иначе ЧастьЗапроса = "`number` = '" + СокрЛП(СтрЗаменить(Объект.Номер, "'", "")) + "'"; МассивЗапросов.Добавить("INSERT INTO `" + БД + "`.`tablename1` SET `ref` = '" + Объект.Ссылка.УникальныйИдентификатор() + "' , " + ЧастьЗапроса + " ON DUPLICATE KEY UPDATE " + ЧастьЗапроса); КонецЕсли; // Регистр сведений (один объект множество строк регистра)(сперва очищаем по регистратору, потом пишем). ИначеЕсли МетаданныеОбъекта = Метаданные.РегистрыСведений.ИмяРегистра тогда Регистратор = Объект.Отбор.Регистратор.Значение.УникальныйИдентификатор(); // Для регистров сведений необходимо делать очистку по регистратору МассивЗапросов.Добавить("DELETE FROM `" + БД + "`.`tablename2` WHERE `registrar_ref` = '" + Регистратор + "'"); Если Данные.Количество() > 0 Тогда Для каждого Строка из Объект цикл МассивЗапросов.Добавить("INSERT INTO `" + БД + "`.`tablename2` SET `registrar_ref` = '" + Регистратор + "' , `date` = '" + Формат(Дата(Строка.Период), "ДФ=ггггММддЧЧммсс") + "'"); КонецЦикла; КонецЕсли; // Справочник (один объект одна запись) ИначеЕсли МетаданныеОбъекта = Метаданные.Справочники.ИмяСправочника тогда Если ЭтоУдаление тогда МассивЗапросов.Добавить("DELETE FROM `" + БД + "`.`tablename3` WHERE `ref` = '" + Объект.Ссылка.УникальныйИдентификатор() + "'"); Иначе ЧастьЗапроса = "`name` = '" + Объект.НаименованиеПолное + "'"; МассивЗапросов.Добавить("INSERT INTO `" + БД + "`.`tablename3` SET `ref` = '" + Объект.Ссылка.УникальныйИдентификатор() + "' , " + ЧастьЗапроса + " ON DUPLICATE KEY UPDATE " + ЧастьЗапроса); КонецЕсли; Иначе Сообщить(" Объект не инициализирован для парсинга запросов: " + МетаданныеОбъекта); Продолжить; КонецЕсли; Исключение Сообщить(" Ошибка парсинга объекта <" + Объект + "> (" + МетаданныеОбъекта + "): " + ОписаниеОшибки()); Продолжить; КонецПопытки; // Добавляем в таблицу новый объект и запросы к нему ЗаписьОбъекта = ТаблицаОбъектов.Добавить(); ЗаписьОбъекта.Объект = Объект; ЗаписьОбъекта.МассивЗапросов = МассивЗапросов; КонецЦикла; ВремяПарсинга = ТекущаяДата() - ВремяПарсингаНачало; ////////////////////////////////////// // Синхронизация с удалённой MySQL // ////////////////////////////////////// ВремяСинхронизацииНачало = ТекущаяДата(); Если ТаблицаОбъектов.Количество() > 0 тогда // Пытаемся открыть соединение с MySQL Попытка MySQLConnection = Новый("AddIn.MySQLConnection"); MySQLConnection.Сервер = Сервер; MySQLConnection.Пользователь = Логин; MySQLConnection.Пароль = Пароль; MySQLConnection.Порт = Порт; MySQLConnection.БазаДанных = БД; MySQLConnection.НужноПереустановитьСоединение = 1; MySQLConnection.ИспользоватьСжатие = 1; MySQLConnection.ИспользоватьНовыеПароли = Истина; Если MySQLConnection.УстановитьСоединение() = 1 тогда Сообщить(" " + ТекущаяДата() + " - Соединение с MySQL установлено."); Иначе Сообщить(" Не удалось установить соединение с MySQL: " + MySQLConnection.ПоследняяОшибка()); Возврат; КонецЕсли; Исключение Сообщить(" Ошибка соединения с MySQL: " + ОписаниеОшибки()); Возврат; КонецПопытки; // Проверяем открытие соединения Если MySQLПроверкаСоединения(MySQLConnection)=Ложь тогда Сообщить(" Не установлено соединение с MySQL: " + MySQLConnection.ПоследняяОшибка()); Возврат; КонецЕсли; // Перебираем объекты которые вошли в таблицу объектов для синхронизации Для каждого ОбъектСинхронизации из ТаблицаОбъектов цикл Попытка // Пытаемся выполнить запросы для объекта ОшибкаСинхронизацииОбъекта = Ложь; Для каждого SQLЗапрос из ОбъектСинхронизации.МассивЗапросов цикл Если НЕ MySQLConnection.ВыполнитьЗапрос(SQLЗапрос) тогда Сообщить(" | Ошибка выполнения SQL запроса для объекта <" + ОбъектСинхронизации.Объект + "> | |- Ошибка: " + MySQLConnection.ПоследняяОшибка() + " | |- Запрос: " + SQLЗапрос); ОшибкаСинхронизацииОбъекта = Истина; Прервать; КонецЕсли; КонецЦикла; // Сброс регистрации для объекта происходит только если вся пачка запросов была выполнена без ошибок Если ОшибкаСинхронизацииОбъекта = Ложь тогда ПланыОбмена.УдалитьРегистрациюИзменений(Ссылка, ОбъектСинхронизации.Объект); КонецЕсли; Исключение Сообщить(" Ошибка выполнения SQL запросов для объекта <" + ОбъектСинхронизации.Объект + ">: " + ОписаниеОшибки()); Продолжить; КонецПопытки; КонецЦикла; // Закрываем соединение с MySQL MySQLConnection.ЗакрытьСоединение(); Сообщить(" " + ТекущаяДата() + " - Cоединение с MySQL закрыто."); Иначе Сообщить(" Нет объектов для синхронизации."); КонецЕсли; ВремяСинхронизации = ТекущаяДата() - ВремяСинхронизацииНачало; // Сообщаем итоги о времени выполнения парсинга и синхронизации Сообщить(" Время парсинга: " + Число(ВремяПарсинга) + " сек. | Время синхронизации: " + Число(ВремяСинхронизации) + " сек."); КонецПроцедуры Функция MySQLПроверкаСоединения(Соединение) Если Соединение.Подключен() тогда Если Соединение.ПроверитьСоединение() Тогда Возврат Истина; Иначе Возврат Ложь; КонецЕсли; Иначе Возврат Ложь; КонецЕсли; КонецФункции Ну и возможно пригодятся функции и процедуры из основной формы объекта плана обмена: Перем РегистрацияВНовыйУзел; Процедура ПередЗаписью(Отказ) РегистрацияВНовыйУзел = ЭтоНовый(); КонецПроцедуры Процедура ПриЗаписи(Отказ) Если РегистрацияВНовыйУзел Тогда // Регистрация изменений всех данных для узла ПланыОбмена.ЗарегистрироватьИзменения(Ссылка); КонецЕсли; КонецПроцедуры Процедура ОсновныеДействияФормыСинхронизировать(Кнопка) ЭтотОбъект.WebTrackingВыполнитьСинхронизацию(Ссылка); КонецПроцедуры Процедура ОсновныеДействияФормыСбросРегистрации(Кнопка) ПланыОбмена.УдалитьРегистрациюИзменений(Ссылка); КонецПроцедуры Процедура ОсновныеДействияФормыПолнаяРегистрация(Кнопка) ПланыОбмена.ЗарегистрироватьИзменения(Ссылка); КонецПроцедуры |
|||
3
Kreont
30.01.13
✎
20:04
|
Красиво, подпишусь.
Хорошо что фото товаров не надо передавать, повезло :) |
|||
4
Gsoom2010
30.01.13
✎
20:05
|
Дальше я буду прикручивать рендеринг документов из 1С к этому обмену и заливку файлов на Amazone S3... Так что всё впереди!
|
|||
5
Gsoom2010
30.01.13
✎
20:25
|
(3) А фото товаров можно отдельным блоком грузить через ftp, например после парсинга.
|
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |