-
Похоже уже глаз замылился. Есть MSSQL, работаю через ODBC (так надо). Есть таблица create table testtbl (uid int) Есть некий класс TDBConnector с методом
function TDBConnector.DBExecCommand(ac: TADOCommand): Boolean;
begin
Result := False;
if FState<>csConnected then Exit;
try
ac.Connection := FConnection;
try
ac.Execute;
Result := True;
except on E : Exception do
OnException('TDBConnector.DBExecCommand : ' + E.message);
end;
finally
ac.Connection := nil;
end;
end;
т.е. приняли на вход ADOCommand, проверили состояние коннекта, исполнили команду, отцепили от неё коннекшн. Бросаю на форму TADOCommand. выставляю в дизайн-тайм ParamCheck=False; CommandText = insert into testtbl (uid) values (:uid) Ручками в дизайн-тайм добавляю параметр uid, выставляю Direction, DataType и Size. В ран-тайм выполняю код:
procedure TForm2.Button4Click(Sender: TObject);
var
paran : TParameter;
begin
param := ADOCommand1.Parameters.FindParam('uid');
if param=nil then
begin
param := ADOCommand1.Parameters.AddParameter;
param.Name := 'uid';
param.DataType := ftInteger;
param.Direction := pdInput;
param.Size := 4;
end;
ADOCommand1.Parameters.ParamByName('uid').Value := 10;
if FConn.DBExecCommand(ADOCommand1) then
ShowMessage('OK')
else
ShowMessage('Fail');
end; всё ОК. Добавляю в начало метода строчку ADOCommand1.Parameters.Clear; Всё ОК. А вот теперь беру и делаю так: В дизайн-тайм кладу чистый TADOCommand, не выставляю ему никаких свойств. Код метода:
procedure TForm2.Button4Click(Sender: TObject);
var
paran : TParameter;
begin
ADOCommand1.ParamCheck := False;
ADOCommand1.CommandText := 'insert into testtbl (uid) values (:uid)';
ADOCommand1.Parameters.Clear;
param := ADOCommand1.Parameters.FindParam('uid');
if param=nil then
begin
param := ADOCommand1.Parameters.AddParameter;
param.Name := 'uid';
param.DataType := ftInteger;
param.Direction := pdInput;
param.Size := 4;
end;
ADOCommand1.Parameters.ParamByName('uid').Value := 10;
if FConn.DBExecCommand(ADOCommand1) then
ShowMessage('OK')
else
ShowMessage('Fail');
end;
Выполняю, на Execute вижу ошибку Incorrect syntax near ':' В профайлере на сервер запрос долетает в виде 'insert into testtbl (uid) values (:uid)' Что не так делаю?
-
Непонятно зачем ты вообще устраиваешь пляски с бубном вокруг параметров - чем не устроила стандартная схема ? Ну и чисто "профилактика": не стОит обзывать параметры именами, совпадающими с именами полей - достаточно вставлять какой-нибудь префикс (я использую буковку "р")
-
Грубо говоря, если ParamCheck=False, то добавление параметров отдано на откуп программиста. Что ты и делаешь. Если же ParamCheck=True, то коллекция параметров генерится автоматом, и добавление их "руками" ни смысла, ни ожидаемого эффекта не имеет...
ЗЫ Сабж надо рассматривать чисто с позиции академического интереса. Ибо автомат - наше всё :)
-
> Непонятно зачем ты вообще устраиваешь пляски с бубном вокруг > параметров - чем не устроила стандартная схема ?
Тем, что у меня вообще не оконное приложение. И в дизайн-тайме я ничего выставить не могу.
> Если же ParamCheck=True, то коллекция параметров генерится > автоматом, и добавление их "руками" ни смысла, ни ожидаемого > эффекта не имеет...
Это только в том случае, если есть коннект. Если коннекта нет - один фиг ручками.
Нет, вы мне объясните: если я CommandText прописываю 'insert into testtbl (uid) values (10)'; - всё ОК.
Как только я задаю CommandText в ран-тайм и создаю параметр - всё, incorrect syntax
Блин, ну где же Коля? :)
-
страно все это. я просто создаю адокомманд, присваиваю текст в котором :параметры затем Parameters.ParamValues[''] := бла бла бла и все.
-
> страно все это.
Да у меня у самого уже башня едет. Как только ParamCheck=True - всё нормально проходит. Как только снимаю - всё, приехали.
-
а ADOCommand1.Prepared := true не надо сделать во 2-м случае?
-
> Выполняю, на Execute вижу ошибку Incorrect syntax near ':' Ю В профайлере на сервер запрос долетает в виде 'insert into testtbl (uid) values (:uid)' > Что не так делаю? создаешь параметр сам, а синтаксис оставляешь дельфевый (вот если бы ты пользовался дельфевым же препаре, тогда бы сработало (наверное... теоретически)) так должно сработать. ADOCommand1.ParamCheck := False;
ADOCommand1.CommandText := 'insert into testtbl (uid) values (?)';
with ADOCommand1.Parameters.AddParameter do begin
Name := 'uid';
DataType := ftInteger;
Direction := pdInput;
Size := 4;
Value := 10;
end;
-
> так должно сработать. не уверен, тк пользуюсь немного другой формой записи для таких случаев, попроще ADOCommand1.ParamCheck := False;
ADOCommand1.CommandText := 'insert into testtbl (uid) values (?)';
ADOCommand1.Parameters.CreateParameter('uid', ftInteger, pdInput, 0, 10);
ADOCommand1.Execute;
-
В ADO компонентах Delphi при работе с MSSQL есть проблемы, с которыми я недавно столкнулся. Первая из них и состояла в странной работе парсера, который с параметрами разбирается. Например, параметр, созданный в дизайн-тайм после присвоения текста команде теряет свой тип. То есть вместо того чтобы придерживаться списка определенных разработчиком (persistent) параметров и их типов (и ругаться при execute), парсер почему-то заново создает параметры на ходу, как умеет. Это совершенно несандартное поведение компонентов, шокирующее разработчика.
Другим шокирующим меня лично благим намерением ADO стала полная невозможность избавиться от навязчивой манеры поддерживать многотабличную вставку, когда я его об этом вовсе не прошу. Мне так и не удалось победить это явление. Смысл следующий. Имеется команда select, в которой связаны 2 таблицы. Например, справочник товаров и позиции накладной. Хочется получить вставку строки в накладную. Но так как никаких свойств вроде InsertSQL, IpdateSQL и DeleteSQL у ADODataSet нет, он пытается все эти запросы сам как-то сгенерировать, в результате он, естественно, пытается вставлять данные не только в таблицу накладных, но и наименования товаров в справочник товаров, хотя они там уже присутствуют и защищены у меня уникальным ключом.
Никакие советы и способы лечить эту проблему не сработали. Если мне потребуется писать реальный проект под MSSQL, я предпочту компоненты прямого доступа, либо воспользуюсь услугами BDE.
-
> Блин, ну где же Коля? :) работаю, блин!
-
> Никакие советы и способы лечить эту проблему не сработали. Unique Table советовали? проверял?
-
> я предпочту компоненты прямого доступа все компоненты "прямого" доступа для MSSQL работают через OLEDB т.е. тоже ADO только без "обертки", т.е. если они что то могут, а ты на ADO нет, значит просто не разобрался. а они просто привели логику ADO к твоей...
-
комнепонты прямого доступа работают через адо конечно, но именно через адо, а не через делфийское недоразумение вокруг него.
-
>kaif © (03.10.08 17:37) [9] > Другим шокирующим меня лично благим намерением ADO стала полная >невозможность избавиться от навязчивой манеры поддерживать >многотабличную вставку, когда я его об этом вовсе не прошу.
Тебе же, Ашот, ясно было сказано в той ветке, что есть такая фигня, но ты, как тот ёжик, упорно лезешь на кактус..
>Ega23 © (03.10.08 15:35) [3] >Тем, что у меня вообще не оконное приложение.
Причем тут вообще окна-то ?
-
> MsGuns © (04.10.08 02:00) [14] >
> Ну и чисто "профилактика": не стОит обзывать параметры именами, > совпадающими с именами полей - достаточно вставлять какой- > нибудь префикс (я использую буковку "р")
А почему не стоит? Приведи обоснование сему тезису.
-
sniknik © (03.10.08 17:40) [11] > Никакие советы и способы лечить эту проблему не сработали. Unique Table советовали? проверял?
Проверял.
Не вижу, какое отношение имеет OLEDB к проблемам того, что компонент ADO ведет себя нестандартным образом, например, тихаря переопределяет persistent свойства рантайм и не предупреждает об этом в документации. Это то же самое, что заявить, что раз глюкавый оконнный компонент использует нормально работающее в других компонентах API Windows, то значит, что я в нем плохо разобрался, а не компонент глюкавый. На то он и компонент, чтобы вести себя стандартным образом. Для меня компоент это не просто класс - наследник TComponent. Для меня компонент это прежде всего контракт между разработчиком компонента и мной. Контракт, в котором любое нестандартное поведение обязано быть специально оговорено в Help.
Против самого OLEDB ничего не имею.
Как, впрочем, и против компонентов ADO Delphi в иных использованиях. Я сам использовал палитру ADO достаточно часто при работе с dBase-файлами и файлами Access, и она меня там не подводила. Кроме одного случая, когда "благие намерения" ADO перекодировали файлы dBase, в заголовках которых ошибочно устанавливался байт кодировки (в FoxPro была такая проблема) и приходилось этот байт искусственно обнулять для того чтобы обойти эту угодливость ADO, плохо сочетавшуюся с либеральностью FoxPro в отношении этого байта.
MsGuns © (04.10.08 02:00) [14] >kaif © (03.10.08 17:37) [9] > Другим шокирующим меня лично благим намерением ADO стала полная >невозможность избавиться от навязчивой манеры поддерживать >многотабличную вставку, когда я его об этом вовсе не прошу.
Тебе же, Ашот, ясно было сказано в той ветке, что есть такая фигня, но ты, как тот ёжик, упорно лезешь на кактус..
Если кто-нибудь приведет конкретное решение с Unique Table с примером работающего кода, буду признателен. Самому искать больше невмоготу и незачем. Может пригодится остальным участникам форума, решившим сделать ставку на связку ADO Delphi + MSSQL.
Любопытно, что работая с ADO.NET в Visual Studio на C# я не обнаружил вообще никаких проблем. Ничего такого непредвиденного.
-
ADOCommand1.CommandText := 'insert into testtbl (uid) values (?)';
О как... А если их (параметров) насколько, то insert into testtbl (col1, col2) values (?, ?) ?
-
> О как...
Ага, именно так, как описано в справке...:)
-
Parameters[0], Parameters[1], можно присвоить имена параметрам.
|