Конференция "Базы" » Вызов процедуры Oracle через ODAC
 
  • Андрей0209 (02.09.12 18:10) [0]
    Всем привет. Использую Rad 2009, ODAC 6.90.0.55.
    Сабж:
    Клиент подключается к программе через TCP/IP. Если клиент начинает посылать данные, то идет вызов процедуры Oracle с этими данными, которая возвращает данные для отправки клиенту обратно. Когда подключается один клиент - проблем нет. А вот когда больше одно, то получается следующее: процедура выполняется, и вдруг ещё один пользователь отправил данные. Процедура, которая выполнялась останавливается и начинает выполняться новая. Клиент, который запустил её первый - ничего не получает. Как тут можно поступить? Создать массив из компонентов TOraStoredProc и создавать в нём компоненты при подключении. Каждое соединение будет использовать свой компонент. Или же определять запущено ли выполнение процедуры и подождать, когда завершиться.
    Подскажите, пож-та. Спасибо.
  • AV © (04.09.12 12:05) [1]
    А что логика приложения требует?
    Процедура что, имеет жесткий параметр(нет параметра)?
    И каждый запускает только с ним?
  • Андрей0209 (04.09.12 17:59) [2]
    Параметры тут не при чем. Если идет выполнение процедуры и вдруг её опять вызывают, то он останавливает выполнение и возвращает, что есть. Это наверное все компненты для работы с базами данными так делают. Вот я и спрашиваю делать много компонентов(для каждого компонента свой TOraStoredProc) или как?
  • AV © (05.09.12 09:29) [3]
    В общем случае - да.

    Делай как oracle сам делает: на запрос от клиента процесс-Listener выделяет новый поток (или берет свободный из пула потоков) и назначает его этому клиенту. Больше листенер клиенту не нужен.

    Представим, что твоя программа Listener.
    Клиент соединяется с программой, программа рождает для него поток, в котором есть все компанеты доступа(_свой_ TOraSession, TOraStoredProc, etc ), связывает клиента с этим потоком, и забывает про этого клиента.
  • Андрей0209 (05.09.12 20:33) [4]
    Спасибо, большое. Подскажите, пожалуйста, как сделать вышеописанное вами.
    Пытался сделать через массив форм. На каждой форме есть сессия и процедура. Вроде работает, но приложение виснет, пока клиенты не отключаться.
  • AV © (06.09.12 09:16) [5]
    Не через формы
    Через список потоков


    > Вроде работает, но приложение виснет

    потому что все в одном потоке, главном, VCL

    На новое соединение создается и запускается класс-наследник TThread
  • Андрей0209 (06.09.12 18:10) [6]
    Спасибо. Буду читать про потоки в Windows и Delphi.
    Потом отпишусь.
  • Андрей0209 (06.09.12 21:31) [7]
    Подскажите еще, пожалуйста. Обязательно для каждого нового соединения создавать сессию в Oracle. Нельзя через одну сессию делать много ToraStoredProc?
  • AV © (07.09.12 09:37) [8]

    > Обязательно для каждого нового соединения создавать сессию
    > в Oracle

    Если в разных потоках - да
  • Андрей0209 (11.09.12 20:19) [9]
    Добрый вечер.
    Начал пробовать с потоками.
    Создаю класс-наследник.

    type
     TOraThread = class(TThread)
     private
       OraSession: TOraSession;
       OraProc: TOraStoredProc;
     protected
       procedure Execute; override;
     public
       function Connect(pOraConnectString: String): Boolean;
       procedure Disconnect;
     end;



    Методы:

    function TOraThread.Connect(pOraConnectString: String): Boolean;
    begin
     Result := False;
     if OraSession.Connected then
      Result := True
     else
          try
              OraSession := TOraSession.Create(nil);
              OraSession.ConnectString := pOraConnectString;
              OraSession.LoginPrompt := False;
              OraSession.Connect;
              Result := True;
          except
                   //
          end;
    end;

    procedure TOraThread.Disconnect;
    begin
     if OraSession.Connected then
       OraSession.Disconnect;
    end;



    Как создаю:

    var
      OraThreads: Array[1..10] of TOraThread;
    ...
    procedure TForm1.Button1Click(Sender: TObject);
    var
      i: Integer;
    begin
     for i := 1 to SpinEdit1.Value do
        begin
          Inc(OraThreadsCount);
          OraThreads[i].Create(True);
          OraThreads[i].Connect(OraSession1.ConnectString);
        end;
    end;



    При нажатии на кнопку получаю EAccessViolation. Подскажите, пожалуйста, что я делаю не так? Спасибо!!!
  • sniknik © (11.09.12 21:23) [10]
    что то не создано в момент вызова, вот хоть сессия т.к делается "внешним" вызовом извне потока, и в момент работы потока... скорее всего, т.к. что то после нее или в ней не видно resume... т.е. оно где то в "не опубликованном".
  • sniknik © (11.09.12 21:30) [11]
    вообще, это весь код? глюков немеряно...
    1 создание потока в режиме саспенд, резюма не видно.
    2 обращение к не созданому еще объекту  if OraSession.Connected then
    3 сессия сама по себе, ни сч чем не связана.
    4 дисконект тоже бесполезная функция
  • AV © (12.09.12 10:19) [12]
    > function TOraThread.Connect(pOraConnectString: String):
    > Boolean;
    > begin
    >  Result := False;
    >  if OraSession.Connected then  // тут я появился :), т.к. OraSession = nil

    > function TOraThread.Connect(pOraConnectString: String):
    > Boolean;
    > begin
    >  Result := False;
    if OraSession <> nil then
    b
     >  if OraSession.Connected then
     Result := True
    e
    else
         try
             OraSession := TOraSession.Create(nil);
             OraSession.ConnectString := pOraConnectString;
             OraSession.LoginPrompt := False;
             OraSession.Connect;
             Result := True;
         except
                  //
         end;
  • Андрей0209 (12.09.12 17:26) [13]
    Исправил. Тоже самое.
    Возможно нужно добавить этот в код в код создания потока?
    Нужно переопределить метод Create? Так же как метод Execute?

    function TOraThread.Connect(pOraConnectString: String): Boolean;
    begin
     Result := False;
     if OraSession <> nil then
       Result := True
     else
         try
            OraSession := TOraSession.Create(nil);
            OraSession.ConnectString := pOraConnectString;
            OraSession.LoginPrompt := False;
            OraSession.Connect;
            Result := True;
         except
           //
         end;
    end;

  • AV © (12.09.12 17:30) [14]

    > Возможно нужно добавить этот в код в код создания потока?
    > Нужно переопределить метод Create? Так же как метод Execute?

    это все равно

    Когда поток стартует? где resume?
    Как используется, короче?
  • Андрей0209 (12.09.12 17:33) [15]

    > вообще, это весь код? глюков немеряно...
    > 1 создание потока в режиме саспенд, резюма не видно.
    > 3 сессия сама по себе, ни сч чем не связана.
    > 4 дисконект тоже бесполезная функция

    Это весь код, для начала пытаюсь проверить как создавать потоки с сессиями.
    Потом буду внедрять в прогу.
    1. Хочу просто создать сессию ничего не делая.
    3. А с чем нужно связать?
    4. Почему бесполезно? При уничтожении потока будет выполнен корректное отключение от базы данных?
  • Андрей0209 (12.09.12 17:34) [16]
    Надо запустить поток, чтобы сессия создалась?
  • Андрей0209 (12.09.12 17:42) [17]
    Исправил. К сожалению ситуация не изменилась.

    OraThreads[i].Create(False);

  • sniknik © (12.09.12 17:53) [18]
    > Это весь код
    это очень мало...

    > Надо запустить поток, чтобы сессия создалась?
    смысл потока в том чтобы его "запускать" и выполнять в нем какие то действия, без этого, используя его исключительно как контейнер для функций, он бесполезен. однозначно.

    > Исправил. К сожалению ситуация не изменилась.
    значит не там исправил.
  • sniknik © (12.09.12 17:56) [19]
    > 4. Почему бесполезно?
    не используется. раз - "Это весь код"

    > При уничтожении потока будет выполнен корректное отключение от базы данных?
    это ты у меня спрашиваешь? код твой! сделаешь - будет, нет - ну и не надо...
  • Андрей0209 (12.09.12 19:03) [20]
    Сделал все по новой. Вроде работает.
    Только подскажите пож-та, когда вызывается метод потока Execute?
    Если он запускается циклически, то с какой периодичностью?
    Спасибо.
  • sniknik © (12.09.12 20:10) [21]
    справочная информация находится в справке.
  • AV © (13.09.12 11:50) [22]

    > когда вызывается метод потока Execute?

    ОС решает, зависит от приоритета процесса, потока,
    других запущенных на компе потоков/процессов,
    в т.ч. системных
  • AV © (13.09.12 11:53) [23]
  • Андрей0209 (13.09.12 16:35) [24]
    Спасибо, большое!
  • Андрей0209 (14.09.12 11:16) [25]
    А еще вопросик.
    Смотрите, при подключении клиента к IdTCPServer инди делает новый поток, нельзя ли как-то создать в этом потоке нужные мне данные(OraSession, и т.д.).
    А то получается для соединения инди делает поток, потом еще я делаю поток. Не будет проблем при вызове процедур моих потоков из потока инди?
  • AV © (14.09.12 15:04) [26]

    > Смотрите, при подключении клиента к IdTCPServer инди делает
    > новый поток, нельзя ли как-то создать в этом потоке нужные
    > мне данные(OraSession, и т.д.).

    Я создавал на событие соединения свой поток со своим IdPerThread, в качестве переменной,
    которой просто присваивал порожденный из IdTCPServer поток
    т.о. в моем потоке содержится поток от инди
 
Конференция "Базы" » Вызов процедуры Oracle через ODAC
Есть новые Нет новых   [134430   +2][b:0][p:0.002]