COM соединение с базой

Автор SnakePlisskin, 29 августа 2025, 16:43

« назад - далее »

SnakePlisskin

Доброго дня, господа!
Сложилась такая ситуация, что нужно в базу 8, перегрузить справочник номенклатура, из базы на 7.7, причем делать это в регламентном задании на стороне 8 (клиент-серверная), после первоначальной загрузки в последующих "синхронизациях" нужно проверять на изменение наименования / полного наименования. Честно говоря раньше с такими задачами не сталкивался.

накидал вот такой код

    V77 = Новый COMОбъект("V77.Application");
    Запрос = V77.CreateObject("Запрос");
    ТекстЗапроса=

    "//{{ЗАПРОС(Сформировать)
    |Обрабатывать НеПомеченныеНаУдаление;
    |Номенклатура = Справочник.Номенклатура.ТекущийЭлемент;
    |Код = Справочник.Номенклатура.Код;
    |Наименование = Справочник.Номенклатура.Наименование;
    |Родитель = Справочник.Номенклатура.Родитель.Наименование;
    |РодительКод = Справочник.Номенклатура.Родитель.Код;
    |Группировка Номенклатура;
    |";//}}ЗАПРОС
   
    Если Запрос.Выполнить(ТекстЗапроса)=0 Тогда
        ОбщегоНазначения.СообщитьОбОшибке("Ошибка выпонения запроса номенклатуры в базе-источнике");
        Возврат;
    КонецЕсли;
   
    Таблица = Новый ТаблицаЗначений;
    Таблица.Колонки.Добавить("Код",,,15);
    Таблица.Колонки.Добавить("Наименование",,,50);
    Таблица.Колонки.Добавить("Родитель",,,50);   
    Таблица.Колонки.Добавить("РодительКод",,,15);
    Таблица.Колонки.Добавить("ЭтоГруппа",,,1);
   
    Пока Запрос.Группировка() Цикл
        Строка = Таблица.Добавить();
        Строка.ЭтоГруппа    = Запрос.Номенклатура.ЭтоГруппа();
        Строка.Код          = Запрос.Код;
        Строка.Наименование = Запрос.Наименование;
        Строка.Родитель     = Запрос.Родитель;
        Строка.РодительКод  = Запрос.РодительКод;
    КонецЦикла;   
    V77 = "";

Но это только заполнение таблицы для последующей ее обработки, 36 тысяч элементов, заполняется почти 4 минуты, можно ли как то ускорить, хотя как, я особо не понимаю, но все же. Плюс может есть-какой то другой путь решения задачи ?

Злоп

Группировка номенклатура без групп без упорядочивания
.
Тз = создатьобьект("таблицазначений")
Запрос.выгрузить(таблицазначений,....)

Злоп

Н хрена непонятно про изменение наименования. Где может происходить - только на стороне 77? Если номенклатура в 77 изменяется !!! Только интерактивно!!! Заведи в спр. Номенклатура флаг с сортировка=1, при изменении взводи его, в запросе фильтруй по условию флаг=взведен, после отработки регзадания в конце его сбрасывай в 77 флаг. Первый регламент отработает медленно, остальные будут быстро.
При сбросе флага делай в транзакции по например 10 элементов, чтобы если какой дятел держит номенклатуру открытой - чтобы не сломалось. Сброс флага делай в попытке. Если очередная порция не прошла в транзакции - да и хрен с ней, при следующем регламенте пройдёт.
.
Или контроль изменений номенклатуры регистрируй штатно с использованием УРБД. Регламент будет подчищать таблицу изменений. Можно без урбд, служебный справочник изменений куда писать ссылку на номенклатуру которая изменилась и запрос только по этому списку.
.
Ну или проще всего прямым запросом

Злоп

Если база файловая - с использованием 1sqlite прямой запрос. Ну и скульную базу тоже можно прямым запросом.
Ускорение на 1-2 порядка будет.

Злоп

А если еще между регламентами закешировать verstamp элементов справочника и в прямом запросе фильтровать к отбору по несовпадающим верстамп (он у элемента меняется при каждой модификации) то вообще время мизер будет

Злоп

В 77 поставить по умолчанию режим открытия "для просмотра" ибо нехер открыть, посмотреть и жать ОК.

Злоп

Это я так, в порядке дежурного бреда накидал, топая пешком домой.
Гуры и сенсейбабаи поправят.

Злоп

Изменения наименования/полного наименования я бы вообще контролировать забил. Чек только на изменение элемента как факт.

Злоп

Если номенклатура (наименования) может меняться на двух сторонах - ССЗБ.
Схемы примерно те же самые с добавкой контроля изменений на снеговике

vladmenleo

ВЫбросить нафиг ком соединение, делать через файл, самое простое dbf. На стороне 7.7 выгружаешь роботом по расписанию каждую ночь к примеру, а на стороне 8-ки загружаешь из файла. Работает такое  фиг знает сколько лет и хлеба не просит. Чтобы уменьшить объем, у нас в номенклатуре 7.7 есть спецполе дата последнего редактирования, и в выгрузку выгружаем только измененные за последние несколько дней

SnakePlisskin

ЗЛОП - спасибо за ответы.
Базы обе SQL правда лежат на разных серверах, прямые запросы в клюшках умею, а как из снеговика добраться до базы SQL 7.7 не умею...буду благодарен за пример.

А почему Группировка номенклатура без групп без упорядочивания - как тогда структуру справочника повторить если групп не будет ?


vladmenleo - чета dbf - совсем как то по олдскульному, но тоже как вариант.

vladmenleo

Ну не хочешь по олдскульному, юзай xml к примеру. Хозяин барин  ;D

Злоп

Цитата: SnakePlisskin от 30 августа 2025, 08:39ЗЛОП - спасибо за ответы.
чета dbf - совсем как то по олдскульному, но тоже как вариант.
Дбф читается очень быстро

ADirks

Например (ADODB):
(ТекстЗапроса - нормальный SQL-запрос)

Функция СоединениеСКЛ(ИмяСервера, ИмяПользователя, ПарольПользователя, ИмяБазы = "") Экспорт
	Если НЕ ЗначениеЗаполнено(ИмяСервера) Тогда
		Возврат Неопределено;
	ИначеЕсли НЕ ЗначениеЗаполнено(ИмяПользователя) Тогда
		Возврат Неопределено;
	КонецЕсли;

	
	ConnectionString = "Driver={SQL Server Native Client 11.0};Server="+ИмяСервера+";uid="+ИмяПользователя;
	Если НЕ ПустаяСтрока(ПарольПользователя) Тогда
		ConnectionString = ConnectionString + ";pwd="+ПарольПользователя;
	КонецЕсли; 
	Если ИмяБазы <> "" Тогда
		ConnectionString = ConnectionString + ";Database="+ИмяБазы;
	КонецЕсли; 
	
	СоединениеСКЛ = Новый  COMОбъект("ADODB.Connection");
	СоединениеСКЛ.ConnectionTimeout	= 5;
	СоединениеСКЛ.CommandTimeout	= 0;
	СоединениеСКЛ.CursorLocation	= 3;
	СоединениеСКЛ.Provider			= "MSDASQL";
	СоединениеСКЛ.ConnectionString	= ConnectionString;
	Попытка
		СоединениеСКЛ.Open();
	Исключение
		Сообщить(ОписаниеОшибки());
		СоединениеСКЛ = Неопределено;
	КонецПопытки;
	

	Возврат СоединениеСКЛ;
КонецФункции


Функция ВыполнитьИнструкцию(Соединение, ТекстЗапроса)  Экспорт
	ТЗ = Новый ТаблицаЗначений;
	
	Если Соединение = Неопределено Тогда
		Сообщить("Соединение не установлено", СтатусСообщения.Внимание);
		Возврат Неопределено;
	КонецЕсли;
	
	cmd = Новый COMОбъект("ADODB.Command");
	cmd.CommandTimeout = 0;
	cmd.ActiveConnection = Соединение;    
	cmd.CommandText = ТекстЗапроса;
	
	rs = cmd.Execute();
	
	Fields = Rs.Fields;
	nFields = Fields.Count;
	
	Колонки = ТЗ.Колонки;
	мКолонки = новый массив(nFields);
	Для нПоле = 0 По nFields-1 Цикл
		ИмяКолонки = Fields.Item(нПоле).Name;
		мКолонки[нПоле] = ИмяКолонки;
		Колонки.Добавить(ИмяКолонки);
	КонецЦикла;
	
	Если Не Rs.eof Тогда
		rs.MoveFirst();
	КонецЕсли;
	Пока Не Rs.eof Цикл    
		стрТЗ = ТЗ.Добавить();
		
		Для каждого ИмяКол из мКолонки Цикл
			Значение = Fields.Item(ИмяКол).Value;
			Если Значение <> Null Тогда
				стрТЗ[ИмяКол] = Значение;
			КонецЕсли;        
		КонецЦикла;
		
		rs.MoveNext();
	КонецЦикла;
	
	Возврат ТЗ;
КонецФункции

Функция ВыполнитьСкалярный(Соединение, ТекстЗапроса) Экспорт
	стРез = Неопределено;
	
	cmd = Новый COMОбъект("ADODB.Command");
	cmd.CommandTimeout = 0;
	cmd.ActiveConnection = Соединение;    
	cmd.CommandText = ТекстЗапроса;
	rs = cmd.Execute();
	
	Fields = Rs.Fields;
	
	//Ничего не получилось в результате
	Если Rs.EOF И Rs.BOF Тогда
		Возврат НЕопределено;
	КонецЕсли; 
	
	rs.MoveFirst();
	Пока Не Rs.EOF Цикл    
		стРез = Новый Структура;
		
		Для каждого Поле из Fields Цикл
			ИмяКол = Поле.Name;
			Значение = Поле.Value;
			стРез.Вставить(ИмяКол, Значение);
		КонецЦикла;
		
		Прервать;
	КонецЦикла;
	
	Возврат стРез;
КонецФункции

Харлампий Дымба

Стоит упомянуть, что это реализованный функционал в типовой бухгалтерии 7.70.671 (начиная с 7.70.564 - 12 лет в обед) - обработка ПомощникПереходаНа1С8 умеет делать синхронизацию справочников и документов. Вот это вот все: "Справочник.ПараметрыСинхронногоУчета", "Справочник.МенеджерВыгрузок", "Справочник.МодифицированныеОбъекты", глУчестьЭлементПриИзменении, глУчестьДокументПриИзменении, ACC_ACC8.ert etc. При желании можно и с этими поразбираться и стащить себе схему работы. Я бы, если честно, не стал.

+Вопрос: в исходном коде Строка.Родитель и Строка.РодительКод разве заполнены после выполнения запроса?