Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Оптимальное обновление данных, нужен совет 
:(
    Опции темы
DDX
Дата 29.7.2005, 09:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 127
Регистрация: 31.1.2005
Где: Москва

Репутация: 5
Всего: 5



используется MS SQL Server, Delphi 7, ADO

все манипуляции с данными (insert, update,delete) происходят путем вызова хранимых процедур сервера.

здесь и хочу спросить вашего совета: каким образом после обновления данных лучше обновлять даные в maste/detail гридах на форме? источником данных для master грида служит запроc (ADOQuery), для подчиненного - view-таблица с сервера (TADOTable)

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


--------------------
Учиться, учитьcя и ещё раз учиться  
PM MAIL WWW   Вверх
Bes
Дата 29.7.2005, 09:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 806
Регистрация: 8.12.2004

Репутация: 2
Всего: 7



я делаю так
Код

Var
   b:TBookmark;
Begin
     b:=adoquery.getbookmark;
     adoquery.active:=false;
     adoquery.active:=true;
     adoquery.gotobookmark(b);
     b.free;//вот про эту строчку не помню есть она или нет
end;

а что такое с лагом ?

Это сообщение отредактировал(а) Bes - 29.7.2005, 09:59
PM MAIL   Вверх
DDX
Дата 29.7.2005, 10:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 127
Регистрация: 31.1.2005
Где: Москва

Репутация: 5
Всего: 5



спасибо за ответ!

с лагом = с небольшой задержкой, т.е. нажимаешь кнопочку "добавить" или изменить, и наблюдаешь изменения в гриде не сразу, а через 1-2 секунды. немного напрягает, тем более, что юзер обычно туп и ненаблюдение изменений мгновенно вводит его в ступор
--------------------
Учиться, учитьcя и ещё раз учиться  
PM MAIL WWW   Вверх
Bes
Дата 29.7.2005, 11:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 806
Регистрация: 8.12.2004

Репутация: 2
Всего: 7



сколько записей в таблице?
PM MAIL   Вверх
Петрович
Дата 29.7.2005, 17:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1000
Регистрация: 2.12.2003
Где: Москва

Репутация: 6
Всего: 55



Bes, твой код хорошь, но иногда может вызвать Exception!
Увы, сам на это наткнулся.
Например, стоишь на последней записи, отдельным запросом удаляешь ее, и потом выполняешь твой код.
Вынужден был городить огород с locate. Причем, даже DBGridEh в EhLib'е для этого доработал. (см. здесь)
Но, и там тоже есть пробдлемы - Ошибка TADODataSet.Locate!, проверено в Delphi 6,7,9.

Так что, на сегодня, универсального решения нет. Лично у меня, все таблицы имеют ключевое поле, причем, всегда первое. Этому полу назначено Visible=False, поэтому его не видно. Перед закрытием датасета я сохраняю его значение, и после открытия делаю locate на него.
Если интересует, могу выложить новую доработку DBGridEh в EhLib'е, которая позволяет указывать как искать текущую запись:
добавлено:
Код
type
  TDBGridEhSavePosition = ( // какие поля однозначно идентифицируют запись для
                         // сохранания/восстановления позиции при обновлении, пересортировке и перефильтрации
        gspNone          // не сохранять позицию (по умолчанию)
       ,gspByFirstField  // первое поле в наборе данных (datasource.dataset.fields[0])
       ,gspByAllFields   // все поля
       ,gspByKeyFields   // поля для которых в ProviderFlags установлен pfInKey
       ,gspByWhereFields // поля для которых в ProviderFlags установлен pfInWhere
       );
...
    property SavePosition :TDBGridEhSavePosition read FSavePosition write FSavePosition default gspNone;


Это сообщение отредактировал(а) Петрович - 29.7.2005, 17:55


--------------------
Все знать невозможно, но хочется
PM ICQ   Вверх
Bes
Дата 1.8.2005, 06:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 806
Регистрация: 8.12.2004

Репутация: 2
Всего: 7



2Петрович:
да-да забыл про это - я решил проблему так
вместо
Код

adoquery.gotobookmark(b);

надо писать
Код

try
   adoquery.gotobookmark(b);
except
end;

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

Это сообщение отредактировал(а) Bes - 1.8.2005, 06:42
PM MAIL   Вверх
DDX
Дата 2.8.2005, 12:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 127
Регистрация: 31.1.2005
Где: Москва

Репутация: 5
Всего: 5



спасибо за советы, букмарки - хорошее решение

единственно, что интересно: если данные отсортированы по алфавиту и добавляется новая запись, то возможно ли установить выделение на неё smile

Петрович, если можешь, выложи, или пришли на почту: ddx{песик}.mail.ru,спасибо.
или, может, тоже самое можно скачать из указанной тобой темы?
--------------------
Учиться, учитьcя и ещё раз учиться  
PM MAIL WWW   Вверх
Петрович
Дата 2.8.2005, 13:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1000
Регистрация: 2.12.2003
Где: Москва

Репутация: 6
Всего: 55



Цитата(DDX @ 2.8.2005, 13:25)
Петрович, если можешь, выложи, или пришли на почту: ddx{песик}.mail.ru,спасибо.
или, может, тоже самое можно скачать из указанной тобой темы?

Вот объект:
Код
/////////////////////////////////////////////////////////////////// tSaveContext
//
// Объект используемый для сохранения/восстановления состояния грида.
//

type
  tSaveContext = class
    private
      Grid         :TCustomDBGridEh;
      FieldsList   :String;           // Список полей DataSet'а
      FieldsValues :{array of }Variant; // Список значений текущей записи
      SaveIsStored :array of Boolean; // Список значений IsStored всех колонок
      ActiveRow    :Integer;          // Номер текущей строки грида
    public
      constructor SaveGridContext (aGrid :TCustomDBGridEh);
      procedure RestoreGridContext;
    end;

constructor tSaveContext.SaveGridContext (aGrid :TCustomDBGridEh);
var i,o :Integer;
begin
  inherited Create;
  Grid := aGrid;

  // Если набор данных закрыт, сохранять нечего
  if   not Assigned(Grid.DataSource)
    or not Assigned(Grid.DataSource.DataSet)
    or not Grid.DataSource.DataSet.Active  then
      Exit;

  // сохранить список имен и значений ключевых полей текущей записи для восстановления позиции
  FieldsList := '';
  with  Grid.DataSource.DataSet  do begin
    case  aGrid.SavePosition  of
      gspNone : ;
      gspByFirstField : with  Fields[0]  do begin
          FieldsList   := FieldName;
          FieldsValues := Value;
        end;
      else begin
          FieldsValues := VarArrayCreate([0, Fields.Count-1], varVariant);
          o := -1;
          for i:=0  to  Fields.Count-1  do with  Fields[i]  do begin
            if   (aGrid.SavePosition = gspByAllFields)
             or ((aGrid.SavePosition = gspByKeyFields  ) and (pfInKey   in ProviderFlags))
             or ((aGrid.SavePosition = gspByWhereFields) and (pfInWhere in ProviderFlags))
             then begin
              Inc(o);
              FieldsList      := FieldsList + FieldName + ';';
              FieldsValues[o] := Value;
            end;
          end;
          System.Delete(FieldsList,Length(FieldsList),1);
          if  o = 0  then
            FieldsValues := FieldsValues[0];
      end;
    end;
//    SetLength(FieldsValues,Fields.Count);
//    for i:=0  to  Fields.Count-1  do with  Fields[i]  do begin
//      FieldsList      := FieldsList + FieldName + ';';
//      FieldsValues[i] := Value;
//    end;
//    Delete(FieldsList,Length(FieldsList),1);
  end;

  // Сохранить признак динамического создания для всех колонок,
  with  Grid  do begin
    SetLength(SaveIsStored,Columns.Count);
    for i:=0  to  Columns.Count-1  do with Columns[i] do begin
      SaveIsStored[i] := IsStored;
      IsStored := True;
    end;
  end;

  // Сохранить номер текущей строки грида
  ActiveRow := Grid.DataLink.ActiveRecord;
end;

procedure tSaveContext.RestoreGridContext;
var i :Integer;
begin
  try
    // Востановить признак динамического создания для всех колонок,
    for i:=0  to  Length(SaveIsStored)-1  do
      Grid.Columns[i].IsStored := SaveIsStored[i];

    // Если набор данных закрыт, например не смог открыться после изменения
    // запроса, то надо уничтожить все динамически создаваемые колонки.
    // Обычно это делает сам набор данных при закрытии. Но, в данном случае,
    // мы сами не дали ему это сделать. Придется делать это здесь
    if   not Assigned(Grid.DataSource)
      or not Assigned(Grid.DataSource.DataSet)
      or not Grid.DataSource.DataSet.Active  then begin
        for i := Grid.Columns.Count-1 downto 0 do
          with Grid.Columns[i] do if not IsStored then Free;
      end
    // Если-же набор данных открыт, и есть список полей записи текущей на
    // момент сохранения, то надо попытаться переместиться на нее.
    // Если это получится (есть запись), то попытаться передвинуть ее строку
    // которая была текущей на момент сохранения.
    else if  Length(FieldsList) > 0  then
      if  Grid.DataSource.DataSet.Locate(FieldsList,FieldsValues,[])  then
        Grid.FDatalink.Dataset.MoveBy(-Grid.FDatalink.Dataset.MoveBy(Grid.DataRowCount-1-ActiveRow));
  except
    // Ошибки в данном случае не повод для беспокойства, просто не сохранится
    // позиция в датасете и/или маркеры сортировки.
  end;
  Free;
end;
////////////////////////////////////////////////////////////////////////////////

А вот как им пользоваться:
Код

  with  tSaveContext.SaveGridContext(AGrid)  do try
    AGrid.DataSource.DataSet.Close;
    AGrid.DataSource.DataSet.Open;
 finally
    RestoreGridContext;
  end;



--------------------
Все знать невозможно, но хочется
PM ICQ   Вверх
DDX
Дата 2.8.2005, 16:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 127
Регистрация: 31.1.2005
Где: Москва

Репутация: 5
Всего: 5



Петрович
сенкс

Это сообщение отредактировал(а) DDX - 2.8.2005, 17:12
--------------------
Учиться, учитьcя и ещё раз учиться  
PM MAIL WWW   Вверх
Akella
Дата 9.8.2005, 13:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: 29
Всего: 329



Код

Var
   b:TBookmark;
Begin
     b:=adoquery.getbookmark;
     adoquery.active:=false;
     adoquery.active:=true;
//не забывай про BookMarkValid и исключений не будет
!!!     if adoquery.BookMarkValid(b) then
       adoquery.gotobookmark(b);

     b.free;//вот про эту строчку не помню есть она или нет
end;


PM MAIL   Вверх
Bes
Дата 9.8.2005, 14:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 806
Регистрация: 8.12.2004

Репутация: 2
Всего: 7



Ух ты! Спасибо. Век живи - век учись. smile

PM MAIL   Вверх
AntonSaburov
Дата 9.8.2005, 14:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Штурман
****


Профиль
Группа: Модератор
Сообщений: 5658
Регистрация: 2.7.2002
Где: Санкт-Петербург

Репутация: нет
Всего: 118



Что-то опасно как-то сделано - с букмарками это плохое решение. Это же указатели. И гарантированно работать они не будут. Лучше тогда использовать поле ID какое-нибудь (ну чтобы в базе было) и уже по нему делать Locate.

А букмарки - это же указатели. Их к тому же освобождать надо. Не советую.
PM MAIL WWW ICQ   Вверх
Akella
Дата 9.8.2005, 14:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: 29
Всего: 329



Цитата(AntonSaburov @ 9.8.2005, 14:28)
Что-то опасно как-то сделано - с букмарками это плохое решение.

а нафига ж их придумали? smile
Добавлено @ 14:33
Цитата(AntonSaburov @ 9.8.2005, 14:28)
А букмарки - это же указатели. Их к тому же освобождать надо. Не советую.

что, освобождать не советуешь?

Программеры там, у дяди Бормана, сидят и головы ломают, как сделать то или иное, а мы тут умничать начинаем smile

smile
Как в КВН было сказано про футбол: "Вся страна специалисты, одни мы, 11 человек играть не умеем".
PM MAIL   Вверх
AntonSaburov
Дата 9.8.2005, 14:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Штурман
****


Профиль
Группа: Модератор
Сообщений: 5658
Регистрация: 2.7.2002
Где: Санкт-Петербург

Репутация: нет
Всего: 118



Цитата(dsergey @ 9.8.2005, 14:30)
а нафига ж их придумали?

Их удобно использовать, если например надо пробежать по всему DataSet и сосчитать сумму. Или еще чего. Но на это время сам DataSet не закрывается. В этом случае букмарки - штука очень удобная и наверно самая быстрая.
PM MAIL WWW ICQ   Вверх
Akella
  Дата 9.8.2005, 14:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: 29
Всего: 329



Программист сам в праве выбирать, что ему использовать: закладки или locate smile
Добавлено @ 14:37
Цитата(AntonSaburov @ 9.8.2005, 14:34)
Их удобно использовать, если например надо пробежать по всему DataSet и сосчитать сумму. Или еще чего. Но на это время сам DataSet не закрывается.

я и с закрытием DataSet`a использую закладки, пока проблем небыло.

Код

Var
   b:TBookmark;
Begin
  try
     b:=adoquery.getbookmark;
     adoquery.active:=false;
     adoquery.active:=true;
     if adoquery.BookMarkValid(b) then
       adoquery.gotobookmark(b)
    else
       adoquery.First;//или adoquery.last;
  finally
     adoquery.FreeBookMark(b);
  end;   //try
end;



Это сообщение отредактировал(а) dsergey - 9.8.2005, 14:41
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Базы данных и репортинг"
Vit
Петрович

Запрещено:

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами


Обязательно указание:

1. Базы данных (Paradox, Oracle и т.п.)

2. Способа доступа (ADO, BDE и т.д.)


  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи
  • Вопросы по SQL и вопросы по базам данных не связанные с Дельфи задавать здесь

FAQ раздела лежит здесь!


Если Вам помогли и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, Vit, Петрович.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Базы данных и репортинг | Следующая тема »


 




[ Время генерации скрипта: 0.1262 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.