Восстановление сессии в фоне

Обсуждение возникших проблем, предложений и ошибок ODAC компонентов
yuryleon77
Сообщения: 13
Зарегистрирован: Ср 29 июл 2020 15:20

Восстановление сессии в фоне

Сообщение yuryleon77 » Ср 29 июл 2020 15:35

Добрый день!

Возникла такая неприятная ситуация при использовании компонент ODAC (версия 10.3.9) в студии Embarcadero 10.1 Berlin.
Имеется форма, на ней кнопка, при нажатии на которую происходит загрузка данных структурированного файла в БД Oracle (версия 18с). Если грузим последовательно несколько файлов (или один файл несколько раз), то после каждой нечетной загрузки кроме первой (3-я, 5-я, 7-я и т.д.) происходит переподключение сессии (срабатывает событие OnAfterConnect на компоненте TOraSession). Опытным путем установил, что реконнект идет при обращении к методу Prepare компонента TOraStoredProc. Так как исходников не имею, то не могу понять причину происходящего. При подключении используется Direct. DisconnectedMode отключен.

MaximG
Devart Team
Сообщения: 114
Зарегистрирован: Пн 06 июл 2015 12:51

Re: Восстановление сессии в фоне

Сообщение MaximG » Пт 31 июл 2020 13:18

Пожалуйста уточните, используете ли Вы DisconnectedMode ? Приведите DDL-скрипт на создание используемой хранимой процедуры и пример кода работы с ней в Вашем проекте

yuryleon77
Сообщения: 13
Зарегистрирован: Ср 29 июл 2020 15:20

Re: Восстановление сессии в фоне

Сообщение yuryleon77 » Пт 31 июл 2020 13:47

При DisconnectedMode вылетало бы постоянно. Нет, я его не использую.

yuryleon77
Сообщения: 13
Зарегистрирован: Ср 29 июл 2020 15:20

Re: Восстановление сессии в фоне

Сообщение yuryleon77 » Пт 31 июл 2020 13:51

пример кода в Delphi:

Код: Выделить всё

TPkMop = class(TCustomOraPackage)
  private
    FSession: TOraSession;
    procedure GetStoreProc;
  protected
    StoredProc: TOraStoredProc;
  published
    property Name;
    property Session: TOraSession read GetSession write SetSession;
    // property Cursor;
  public
    procedure ImpMVDDict_1207(const PStan: TList<Variant>;
      const  PId, PName, PAddr, PPrim: TList<string>);
  end;

implementation   

procedure TPkMop.GetStoreProc;
begin
  if Assigned(StoredProc) then
    FreeAndNil(StoredProc);
  StoredProc := TOraStoredProc.Create(nil);
  StoredProc.AutoCommit := False;
  StoredProc.Session := Session;
end;

procedure TPkMop.ImpMVDDict_1207(const PStan: TList<Variant>;
  const PId, PName, PAddr, PPrim: TList<string>);
var
  LInd, LBuf: Integer;
  LStan: TList<Variant>;
  LID,LPName, LAddr, LPrim: TList<string>;
  I, LLast: Integer;
begin
  try
    GetStoreProc;
    LID := TList<string>.Create;
    LPName := TList<string>.Create;
    LAddr := TList<string>.Create;
    LStan := TList<Variant>.Create;
    LPrim := TList<string>.Create;
    StoredProc.StoredProcName := 'FGV0.MOP.IMPORT_MVD_DICT_1207';
    StoredProc.Prepare;
    LInd := 0;
    LBuf := 32000;
    while (LBuf * LInd <= PId.Count) do
    begin
      LLast := Iff((LBuf * (LInd + 1) > PId.Count), PId.Count,
        LBuf * (LInd + 1));
      for I := (LBuf * LInd) to (LLast - 1) do
      begin
        LId.Add(PId[I]);
        LPName.Add(PName[I]);
        LAddr.Add(PAddr[I]);
        LStan.Add(PStan[I]);
        LPrim.Add(PPrim[I]);
      end;
      SetParam('P_ID', LId);
      SetParam('P_NAME', LPName);
      SetParam('P_ADDR', LAddr);
      SetParam('P_STAN', LStan);
      SetParam('P_PRIM', LPrim);
      StoredProc.Execute;
      Inc(LInd);
      LId.Clear;
      LPName.Clear;
      LAddr.Clear;
      LStan.Clear;
      LPrim.Clear;
    end;
  finally
    FreeAndNil(LId);
    FreeAndNil(LPName);
    FreeAndNil(LAddr);
    FreeAndNil(LStan);
    FreeAndNil(LPrim);
  end;
end;

yuryleon77
Сообщения: 13
Зарегистрирован: Ср 29 июл 2020 15:20

Re: Восстановление сессии в фоне

Сообщение yuryleon77 » Пт 31 июл 2020 13:53

Код: Выделить всё

PROCEDURE import_mvd_dict (  p_id string_table,
                           p_name string_table,
                           p_addr string_table,
                           p_stan number_table,
                           p_prim string_table )is
  dt      date := sysdate;
  ex      number;
  st      number;
  cur     MOP_MVD%ROWTYPE;
  l_id    varchar2(4000);
  l_name  varchar2(4000);
  l_addr  varchar2(4000);
  l_stan  number;
  l_prim  varchar2(4000);
begin
  -- основной цикл обработки входящих данных
  for i in p_id.first..p_id.last loop
    l_stan := p_stan(i);
    if l_stan not in (0,1) then
      fgv_err.raiserr( TA_ERRC, TA_PFX, 757, DEST_TA );
    end if;
    l_id := substr(trim(p_id(i)),1,4);
    if l_id is null then
      fgv_err.raiserr( TA_ERRC, TA_PFX, 759, DEST_TA );
    end if;
    l_name := substr(p_name(i),1,300);
    l_addr := substr(p_addr(i),1,100);
    l_prim := substr(p_prim(i),1,100);
    select count(1) into ex from mop_mvd m where m.id = l_id;
    if ex = 0
      then -- добавление новой записи
        st := l_stan * 2;
        insert into mop_mvd (id,full_name,addr,stan,prim,date_add,date_edit,date_del)
          values (l_id,l_name,l_addr,st,l_prim,dt,dt,case when st = 0 then dt else null end);
      else -- редактирование существующей записи
        select * into cur from mop_mvd m where m.id = l_id;
        if cur.date_edit = dt then
          fgv_err.raiserr( TA_ERRC, TA_PFX, 758, DEST_TA, l_id );
        end if;
        if  nvl(cur.full_name,chr(0)) = nvl(l_name,chr(0))
        and nvl(cur.addr,chr(0)) = nvl(l_addr,chr(0))
          then -- ключевые реквизиты не изменились
            st := l_stan * 1;
            update mop_mvd m set m.prim = l_prim,
                                 m.stan = st,
                                 m.date_edit = dt,
                                 m.date_del = case when st = 0 then nvl(m.date_del,dt) else null end
                           where m.id = l_id;
          else -- обновление записи
            st := l_stan * 3;
            update mop_mvd m set m.full_name = l_name,
                                 m.addr = l_addr,
                                 m.prim = l_prim,
                                 m.stan = st,
                                 m.date_edit = dt,
                                 m.date_del = case when st = 0 then nvl(m.date_del,dt) else null end
                           where m.id = l_id;
          end if;
      end if;
  end loop;
  -- "удаление" не упомянутых в файле записей
  update mop_mvd m set m.stan = 0, m.date_del = nvl(m.date_del,dt) where m.date_edit < dt;
end import_mvd_dict;

MaximG
Devart Team
Сообщения: 114
Зарегистрирован: Пн 06 июл 2015 12:51

Re: Восстановление сессии в фоне

Сообщение MaximG » Пн 03 авг 2020 08:08

Спасибо за предоставленную Вами информацию. Мы проверим работу наших компонентов согласно Вашего описания и сообщим Вам о результатах в самое ближайшее время

yuryleon77
Сообщения: 13
Зарегистрирован: Ср 29 июл 2020 15:20

Re: Восстановление сессии в фоне

Сообщение yuryleon77 » Пт 28 авг 2020 08:41

Добрый день! Есть какие-либо подвижки по моему вопросу?

MaximG
Devart Team
Сообщения: 114
Зарегистрирован: Пн 06 июл 2015 12:51

Re: Восстановление сессии в фоне

Сообщение MaximG » Вт 01 сен 2020 12:18

Мы внимательно изучили присланную Вами информацию, но ее оказалось недостаточно для воспроизведения проблемы в нашем окружении. Пожалуйста с помощью формы e-support (https://www.devart.com/company/contactform.html) пришлите полный исходный код тестового примера, а также DDL-скрипт для создания объектов БД (таблиц, типов и т.д.),
которые необходимы для использования хранимой процедуры import_mvd_dict

yuryleon77
Сообщения: 13
Зарегистрирован: Ср 29 июл 2020 15:20

Re: Восстановление сессии в фоне

Сообщение yuryleon77 » Ср 21 окт 2020 13:47

Извините за долгий ответ. Поменялся приоритет задач на время.
Посредством формы e-support выслал тестовый пример с описанием необходимых действий.

MaximG
Devart Team
Сообщения: 114
Зарегистрирован: Пн 06 июл 2015 12:51

Re: Восстановление сессии в фоне

Сообщение MaximG » Ср 28 окт 2020 16:04

Пожалуйста попробуйте отослать Ваш пример еще раз, т.к. к настоящему времени мы не получили на e-support Ваш запрос

yuryleon77
Сообщения: 13
Зарегистрирован: Ср 29 июл 2020 15:20

Re: Восстановление сессии в фоне

Сообщение yuryleon77 » Пт 30 окт 2020 08:06

Странно отправлял даже дважды. Сейчас отправлю еще раз

yuryleon77
Сообщения: 13
Зарегистрирован: Ср 29 июл 2020 15:20

Re: Восстановление сессии в фоне

Сообщение yuryleon77 » Пт 30 окт 2020 09:14

MaximG писал(а): Ср 28 окт 2020 16:04 Пожалуйста попробуйте отослать Ваш пример еще раз, т.к. к настоящему времени мы не получили на e-support Ваш запрос
Не могу отослать через e-support. Залогинился, почту не позволяет сменить, но пишет "No such user here"

Как я могу передать вам тестовый пример?

MaximG
Devart Team
Сообщения: 114
Зарегистрирован: Пн 06 июл 2015 12:51

Re: Восстановление сессии в фоне

Сообщение MaximG » Пн 02 ноя 2020 12:30

По техническим причинам Вы не могли некоторое время воспользоваться нашим сервисом e-support. Сейчас проблема решена, мы получили отправленный Вами пример и приступили к его анализу.

yuryleon77
Сообщения: 13
Зарегистрирован: Ср 29 июл 2020 15:20

Re: Восстановление сессии в фоне

Сообщение yuryleon77 » Вт 03 ноя 2020 08:31

Отправил еще раз архив с тестовым примером

MaximG
Devart Team
Сообщения: 114
Зарегистрирован: Пн 06 июл 2015 12:51

Re: Восстановление сессии в фоне

Сообщение MaximG » Ср 04 ноя 2020 14:50

Спасибо за составленный Вами пример. Мы внимательно изучили его работу и убедились, что Вы используете режим DisconnectedMode. Пожалуйста отключите этот режим :

Код: Выделить всё

function TfrmConnectDlg.DoConnect: TModalResult;
  begin
    ...
    MainSession.Options.DisconnectedMode := False;
    ...
  end;

и сообщите нам, воспроизводится ли проблема без использования DisconnectedMode

Закрыто