![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
параметрические запросы в ADO. что я упустил7 [D7, 95/98]
umbra © (2007-12-24 12:44:00)есть адодатасет
dsMain, у которого в коллекции Parameters создано 5 параметров
name типа ftString
date типа ftDate
dtindex типа ftInteger
nmindex типа ftInteger
rjnumber типа ftString;
База аксессовская,dsMain.ParamCheck = true;
Сперва выполняется следующий код:
procedure TdmBaseLink.SetAccount(const Value: String);
begin
if FAccount = '' then
begin
FAccount := Value;
with dsMain do
begin
//это контейнер для хранения параметров
FParameters[0].Value := Value;
Parameters[0].Value := Value;
CommandText := 'SELECT Counter FROM accounts ' +
'WHERE accname=:name';
//здесь, как я понимаю, dsMain.Parameters.Count = 1
Open;
FParameters[3].Value := Fields[0].AsInteger;
Close;
//восстанавливаем состояние параметров
RestoreParams;
end;
end;
end;
эта процедура отрабатывает без проблем. Далее выполняется следующая
function TdmBaseLink.DateExists: Boolean;что я упускаю? в отладчике видно, что значения у параметров есть.
begin
Result := True;
with dsMain do
begin
CommandText := 'SELECT dtcounter FROM dates ' +
'WHERE (accdate=:date) AND (AccName=:nmindex)';
//здесь dsMain.Parameters.Count = 1
Open;//здесь получаем сообщение о том, что не всем
//параметрам присвоено значение
if not Bof then
Result := False
else
begin
FParameters[2].Value := Fields[0].AsInteger;
end;
Close;
RestoreParams;
end;
end;
umbra (2007-12-24 17:57:00) [1]Все дело оказалось в том, что в таблице Accounts поле-счетчик я назвал Counter Усиленно читая справку, я обнаружил, что это зарезервированное слово
Изменил название поля и все прошло. :)
sniknik (2007-12-24 17:05:00) [2]> На момент открытия все параметры уже имеют нужные значения.
если бы было так то этого
> получаем сообщение о том, что не всем параметрам присвоено значение
бы не было...
а пока, по коду, сообщение логичное, параметрам значения не присваивается и сообщение о том же.
> если AccName - подстановочное значение из другой таблицы, связанное по счетчику
у тебя в запросе нет связи, подстановочного значения которое делает аксесс, ... банальная, плоская таблица (ели цель получить аналог запроса в аксесс), есть только поле связи (раз говориш это оно). подставлять естественно нужно значение того же типа, что поле по которому связь, а не того, которое аксесс ставит на его место (у тебя его и нет, т.что выбор из одного варианта).
umbra (2007-12-24 15:27:00) [3]
> .е. даже если ты там их правильно восстанавливаешь
в отладчике видно, что количество параметров, их значения и порядок - правильные.
> 'WHERE (accdate=:date) AND (AccName=:nmindex)';
кстати, если AccName - подстановочное значение из другой таблицы, связанное по счетчику, то правильно ли я понимаю, что в запрос надо подставлять значение счетчика? В самом аксесе, по крайней мере, надо подставлять именно значение счетчика.
umbra (2007-12-24 15:21:00) [4]
> странно то, что RestoreParams у тебя вызывается после Open;
оно всегда и должно быть после Open. На момент открытия все параметры уже имеют нужные значения. На самом деле вся эта возня - это последовательная инициализация этих самых параметров на основе уже инициализированных. Первой всегда вызываетсяTdmBaseLink.SetAccount. В ней происходит первое обращение к базе и в ней входящий параметр присваивается иdsMain.Parameters[0].ValueиFParameters[0].Value. После этого везде значения присваиваются толькоFParameters[х].Value, а после закрытия датасета вызываетсяRestoreParams.
sniknik (2007-12-24 15:07:00) [5]> после RestoreParams значения оказываются в dsMain.Parameters Так что ничего странного нет :)
странно то, что RestoreParams у тебя вызывается после Open;, т.е. даже если ты там их правильно восстанавливаешь то все одно поздновато будет.
umbra (2007-12-24 13:37:00) [6]
> это не значит что поставив false ты сохранишь предустановленные
> значения, нет, это будет значить, что автопарсинг/автосоздание
> убираются и задача по инициализации ложится на программиста
> (by hand)...
да это я уже понял. Просто я думал, что сработает следующая схема - значения и типы параметров хранятся в отдельном списке. После каждого изменения текста запроса приParamCheck = true;в датасете остается столько параметров, сколько в тексте запроса. Поэтому, после закрытия датасета из списка в датасет добавляются все параметры, со всеми готовыми значениями, а при следующем запросе остаются только нужные. Но что-то все не так просто, наверное.
На самом деле все это - сбор вспомогательной информации, хранящейся в базе и нужной приложению.
umbra (2007-12-24 13:26:00) [7]> //здесь dsMain.Parameters.Count = 1
а должно бы быть 2, т.к. их два в запросе
имелось в видуdsMain.Parameters.Count = 2Копипаст подвел :)
да ты их вообще не задаешь...
они задаются в сеттерах свойств и хранятся в спискеFParameters. после RestoreParams значения оказываются вdsMain.ParametersТак что ничего странного нет :)
> а должен сразу после внесения запроса (не до!!!).
именно так? просто ДО присвоения текста запроса у меня есть 5 параметров, после присвоения - столько, сколько параметров в тексте запроса.
sniknik (2007-12-24 13:24:00) [8]> тк. ParamCheck = true;
это не значит что поставив false ты сохранишь предустановленные значения, нет, это будет значить, что автопарсинг/автосоздание убираются и задача по инициализации ложится на программиста (by hand)...
sniknik (2007-12-24 13:17:00) [9]при присвоении запроса CommandText-у параметры пере-инициализируются (тк. ParamCheck = true;)
> //здесь dsMain.Parameters.Count = 1
а должно бы быть 2, т.к. их два в запросе
> ...
> 'WHERE (accdate= :date) AND (AccName= :nmindex)';
> что я упускаю?
да ты их вообще не задаешь... а должен сразу после внесения запроса (не до!!!).
> в отладчике видно, что значения у параметров есть.
а вот это странно... как и со счетчиком параметров, уверен что смотришь туда куда надо?
umbra (2007-12-24 12:59:00) [10]
> А на самом деле как?
>
именно так
> Так а тут что?
>
procedure TdmBaseLink.RestoreParams;
begin
FParameters.RestoreDatasetParams(dsMain);
FParameters.RestoreCommandParams(cmdMain);
end;
FParametersимеет типTSimpleParams
TSimpleParams = class
private
FParams: TObjectList;
function GetItem(index: Integer): TSimpleParam;
procedure SetItem(index: Integer; const Value: TSimpleParam);
function GetCount: Integer;
public
constructor Create; reintroduce; virtual;
destructor Destroy; override;
function Add: TSimpleParam;
procedure Delete(item: Integer);
function Insert(before: Integer): TSimpleParam;
procedure RestoreDatasetParams(target: TADODataSet);
procedure RestoreCommandParams(target: TADOCommand);
property Items[index: Integer]: TSimpleParam read GetItem write SetItem; default;
property Count: Integer read GetCount;
end;
procedure TSimpleParams.RestoreDatasetParams(target: TADODataSet);
var
i: Integer;
tmp: TParameter;
begin
with target.Parameters do
begin
Clear;
for i := 0 to FParams.Count - 1 do
begin
tmp := Add as TParameter;
Self[i].AssignTo(tmp);
end;
end;
end;
RestoreCommandParamsполностью аналогично, только параметрі добавляются вADOCommand
Kolan (2007-12-24 12:50:00) [11]> //восстанавливаем состояние параметров
> RestoreParams;
Так а тут что?
Kolan (2007-12-24 12:48:00) [12]> //здесь, как я понимаю, dsMain.Parameters.Count = 1
А на самом деле как?