Конференция "Базы" » TADOCommand + MSSQL + SP [D7, MSSQL]
 
  • Барра Кабамма (10.11.08 15:01) [0]
    Помогите понять магию и логику адо при выполнении хранимок на mssql. Исходные данные:
    хранимая на сервере, три входных параметра, шесть выходных.
    Сама процедура отлажена и возвращает то что нужно. Кроме того, прекрасно выполняется из под asp.net и других хранимых процедур на самом сервере.
    В Д7 вызываю так:

    with TADOCommand.Create(Self) do
     try
      Connection  := ADOConnection;
      CommandType := cmdStoredProc;
      CommandText := 'my_procedure';
      with Parameters.AddParameter do
       begin
        Direction := pdReturnValue;
        DataType  := ftInteger;
        Name      := '@return_value';
       end;
      with Parameters.AddParameter do
       begin
        Direction := pdInput;
        DataType  := ftString;
        Size      := 20;
        Name      := '@p_cnt_num';
        Value      := ...
       end;
     ....
      with Parameters.AddParameter do
       begin
        Direction := pdInputOutput;
        DataType  := ftFloat;
        Name      := '@p_oborot_db';
       end;

    Execute;

    А дальше все зависит от фаз луны.

    Может ругнуться на то, что ожидается параметр '@p_oborot_db который не определен.
    Может ни на что не ругнуться но в половине выходных параметрах будут верные данные, в остальных либо пусто, либо неверные данные.

    Если настроить ADoCommand в дизайне, то все работает как надо. Но мне необходимо создавать экземпляр динамически, или по крайней мере менять имя владельца в имени процедуры на рантайме (БД на разных серверах по разному называется), а при этом параметры установаленные в дизайнтайме говорят мне "привет".
  • GRAND © (10.11.08 15:10) [1]
    А че, TADOStoredProc - не кошерный компонент?
  • MsGuns © (10.11.08 15:11) [2]
    Не надо параметры строить вручную - это приводит к множественным ошибкам и скоропалительном выводе о глючности ADO

    Я бы не рекоментдовал использовать TADOStoredProc вообще (она "удобна" в дизайне, т.к. дает возможности извлечь параметры и задать им значения визуально)
    Грамотнее делать так:

    with ADOCommand1 do
     try
       CommyndType := cmdStoredProc;
       CommandText := ...
       Parameters.Refresh;
       Parameters.ParamByName(..).Values := ..;
       Parameters.ParamByName(..).Values := ..;
       Execute;
     except
       ..
     end;
  • Барра Кабамма (10.11.08 15:18) [3]
    пробовал, не помогает.

    После  Parameters.Refresh ParamCount = 0
  • GRAND © (10.11.08 15:19) [4]

    > Не надо параметры строить вручную - это приводит к множественным
    > ошибкам и скоропалительном выводе о глючности ADO


    :))))))))

    Я, пожалуй, помолчу...
  • MsGuns © (10.11.08 15:38) [5]
    >Барра Кабамма   (10.11.08 15:18) [3]
    >пробовал, не помогает.

    Очевидно, не так пробовал. Для указания ошибки в конкретном случае мало привести код, надо еще и саму ХП.
    И, кстати, собака в именах параметров имеется в самой декларации ХП ?
  • Барра Кабамма (10.11.08 15:52) [6]
    собака в именах параметров в хранимке есть. модификатор out для выходных тоже есть.

    а сама процедура в процессе тестирования и ловли бага адо выродилась до банального присвоения выходным параметрам литеральных значений без всяких селектов.

    ....
    set @p_oborot_db = 3.62;
    set @p_oborot_cr = 4.12;
    return 0;
    end
  • sniknik © (10.11.08 16:11) [7]
    > Я, пожалуй, помолчу...
    все правильно, если в десигне там где код написан борландавцами не забыли сделать рефреш параметрам/не дублировать их/правильные типы выставить и т.д. то оно и не глючит. а при ручном создании  нужно как минимум понимать что делаешь и зачем. без этого не работает/глюки, но на себя любимого никто не думает, что сам глючит....
    а потому либо пользуйся готовым за тебя написанным, либо не жалуйся, а изучай то с чем работаешь.

    > и ловли бага адо
    лови не баги ado, а свои, и все у тебя получится.
  • Барра Кабамма (10.11.08 16:14) [8]
    нужно как минимум понимать что делаешь и зачем

    Знаешь что я первым делом сделал, когда глюк обнаружил?
    Настроил все в дизайне через редактор параметров и открыл dfm.
    Потом сравнил все что туда попало со своим кодом.
    Все тоже самое.
  • sniknik © (10.11.08 16:15) [9]
    > После  Parameters.Refresh ParamCount = 0
    коннект к серверу в момент рефреша есть?
  • Барра Кабамма (10.11.08 16:15) [10]
    конечно есть
  • sniknik © (10.11.08 16:17) [11]
    > Все тоже самое.
    а у меня нет, но всегда работает...
  • Барра Кабамма (10.11.08 16:26) [12]
    а у меня нет, но всегда работает...

    Здесь напрашивается вывод, что свойства параметров, создаваемых в рантайме должны отличаться от дизайновых и что ты знаешь как именно.
    А рассказать можешь?
  • sniknik © (10.11.08 16:29) [13]
    > Здесь напрашивается вывод
    неправильный вывод...

    см. правильный код
    MsGuns ©   (10.11.08 15:11) [2]
    где видишь создание параметров?
  • Барра Кабамма (10.11.08 16:33) [14]
    Ну ё-мае, мужики. Сколько можно?
    Тот правильный код правилен только для него самого.
    Ноль параметров у меня после рефреша. Ноль!
  • sniknik © (10.11.08 16:33) [15]
    кстати у тебя не все тоже самое, если бы было тоже
    то было бы так
    CommandText := 'my_procedure;1';
  • sniknik © (10.11.08 16:36) [16]
    > Ну ё-мае, мужики. Сколько можно?
    действительно...

    > Ноль параметров у меня после рефреша. Ноль!
    значит варианты
    MsGuns ©   (10.11.08 15:38) [5]
    > Очевидно, не так пробовал.

    sniknik ©   (10.11.08 16:15) [9]
    > коннект к серверу в момент рефреша есть?
  • Барра Кабамма (10.11.08 16:36) [17]
    ;1

    и так тоже делал.
    и два раза приседал и крек-пекс-фекс тоже говорил.
  • Барра Кабамма (10.11.08 16:38) [18]
    sniknik ©   (10.11.08 16:15) [9]
    > коннект к серверу в момент рефреша есть?


    До возни с этой процедурой приложение уже успело выполнить с десяток запросов с mssql. Авторизовать пользователя, прочитать его профиль, вставить кучу записей в лог таблицу и т.д.
  • Барра Кабамма (10.11.08 16:46) [19]
    В общем резюмирую, мужики.
    Вся ваша уверенность в безгрешности делфийского адо и собственного  умения с ним работать зиждется на ограниченном жизненном опыте. Написали сотню однотипных хранимок, которые работают из под адо и все.
    У меня тоже сотня хранимок работает. Одни возвращают наборы данных, другие строковые параметры.
    А вот эта не работает из под делфийского адо.

    И ни вы, ни я не знаете почему.
  • Барра Кабамма (10.11.08 16:51) [20]
    Вот последний копипаст из редактора кода

    with TADOCommand.Create(Self) do
     try
      Connection  := ADOConnection;
      if not ADOConnection.Connected then ADOConnection.Connected := True;   CommandType := cmdStoredProc;
      CommandText := Format('%s.dbo.GET_ACCOUNT_SALDO;1',[fDB]);
      //CommandText := Format('%s.dbo.GET_ACCOUNT_SALDO',[fDB]);
      Log('CommandText = ',CommandText);
      Parameters.Refresh;
      Log('ParamCount = ',IntToStr(ParamCount));
      for i := 0 to Pred(ParamCount) do Log(Parameters.Items[i].Name);

    и в логе круглый ноль.
  • sniknik © (10.11.08 17:04) [21]
    > А вот эта не работает из под делфийского адо.
    "эта" это собственно какая?

    > И ни вы, ни я не знаете почему.
    да где нам.

    Log('ParamCount = ',IntToStr(ParamCount));
    это что за переменная? к чему относится?
  • sniknik © (10.11.08 17:12) [22]
    GRAND ©
    ну так как, честь ADO восстановлена? ;)
    кто глючит то на самом деле? ;)))
  • Барра Кабамма © (10.11.08 17:12) [23]
    это что за переменная? к чему относится?

    Относится к верхнему with

    Log('Parameters.Count = ',IntToStr(Parameters.Count));
    Log('ParamCount = ',IntToStr(ParamCount));

    В логе:

    10.11.2008 17:10:28 Parameters.Count =  0
    10.11.2008 17:10:28 ParamCount =  0
  • sniknik © (10.11.08 17:18) [24]
    > Относится к верхнему with
    ну так нет там такой, у верхнего with, берется системная.

    > В логе:
    > 10.11.2008 17:10:28 Parameters.Count =  0
    сказок не рассказывай... так я тебе и поверил после [20] (хотя и до этого не очень то...).
  • Барра Кабамма © (10.11.08 17:21) [25]
    ты сам поменьше сказок рассказывай.
    приведен код как есть и приведен лог как есть.

    Parameters.Count нулевой
  • sniknik © (10.11.08 17:26) [26]
    > Parameters.Count нулевой
    значит в твоей процедуре ПАРАМЕТРОВ НЕТ, даже @RETURN_VALUE, что както уже загадочно...
  • Барра Кабамма © (10.11.08 17:27) [27]
    А рефреш что с ;1 что без нее возвращает false
  • Барра Кабамма © (10.11.08 17:28) [28]
    значит в твоей процедуре ПАРАМЕТРОВ НЕТ, даже @RETURN_VALUE, что както уже загадочно...

    Ага. А асп.нет приложение с SqlCommand читает их из космоса.
  • Барра Кабамма © (10.11.08 17:31) [29]
    И еще вдобавок при execute злобные марсиане мне в лог вставляют: expects parameter '@p_cnt_num', which was not supplied
  • Барра Кабамма © (10.11.08 18:01) [30]
    В общем слушайте опытные дивелоперы (у которых все и всегда и везде работает) и пополняйте свой небогатый жизненный опыт.

    Я в начале говорил, что процедура моя самая обычная, но находится в разноименных бд на разных серверах.
    А само приложение коннектится всегда к своей служебной БД и у него всегда есть гранты на объекты второй бд, которая везде по разному зовется.
    Так вот.
    Рефреш говорит правду только если хранимка находится в текущей базе, а если имя ей дать dbname.dbo.procedurename и сделать рефрешь, то получается тот самый эффект, который меня и всех вас поставил в тупик.

    делюсь бесплатно. потому как я сегодня добрый.

    ЗЫ тока не надо щас задним числом говорить, что вы это и так знали.
  • sniknik © (10.11.08 19:22) [31]
    > ЗЫ тока не надо щас задним числом говорить, что вы это и так знали.
    не знали конечно, ты же не дал этой инфы "задним числом".

    то что ты сказал, это  
    > БД на разных серверах по разному называется
    т.е. это понятно (имхо) - работаешь с одним сервером коннектишся к базе с одним именем, с другим к с другим.
    а то что у тебя, из коннекта к одной базе вызывается процедура из другой, а в этой этой процедуры совсем нет... не говорил такого.
    можно было бы по [20] догадаться, так сказать протелепатировать зачем ты там форматом в имя базы значение какой то переменной вставляешь... но извини, я как ParamCount увидел так офигел и больше не  думал на эту тему.

    но это кстати не объясняет почему создание этих параметров у тебя не работает.
  • sniknik © (10.11.08 19:27) [32]
    > ты же не дал этой инфы "задним числом".
    и даже больше того, ты это скрывал, и фальсифицировал пример
    > CommandText := 'my_procedure';
    где здесь 'xxx.xxx.my_procedure';??? показано как к родной.
  • Барра Кабамма © (10.11.08 21:30) [33]
    Про разные базы было в самом вопросе.

    Кроме того в 20 посте было
    CommandText := Format('%s.dbo.GET_ACCOUNT_SALDO',[fDB]);
  • Барра Кабамма © (10.11.08 21:43) [34]
    в общем ладно, проехали.
    меня щас больше интересует как выйти из положения малой кровью.
    базы, которые названы по разному это объективная реальность и наследие прошлого. от этого уже никуда не деться.
    собственно есть выбор из трех альтернатив:
    1. перетащить все объекты дефолтной бд в те разноименные экземпляры
    2. использовать еще один коннект в приложении.
    3. перенести процедуры в дефолтную бд и использовать там динамический sql (вообще не прикалывает такая перспектива)
  • sniknik © (10.11.08 22:37) [35]
    > Кроме того в 20 посте было
    и там же было ParamCount, про что в [31] писал.

    > собственно есть выбор из трех альтернатив:

    > [31] но это кстати не объясняет почему создание этих параметров у тебя не работает.
    самостоятельное создание параметров тоже должно работать, всего то убрать из "неправильного" кода в [0] глюки (раз уж "правильный" не подходит) и все.
 
Конференция "Базы" » TADOCommand + MSSQL + SP [D7, MSSQL]
Есть новые Нет новых   [134477   +39][b:0.001][p:0.001]