Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Базы данных и репортинг > обновление данных


Автор: offline 9.3.2005, 11:15
Мастера, подскажите, как сделать лучше.
У меня есть база Access и я подключаюсь к ней через ADO. В Access я создал запрос показать все из таблицы Tab1 и в Delphi подключился к этому запросу как к таблице. Данные выводятся в DBGrid.
У меня такая задача, по нажатию клавиши произвести групповую замену в Tab1. Соответственно я это делаю через запрос на обновление.
После этого запроса, приходится перечитывать данные, т.к. DBGrid отображает старую информацию. Что я делаю.

1.Отключаю визуальный контроль от ADOTable1
2.запоминаю значение ключевого поля на котором находится указатель
3.вызываю ADOTable1.Requery
4.перемещаюсь на запись на которой был курсор через ADOTable1.Locate
5.Включаю визуальный контроль на ADOTable1

В связи с этим у меня вопрос. Что лучше использовать Locate или ставить до Requery закладку, а после Requery перемещаться на не? А вообще можно каким либо другим способом перечитать данные не используя Requery и при этом остаться на текущей записи? Метод ADOTable1.Refresh не помогает.


И еще вопрос. Подскажите, что лучше: создавать вычисляемые поля или обрабатывать то же самое в ADOTable1.AfterScroll при условии, что данные ни где не используются, а просто выводятся на форму?

Заранее благодарю



Автор: DimW 9.3.2005, 12:34
Я делаю так:
Код

var
n:integer;
begin
n:=Tab1.RecNo;
Query.close;
Query.Parametrs.ParamByName('pID').Values:=25114; //параметр передается селекту
Query.open;
if Query.RecordCount>=n then Tab1.RecNo:=n;
end;


ни когда не пересчитывал значения на этом событии ADOTable1.AfterScroll, видимо значение пересчитывается на активную запись.....(ели я правильно понял....)

Используй вычислимые поля, по моему удобная способ:
Двойной щелчек на TTable или TQuery, New Field---> Name='NameSum' ---> DataType='Float' (Field Type выстави calculated).
Событие OnCalcFields:

Код

procedure TForm1.Table1CalcFields(DataSet: TDataSet);
begin
Table1.FieldByName('NameSum').AsFloat:=Table1.FieldByName('Name1').AsFloat+Table1.FieldByName('Name2').AsFloat;
end;




Автор: offline 9.3.2005, 12:55
По вычесляемым полям я знаю, как они создаются и где обрабатываются. smile
Да, действительно, значение пересчитывается на активной записи. Просто я хочу узнать, как быстрее это пересчитывать, на ADOTable1.AfterScroll или как вычисляемое поле, что быстрее работает. Насколько я понимаю., вычисляемое поле будет применятся ко всем полям, а это займет время, а мне нужно только текущее. Или я ошибаюсь?

А по поводу кода
Код

var
n:integer;
begin
n:=Tab1.RecNo;
Query.close;
Query.Parametrs.ParamByName('pID').Values:=25114; //параметр передается селекту
Query.open;
if Query.RecordCount>=n then Tab1.RecNo:=n;
end;


Я что то не понял, я поизвожу групповую замену запросом на обновление, а не одно значение текущей записи.

Автор: Петрович 9.3.2005, 13:25
Обновление делаешь правильно.

Цитата(kirilllius @ 9.3.2005, 12:15)
Что лучше использовать Locate или ставить до Requery закладку

Раз у тебя есть ключевое поле однозначно идентифицирующее тек.запись то естественно использование Locate теоретически более правильно. Однако, надо учитывать что если тек.запись была удалена, то Locate после Requery ее не найдет, и спозиционирует тебя не туда куда ты ожидаешь.
С закладками, тоже есть проблемы. Если подойти формально, то сохраненная закладка после Requery становится недействительной. Однако, из опыта скажу что закладка в большинстве реализаций это просто номер записи. Соответственно, если сохранить ее до Requery а потом попытаться "прыгнуть" на нее, то опять-же результат будет не всегда ожидаемым. Например была таблица:
Код
1 Запись1
2 Запись2
3 Запись3
Предположим текущей была запись2. Тогда, если она была удалена, после чего сделано:
Код
s := Bookmark;
Requery;
Bookmark := s;

Тогда, текущей станет последняя запись в наборе:
Код
1 Запись1
3 Запись3

Казалось бы, такое поведение более логично чем при использовании Locate. Но, тогда надо обрабатывать ситуацию, когда номер сохраненной записи станет больше чем общее число записей после Requery. Например до Requery тек.позиция была на последней записи набора:
Код
1 Запись1
2 Запись2
3 Запись3

Потом Запись3 удалили, и сделали:
Код
s := Bookmark;
Requery;
Bookmark := s;

В этом случае, при выполнении Bookmark := s возникнет исключение, которое надо будет самому обработать.

Лично я предпочитаю последний вариант - через закладки, с обработкой исключения при Bookmark := s.

Автор: DimW 9.3.2005, 14:16
Цитата

при этом остаться на текущей записи?


это предложил вариант как оставить на текущей записи....

Автор: bursa 9.3.2005, 16:15
Цитата
Насколько я понимаю., вычисляемое поле будет применятся ко всем полям, а это займет время, а мне нужно только текущее. Или я ошибаюсь?

Вычисление будет производиться в видимых СТРОКАХ (OnCalcFields). Если хочешь, чтобы вычислялось не во всех ПОЛЯХ, используй проверку
Код

if DBGrid1.SelectedField=Table1.FieldByName('Field'), 

где Field-изменяемое поле

или другой спсоб (если нужно вычислять и хранить)
использовать метод OnChange самого Поля

Код

procedure TForm1.Table1FieldChange(Sender: TField);
begin
with table1 do begin
if fieldByName('').asfloat<>0 then
FieldByName('').asfloat:=
  round(FieldByName('').asfloat*
  FieldByName('').asfloat*
  FieldByName('').asfloat/
... ;
end;
end;


А что быстрей и правильней зависит от задачи.

Автор: offline 9.3.2005, 19:57
Цитата
Однако, надо учитывать что если тек.запись была удалена, то Locate после Requery ее не найдет, и спозиционирует тебя не туда куда ты ожидаешь.


Я произвожу запрос на обнавление и следовательно записи у меня не удаляются. Поэтому наверное особой разницы нет, Locate или Bookmark. Просто с Locate меньше кода писать smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)