Компьютерный форум NoWa.cc Здесь может быть Ваша реклама
Правила Форума
редакция от 22.06.2020
Форум .::NoWa.cc::.
Вернуться   Компьютерный форум NoWa.cc > В помощь вебмастеру > Программирование > Delphi

Уважаемые пользователи nowa.cc. Мы работаем для вас более 20 лет и сейчас вынуждены просить о финансовой помощи по оплате за сервер.
Окажите посильную поддержку, мы очень надеемся на вас. Реквизиты для переводов ниже.
Webmoney Webmoney WMZ: Z021474945171 Webmoney WME: E159284508897 Webmoney WMUSDT: T206853643180
Кошелёк для вашей помощи YooMoney 4100117770549562
YooMoney Спасибо за поддержку!

Ответ
 
Опции темы Опции просмотра Language
Старый 29.01.2010, 15:22   #1
Пользователь
 
Аватар для Leser
 
Пол:Мужской
Регистрация: 18.02.2008
Сообщений: 104
Репутация: 26
По умолчанию Подскажите по алгоритму плиз...

1. Имеем 1С, в нем справочник ТМЦ порядка 20 тыс. наименований, из них порядка 800 - группы.
2. Имеем БД фаербирд с таблицами:
а) Группы товаров (2 колонки - ид группы и наименование группы, ид группы праймари кей, значение ид группы равно значению кода в 1С)
б) Товары (9 колонок, ид товара равно коду товара в 1С)
в) Цены (4 колонки - ид цены /ставится через тригер БИ + генератор/, ид товара /значение код а товара из таблицы Товары/,Дата цены, значение цены на дату).
Задача: перебросить группы товаров, товары и цены товаров из 1С в фаирбирдовскую таблицу, а также, отслеживать изменения наименований, реквизитов и цен и проводить синхронизацию по этим изменениям.
Моя реализация:
1. Подключаюсь к 1С через ОЛЕ
2. Методом перебора справочника товара в 1С выгребаю группы и передаю нужные значения в процедуру добавления в фаербирд
--
Spr.selectitems(1);
while Spr.GetItem(1) > 0 do
Begin
Progress.StepBy(1);
if Spr.IsGroup('')=0 then Continue;
Group_Code:=Spr.getAttrib('Код');
Group_Lvl:=OLE1C.EvalExpr('ПолучитьУровеньГруппы(' +IntToStr(Group_Code)+')');
Group_Rod:=0;
if Group_Lvl<>1 then Group_Rod:=OLE1C.EvalExpr('ПолучитьРодителяГруппы( '+IntToStr(Group_Code)+')');
if Length(Spr.getAttrib('Наименование'))>24 then Group_Name:=Copy(Spr.getAttrib('Наименование'),1,2 4)
Else Group_Name:=Spr.getAttrib('Наименование');
Add_Group(Group_Code ,Group_Name,Group_Rod);
--
, где ид:=Group_Code,Group_Name - имя группы, Group_Rod - код родительской группы для подгрупп.
3. процедурка Add_Group
--
procedure TMain_Form.Add_Group(G_Code:Integer;G_Name:String; G_Rod:Integer);
Var
Need_Upd:Boolean;
BEgin
Need_Upd:=False;
Proc.StoredProcName:='';
Sel.Close;
Sel.SQL.Text:='Select * from SPR_TMC_G where ID_GROUP='+IntToStr(G_Code);
Sel.Open;
Sel.FetchAll;
if Sel.RecordCount=0 then
Begin
Need_Upd:=True;
Proc.StoredProcName:='SPR_TMC_G_INS';
end
Else
Begin
Sel.First;
if trim(Sel.FieldByName('name_group').AsString)<>trim (G_Name) then Need_Upd:=True;
if Sel.FieldByName('rod_group').AsInteger<>G_Rod then Need_Upd:=True;
end;
if Need_Upd=True then
Begin
if Proc.StoredProcName<>'SPR_TMC_G_INS' then
Proc.StoredProcName:='SPR_TMC_G_UPD';

Tr_Proc.StartTransaction;
Proc.ParamByName('id_group').AsInteger:=G_Code;
Proc.ParamByName('name_group').AsString:=G_Name;
Proc.ParamByName('rod_group').AsInteger:=G_Rod;
Proc.ExecProc;
Tr_Proc.Commit;
End;
--
На этом этапе в принципе все норм, при 20К позиций в справочнике за минуту -две идет оновление БД файербирда.
4. Дальше тем же перебором отбираю именно элементы справочника товаров в 1С
--
Tr_Proc.StartTransaction;
Str_Sost.Caption:='Синхронізація елементів товарів...';
Progress.Min:=0;
Progress.Max:=OLE1C.EvalExpr('ПолучитьКоличествоЭл ементов()');
Progress.Position:=0;
Main_Form.Refresh;

Spr.selectitems(1);
while Spr.GetItem(1) > 0 do
Begin
Progress.StepBy(1);
if Spr.IsGroup('')=1 then Continue;

//Если розничной цены нету - нафиг такой товар
Cena_R:=OLE1C.EvalExpr('ПолучитьРЦену('+Spr.getAtt rib('Код')+')');
IF Cena_R=0 Then Continue;
Group_Code:=Spr.getAttrib('Код');
Group_Lvl:=OLE1C.EvalExpr('ПолучитьУровеньГруппы(' +IntToStr(Group_Code)+')');
Group_Rod:=0;

if Group_Lvl<>1 then Group_Rod:=OLE1C.EvalExpr('ПолучитьРодителяГруппы( '+IntToStr(Group_Code)+')');
if Length(Spr.getAttrib('Наименование'))>128 then Group_Name:=Copy(Spr.getAttrib('Наименование'),1,1 28)
Else Group_Name:=Spr.getAttrib('Наименование');
Add_Tovar(Group_Code,Group_Name,Group_Rod,Spr.getA ttrib('Штрихкод'),Cena_R);
end;
Tr_Proc.Commit;

--
Отличия от предыдущей процедурки для груп - транзакцию всунул тут ибо, имхо, лучше фиксировать транзакцию после выполнения встроеных процедур
5. Процедура Add_Tovar имеет следующий вид:
-
procedure TMain_Form.Add_Tovar(T_Code:Integer;T_Name:String; T_Rod:Integer;T_Shtrihcode:String;T_Cena:Real);
var
Need_Set_Cena:Integer;
Need_upd:Boolean;
BEgin
Need_upd:=False;
Proc.StoredProcName:='';
Sel.Close;
Sel.SQL.Text:='Select * from SPR_TMC where ID_TMC='+IntToStr(T_Code);
Sel.Open;
Sel.FetchAll;
if Sel.RecordCount=0 then
Begin
Need_upd:=True;
Proc.StoredProcName:='SPR_TMC_INS';
end
Else
Begin
Sel.First;
if trim(Sel.FieldByName('name').AsString)<>Trim(T_Nam e) Then Need_upd:=True;
if trim(Sel.FieldByName('shtrihkod').AsString)<>Trim( T_Shtrihcode) Then Need_upd:=True;
if Sel.FieldByName('id_group').AsInteger<>T_Rod Then Need_upd:=True;
end;
if Need_upd=True then
Begin
if Proc.StoredProcName<>'SPR_TMC_INS' then Proc.StoredProcName:='SPR_TMC_UPD';
Proc.ParamByName('id_tmc').AsInteger:=T_Code;
Proc.ParamByName('name').AsString:=T_Name;
Proc.ParamByName('vid_tmc').AsInteger:=0;
Proc.ParamByName('art').AsString:='';
Proc.ParamByName('shtrihkod').AsString:=T_Shtrihco de;
Proc.ParamByName('id_group').AsInteger:=T_Rod;
Proc.ParamByName('dop_name').AsString:=LowerRCase( T_Name);
Proc.ParamByName('skidka').AsInteger:=0;
Proc.ParamByName('Edit_Ceny').AsInteger:=0;
Proc.ExecProc;
end;

Need_Set_Cena:=1;
Sel.Close;
Sel.SQL.Text:='Select * from SPR_CENY where ID_TMC='+IntToStr(T_Code);
Sel.Open;
Sel.FetchAll;
Sel.First;
while not Sel.Eof do
Begin
if sel.FieldByName('DATE_CENA').AsDateTime=Now then
Begin
if sel.FieldByName('CENA').AsFloat<>T_Cena then
Begin
Proc.StoredProcName:='SPR_CENY_UPD';
Proc.ParamByName('id_cena').AsInteger:=Sel.FieldBy Name('id_Cena').AsInteger;
Proc.ParamByName('id_tmc').AsInteger:=T_Code;
Proc.ParamByName('date_cena').AsDate:=Now;
Proc.ParamByName('cena').AsFloat:=T_Cena;
Proc.ExecProc;
Need_Set_Cena:=0;
end;
Break;
end;
Sel.Next;
end;

if Need_Set_Cena=1 then
Begin
Proc.StoredProcName:='SPR_CENY_INS';
Proc.ParamByName('id_tmc').AsInteger:=T_Code;
Proc.ParamByName('date_cena').AsDate:=Now;
Proc.ParamByName('cena').AsFloat:=T_Cena;
Proc.ExecProc;
end;
end;


--
Где в указаном болдом тексте происходит проверка/вставка/апдейт цены.
и собственно, проблема:
При отключении проверки/вставки/апдейта цен время выполнения (имею ввиду именно синхронизация элементов справочника) около 15-18 мин, с ценами - минут 30-40. Присоветуйте коллективным разумом - может возможен другой алгоритм проверок/апдейтов?
З.Ы. Думал, может селект на ИД товара/цены делать не на каждый элемент из справочника, а в общем, и потом искать по готовому набору записей, но вариант 20К раз перебирать набор записей в 20К не кажется более быстрым....
Leser вне форума
 
Ответить с цитированием Вверх
Здесь может быть Ваша реклама
Здесь может быть Ваша реклама


Реклама: бытовые холодильникииз москвы в петербург на теплоходетелевизор hisense 65e7kqциркуляционный насос grundfos magna3 25-60Заходите на сайт MebelStol.ru: стол на кухню с одной ножкой купить - отличные цены и большой выбор!


Старый 29.01.2010, 16:10   #2
Alan2006
Постоялец
 
Пол:Мужской
Регистрация: 02.07.2009
Сообщений: 393
Репутация: 79
По умолчанию Re: Подскажите по алгоритму плиз...

Вот не читал код до конаца... но имхо как-то сложно ты делаешь всё это...
1с какой? 7.7/8.х?
и на чём? на файл-сервере или на sql? не проще ли напрямую через ADO цепляться к базе из программы и забирать что нужно.

+ в самом 1с есть возможность работы с нешними БД через COM объекты. Работате на много быстрее чем OLE
__________________
Каждый человек, которому вы ответили на форуме "гугл в помощь" - потенциальный "возвращенец" в винды. (ц)
Alan2006 вне форума
 
Ответить с цитированием Вверх
Старый 29.01.2010, 16:15   #3
Leser
Пользователь
 
Аватар для Leser
 
Пол:Мужской
Регистрация: 18.02.2008
Сообщений: 104
Репутация: 26
По умолчанию Re: Подскажите по алгоритму плиз...

1С 77. ДБФ.
синхронизация с самой 1С не покатит, ибо оператор-менеждер пришел/не пришел приход сделал/не зделал, на кнопку нажал/ненажал...
А так приблуда службой по таймеру висит...

Добавлено через 3 минуты
плюс закачка прихода в 1С возможна и без учатия человека - пришла электронка, в ней накладная с новыми ценами...

Последний раз редактировалось Leser; 29.01.2010 в 16:18.. Причина: Добавлено сообщение
Leser вне форума
 
Ответить с цитированием Вверх
Старый 29.01.2010, 16:25   #4
Alan2006
Постоялец
 
Пол:Мужской
Регистрация: 02.07.2009
Сообщений: 393
Репутация: 79
По умолчанию Re: Подскажите по алгоритму плиз...

Ну тогда всё просто.
Подцепляешься ADODB connectionom к базе 1с-ной (прям мастером можно настроиться) и оттуда дёргаешь что тебе нужно. Структуру базы данных можно почитать в файлике 1Cv7.DD который лежит в каталоге с конфигурацией. Работать будет в разы быстрее чем OLE.
Если не разберёшься - спрашивай...
__________________
Каждый человек, которому вы ответили на форуме "гугл в помощь" - потенциальный "возвращенец" в винды. (ц)
Alan2006 вне форума
 
Ответить с цитированием Вверх
Старый 29.01.2010, 16:34   #5
Leser
Пользователь
 
Аватар для Leser
 
Пол:Мужской
Регистрация: 18.02.2008
Сообщений: 104
Репутация: 26
По умолчанию Re: Подскажите по алгоритму плиз...

Цитата:
Сообщение от Alan2006 Посмотреть сообщение
Ну тогда всё просто.
Подцепляешься ADODB connectionom к базе 1с-ной (прям мастером можно настроиться) и оттуда дёргаешь что тебе нужно. Структуру базы данных можно почитать в файлике 1Cv7.DD который лежит в каталоге с конфигурацией. Работать будет в разы быстрее чем OLE.
Если не разберёшься - спрашивай...

Дык в том то и вопрос, что скорость чтения через оле меня устраивает - не устраивает скорость проверки и записи/апдейта в файербирде....
Я когда на форму выношу к примеру название взятые из справочника 1С, то порядка 10% - то чтение даных с 1С, и порядка 90% - проверки и апдейты в файрбирде...
Leser вне форума
 
Ответить с цитированием Вверх
Старый 29.01.2010, 16:59   #6
Alan2006
Постоялец
 
Пол:Мужской
Регистрация: 02.07.2009
Сообщений: 393
Репутация: 79
По умолчанию Re: Подскажите по алгоритму плиз...

Хм... ну что я могу сказать... с фаербёрдом не работл честно говоря и не знаю по какому принципу организовано...
Помоему проблема именно в том, что перебирать нужно слишком много из того, что есть уже в фаербёрде...
Как работало у меня в торговом центре (достаточно крупном для нашего города) подобная весчь:
при проведении накладной, устанавливающей цены автоматом происходил запрос к целевой базе, который и определял нужно ли добавлять/апдейтить что-то.
Т.е. примерно так я бы сделал:
При проведении документа прошёлся бы в 1с по табличной части:

ВыбратьСтроки();
Пока получитьСтроку() = 1 Цикл
Код = Номенклатура.Код;
Группа = Номенклатура.Родитель.Код;
Цена = ПолучитьЦену(Номенклатура);
..... //остальные данные, нужные в фаербёрде получить
//Запро выполнить запрос;
КонецЦикла;

А запрос принимал бы такой вид:
"if exist(select * from tovari were tovari.id = '" + СокрЛП(Код) + "') update ...... else insert .... "
Аналогично для групп и для цен....
Это "рыба" для sql сервера. Если не на сервере крутится - в ручную придётся выполнять сравнение. Т.е. сделать выборку по коду и проверить, сколько кортежей в рекордсете и если ниодного тогда инсертить иначе апдейтить...
Если нужно могу прислать 1с-ную процедуру, работающую с sql прислать
При этом человеческий фактор отпадает - если не провелся документ то ничего выгружать не надо а если провелся - выгружается автоматом, не нужно доп. кнопку жать.

+ у тебя, как я понял, постоянно открывается и закрывается соединение с базой (читал не внимательно могу ошибаться) что есть дополнительные затраты по времени. попробуй один раз его открывать/закрывать а запросы все повесить на Query и/или Command'ы
__________________
Каждый человек, которому вы ответили на форуме "гугл в помощь" - потенциальный "возвращенец" в винды. (ц)
Alan2006 вне форума
 
Ответить с цитированием Вверх
Старый 29.01.2010, 18:09   #7
Leser
Пользователь
 
Аватар для Leser
 
Пол:Мужской
Регистрация: 18.02.2008
Сообщений: 104
Репутация: 26
По умолчанию Re: Подскажите по алгоритму плиз...

Помоему проблема именно в том, что перебирать нужно слишком много из того, что есть уже в фаербёрде...
Я тоже к этому склоняюсь....
Получается, что на каждый взятый с 1С элемент выполняется Select * from SPR_TMC where ID_TMC='+IntToStr(T_Code); - тоесть количество выполнений равно количеству элементов справочника. Если же выполнить просто Select * from SPR_TMC , то выйдет, что количество выполнений селекта одно, но зато придется в цикле бегать по этому набору записей столько раз, сколько есть елементов в справочнике 1С )). Не факт, что быстрее выйдет ...
у тебя, как я понял, постоянно открывается и закрывается соединение с базой - не, с базой, как с файербирдовской, так и с 1С-совской соединение один раз - при начале синхронизации устанавливается, после окончания - разрывается. Кстати, может в этом проблема? Не может ли такого быть, что на каждое обращение к процедуре 1С через оле открывается новый поток, и, как следствие, тормоза в системе?

Добавлено через 1 минуту
Заметил, что первые пару К элементов синхронизируются быстрей, а чем дальше - тем больше тормоза...

Последний раз редактировалось Leser; 29.01.2010 в 18:10.. Причина: Добавлено сообщение
Leser вне форума
 
Ответить с цитированием Вверх
Старый 01.02.2010, 14:48   #8
KVGColl
Пользователь
 
Пол:Мужской
Регистрация: 11.05.2007
Сообщений: 48
Репутация: 21
По умолчанию Re: Подскажите по алгоритму плиз...

а если сделать так: из 1С получаем одним запросом все необходимые элементы/группы (можно из delphi запрос послать, можно вызвать из 1С функцию, которая возвращает набор данных из запроса) - это дело можно, например поместить в TMemoryTable (RX компоненты). А затем тоже одним запросом получаем разницу между набором из 1С и Firebird-базой.
KVGColl вне форума
 
Ответить с цитированием Вверх
Ответ


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Подскажите плиз коммуникатор с хорошим звуком APEXik КПК 5 11.10.2010 17:52
Подскажите плиз что за индикатор Renault Kangoo deamon_t Автосервис 2 11.05.2009 09:35
Подскажите,плиз!!! васька59 Ноутбуки, Нетбуки, Планшеты 23 13.06.2008 10:08
подскажите плиз ! Bimbo PHP 2 22.08.2007 07:10
Софт для видеокарты с ТВ-тюнером: подскажите, плиз! LeXXiK Архив 7 13.02.2007 19:31

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход


Текущее время: 08:49. Часовой пояс GMT +3.


Copyright ©2004 - 2025 NoWa.cc

Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2026, vBulletin Solutions, Inc. Перевод: zCarot
Время генерации страницы 0.05642 секунды с 11 запросами