TUniStoredProc - задаёт всем параметрам NULL

Обсуждение возникших проблем, предложений и ошибок UniDAC компонентов
Закрыто
Valery.B
Сообщения: 11
Зарегистрирован: Пн 04 июл 2016 15:13

TUniStoredProc - задаёт всем параметрам NULL

Сообщение Valery.B » Ср 06 июл 2016 11:39

Добрый день.
Есть база MS SQL 2014 и хранимая процедура, которую я пытаюсь вызвать через TUniStoredProc.
Я не заполняю никаких параметров, но ХП выполняется(что значительно усложняет отладку). Хотя должна выдать ошибку.

Как TUniStoredProc получает список параметров ?
Как сделать так, что бы он его не получал и выдавал ошибку в случае отсутствия параметров ?

ViktorV
Devart Team
Сообщения: 212
Зарегистрирован: Чт 31 июл 2014 09:52

Re: TUniStoredProc - задаёт всем параметрам NULL

Сообщение ViktorV » Ср 06 июл 2016 15:07

Для решения вашей задачи вы можете использовать следующий код:

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

  UniStoredProc.ParamCheck := False;
  UniStoredProc.StoredProcName := 'SPName';
  UniStoredProc.Prepare;
  UniStoredProc.Params.Clear;
После этого вам следует создавать параметры вручную.
Пожалуйста, обратите внимание, что, если параметр создан и вы не присваиваете ему значение, то по умолчанию значение параметра установится в NULL.

Valery.B
Сообщения: 11
Зарегистрирован: Пн 04 июл 2016 15:13

Re: TUniStoredProc - задаёт всем параметрам NULL

Сообщение Valery.B » Чт 07 июл 2016 10:33

Добрый день!
Спасибо за ответ.

Если я правильно понимаю, то UniStoredProc.Prepare соединяется с сервером и запрашивает у него параметры ? Это некий аналог ADO.Parameters.Refresh.

Что бы не обращаться к серверу лишний раз, у нас список параметров ХП закеширован на другом сервере в виде XML файла(С ним также работают другие программы на C#), и повторно кэшируется на клиентском приложении.

Можно сделать так, что UniDAC не запрашивал параметры ?

ViktorV
Devart Team
Сообщения: 212
Зарегистрирован: Чт 31 июл 2014 09:52

Re: TUniStoredProc - задаёт всем параметрам NULL

Сообщение ViktorV » Чт 07 июл 2016 13:27

Вы можете использовать компоненты TUniQuery или TUniSQL. Установив свойство ParamCheck в False и необходимый вам SQL запрос в свойстве SQL.Text соответствующих компонентов вам не надо будет вызывать методы Prepare и Params.Clear для решения вашей задачи.

Valery.B
Сообщения: 11
Зарегистрирован: Пн 04 июл 2016 15:13

Re: TUniStoredProc - задаёт всем параметрам NULL

Сообщение Valery.B » Чт 07 июл 2016 14:53

Попробовал сделать как вы сказали.

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

var
Query  : TUniQuery;
...
Query.SQL.Text:='spui_GetItemById';
Query.Params.CreateParam(ftInteger,'@ItemID',ptInput).AsInteger:=42;
Query.Open;
Но в таком случае ошибка возникает даже тогда, когда параметр присутствует.
Можно конечно заменить текст на 'spui_GetItemById 42', но тогда возможна SQL инъекция (если параметр берётся из контролов).

Можно сделать так, когда параметр отсутствует - ошибка. Когда присутствует - исполнятся. Без дополнительных обращений к базе.

ViktorV
Devart Team
Сообщения: 212
Зарегистрирован: Чт 31 июл 2014 09:52

Re: TUniStoredProc - задаёт всем параметрам NULL

Сообщение ViktorV » Пт 08 июл 2016 09:17

Для решения задачи, пожалуйста, попробуйте в вашем примере заменить строку

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

Query.SQL.Text:='spui_GetItemById';
на

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

Query.SQL.Text:='spui_GetItemById @ItemID = :ItemID';

Valery.B
Сообщения: 11
Зарегистрирован: Пн 04 июл 2016 15:13

Re: TUniStoredProc - задаёт всем параметрам NULL

Сообщение Valery.B » Пт 08 июл 2016 13:32

Добрый день!

Мы ищем замену ClientDataSet
И не можем переделать весь проект на аналогичный код.
Кроме того, мы считаем подобный код не совсем безопасным в плане SQL инъекций.

Если я правильно понимаю, то заставить компонент TUniStoredProc НЕ обращаться за списком параметров - нельзя ?

ViktorV
Devart Team
Сообщения: 212
Зарегистрирован: Чт 31 июл 2014 09:52

Re: TUniStoredProc - задаёт всем параметрам NULL

Сообщение ViktorV » Пт 08 июл 2016 14:30

Для того, чтобы компонент TUniStoredProc не запрашивал параметры у сервера, вы можете устанавливать свойство TUniStoredProc.SQL.Text вместо свойства TUniStoredProc.StoredProcName. Например:

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

var
UniStoredProc  : TUniStoredProc;
...
UniStoredProc := TUniStoredProc.Create(nil);
try
  UniStoredProc.Connection := UniConnection1;
  UniStoredProc.ParamCheck := False;
  UniStoredProc.SQL.Text := 'EntityGet @ID = :ID';
  UniStoredProc.Params.CreateParam(ftInteger,'@ID',ptInput).AsInteger:=1;
  UniStoredProc.ExecProc;
finally
  UniStoredProc.Free;
end;

Закрыто