Форум: "Базы";
Текущий архив: 2008.04.06;
Скачать: [xml.tar.bz2];
ВнизКто как поступает? Найти похожие ветки
← →
zorik © (2007-11-09 12:09) [0]САБЖ. Есть грид. Данные берет с запроса TIBSQL. Запрос только для чтения. Есть кнопки "добавить", "изменить", "удалить". Для редактирования используется второй запрос, куда параметрически передается первичный ключ с первого. При нажатии на кнопку передаем ключ во второй запрос, откриваем модальное окно с dbcontrol-ами, связаными с вторым запросом, что используется для редактирования. При нажатии на ок выпольняется update и подтверждается транзакция. Все отлично работает, но после изменения данных, надо перечитать первый запрос, чтоб увидеть эти изменения. При этом курсор переходит на первую запись. Это не удобно. Я использовал Locate после переоткрытия запроса, но при большом количестве записей это сильно тормозит. Да и выделенная строка грида оказывается в самом низу видимой части грида.
Подскажите какие есть варианты решения?
← →
Desdechado © (2007-11-09 12:13) [1]Использовать кэшированные изменения, например, с ClientDataSet.
← →
Reindeer Moss Eater © (2007-11-09 12:13) [2]bookmark вместо locate
← →
Ega23 © (2007-11-09 12:21) [3]
> bookmark вместо locate
нельзя, у него запись может добавиться.
← →
ЮЮ © (2007-11-09 12:22) [4]> Есть грид. Данные берет с запроса TIBSQL
Как то сомнительно. Или справка Врет?
Description
Use a TIBSQL object to execute an InterBase SQL statement with minimal overhead. TIBSQL has no standard interface to data-aware controls and is unidirectional.
> Для редактирования используется второй запрос, куда параметрически
> передается первичный ключ с первого.
А посему просто не использовать TIBDataSet и его методы Insert, Post, Delete. Т.е. изменять данные "в гриде" и слать соответствующие запросы на сервер, а не наоборот?
← →
Reindeer Moss Eater © (2007-11-09 12:24) [5]нельзя, у него запись может добавиться.
В делфи для этого есть опертор if
← →
Ega23 © (2007-11-09 12:35) [6]По сабжу.
Обычно делаю так:
есть форма, на ней вся выборка. Есть три Action"а: Add, Edit, Delete.
Есть модальная форма, вызывается для добавления записи или изменения записи.
выгдядит приблизительно так:type
TRecordEditForm = class(TForm)
private
FWorkMode : Integer;
procedure SetFWorkMode(const Value : Integer);
procedure btnOKClick(Sender : TObject); // реакция на кнопку OK
public
property WorkMode : Integer read FWorkMode write SetFWorkMode; // 0 - добавляем, 1 - изменяем;
property ID : Integer read FID write FID; // Название ключевого поля
// ещё я, обычно, сюда коннект к БД добавляю, дабы не плодить дополнительных
// хотя если ты DataModule используешь - но не нужно
end;
procedure TRecordEditForm.SetFWorkMode(const Value : Integer);
begin
FWorkMode := Value;
if Value=0
begin // Добавление записи
// заполняем контролы default-значениями
end;
if Value=1
begin // Изменение записи
"select * from ... where ID=" + IntToStr(FID);
выполняем вспомогательный запрос, заполняем все контролы данными из этого запроса
end;
end;
procedure TRecordEditForm.btnOKClick(Sender : TObject); // реакция на кнопку
OK
var
ss : string;
begin
case WorkMode of
0 : ss := "Добавить запись?";
1 : ss := "Изменить запись?";
end;
if not (MessageBox(Handle, PChar(ss), PChar("Внимание!"),
MB_OKCANCEL or MB_ICONINFORMATION)=IDOK) then Exit;
// дальше формируем строку на добавление или изменение записи, в зависимости от WorkMode
// Выполняем обновление.
// Запрос строю таким образом, чтобы при добавлении новой записи мне вернулось значение её ключевого поля.
// Записываем это значение в FID;
Modalresult := mrOK;
end;
← →
Ega23 © (2007-11-09 12:39) [7]соответственно, вызов этого дела из Action"ов:
procedure TMainForm.afAddRecordExecute(Sender: TObject);
begin
Application.CreateForm(TRecordEditForm, RecordEditForm);
try
RecordEditForm.workMode := 0;
RecordEditForm.ShowModal;
if RecordEditForm.ModalResult<>mrOK then Exit;
RefreshData; // обновляем данные основного запроса
DataSet.Locate("ID", RecordEditForm.ID, []) ;
finally
TRecordEditForm.Free;
end;
end;
procedure TMainForm.afEditRecordExecute(Sender: TObject);
begin
Application.CreateForm(TRecordEditForm, RecordEditForm);
try
RecordEditForm.workMode := 1;
RecordEditForm.ID := DataSet.FieldByName("ID").AsInteger;
RecordEditForm.ShowModal;
if RecordEditForm.ModalResult<>mrOK then Exit;
RefreshData; // обновляем данные основного запроса
DataSet.Locate("ID", RecordEditForm.ID, []) ;
finally
TRecordEditForm.Free;
end;
end;
← →
Ega23 © (2007-11-09 12:41) [8]Это - общий шаблон.
Да, вот ещё: в модальной форме не использую DB-контролов (кроме DBLookupCombo, если что-то из справочной таблицы выбрать надо). предпочитаю обычные Edit, dateTimePicker, Memo и ComboBox. В 95% случаев их достаточно.
← →
ЮЮ © (2007-11-09 12:42) [9]> есть форма, на ней вся выборка.
if RecordEditForm.Modalresult = mrOK then
м что делаешь тут, чтобы вся выборка обновилась?
← →
Reindeer Moss Eater © (2007-11-09 12:43) [10]дело вкуса, но вообще сильно горбатый шаблон.
сплошной копипаст.
← →
Ega23 © (2007-11-09 12:44) [11]
if RecordEditForm.ModalResult<>mrOK then Exit;
Соответственно, в случае mrOK выполнится RefreshData
← →
Ega23 © (2007-11-09 12:45) [12]
> сплошной копипаст.
Шаблон формы - в репозитории.
← →
Ega23 © (2007-11-09 12:46) [13]
> но вообще сильно горбатый шаблон.
Возможно. Просто не хотел делать по 2 модальные формы для добавления и редактирования. Как-то один раз такой механизм разработал - и уже 6 лет им пользуюсь.
Лично меня не напрягает.
← →
Reindeer Moss Eater © (2007-11-09 12:47) [14]Я про то, что во многих местах повторяется один и тот же код.
Создание, инициализация экземпляря формы редактирования, вызов её методов и т.д.
← →
Ega23 © (2007-11-09 12:49) [15]
> Я про то, что во многих местах повторяется один и тот же
> код.
> Создание, инициализация экземпляря формы редактирования,
> вызов её методов и т.д.
>
Ты знаешь, меня в-общем-то это тоже поначалу напрягало. Но придумать красивый шаблон, с учётом того, что, как правило, в RefreshData может дохрена чего происходить (это я в примере так написал, реально код в 60% случаев - разный) я придумать так и не смог.
В конце-концов плюнул на всё слюной и оставил как есть.
← →
Reindeer Moss Eater © (2007-11-09 12:53) [16]у меня этот код всегда выносится в неклассовую функцию в модуле формы редактирования, а вызовы аппенд и эдит выглядят как
If DoEdit(-1) then //Для новой записи
If DoEdit(<ключ>) then //Для редактирования существующей.
И вызывающий код не парится с именем класса формы редактирования. Я его могу менять в любое время не опасаясь, что от этого перекосит другие модули.
← →
Desdechado © (2007-11-09 12:55) [17]> Reindeer Moss Eater © (09.11.07 12:13) [2]
> bookmark вместо locate
Bookmark - это указатель на запись в ТЕКУЩЕМ состоянии датасета. При переоткрытии указатель становится инвалидным, т.к. указатель может быть совсем в никуда или непонятно на что.
← →
Reindeer Moss Eater © (2007-11-09 13:03) [18]ну так есть же методы проверки букмарка на валидность
← →
Reindeer Moss Eater © (2007-11-09 13:05) [19]Хотя сам я так не делаю. Только если пользователь три раза попросит.
К тому же локейт тоже не гаранитрует, что перенесет вас к именно той записи, которую вы редактировали. Особенно если у вас прога "мультиплеер"
← →
Sergey13 © (2007-11-09 13:08) [20]> [4] ЮЮ © (09.11.07 12:22)
> Т.е. изменять данные "в гриде"
Причем можно и не "в гриде", а как у автора в модальных формах.
← →
Ega23 © (2007-11-09 13:11) [21]
> ну так есть же методы проверки букмарка на валидность
Откровенно говоря, я так не рискую.
← →
ЮЮ © (2007-11-09 13:15) [22]> Причем можно и не "в гриде", а как у автора в модальных
> формах.
Естественно. Но я не об этом. Я имел ввиду изменять данные в DataSete, отображаемом в качестве "всей выборки", где посылка запросов на сервер - "побочный эффект" таких изменений.
Единственно, при многопользовательском режиме захочется получить во "всей выборке" и изменения, сделанные другими. Вариант полного обновления "всей выборки" по завершении редактирования как-то выполняет эту работу, не заставляя его каждый раз жать "обновить".
← →
Reindeer Moss Eater © (2007-11-09 13:16) [23]Фигня какая. Валидный букмарк - пробуем перейти.
Получилось - хорошо, не получилось - в следующий раз получится.
← →
Ega23 © (2007-11-09 13:22) [24]
> Фигня какая. Валидный букмарк - пробуем перейти.
> Получилось - хорошо, не получилось - в следующий раз получится.
ИМХО, дело вкуса, стиля и привычки.
← →
Anatoly Podgoretsky © (2007-11-09 13:25) [25]Функцию режима с успехом может выполнять ID, особенно если это автоинкриментное поле. Предложено выше.
← →
Sergey13 © (2007-11-09 13:29) [26]> [22] ЮЮ © (09.11.07 13:15)
> Я имел ввиду
Да я понял. Вообще, ИМХО, просто автор поддался на страшилки противников "редактирования в гриде". 8-)
> захочется получить во "всей выборке" и изменения, сделанные другими.
А такие попытки надо пресекать в зародыше - нефиг за другими подглядывать. 8-)
← →
Desdechado © (2007-11-09 13:31) [27]> Фигня какая. Валидный букмарк - пробуем перейти.Получилось
> - хорошо, не получилось - в следующий раз получится.
А теперь представь: было у тебя в датасете 30 записей. Стало 35, но 28 из них - другие. Даже при валидном букмарке (что сомнительно) ты перейдешь непонятно на что, т.к. в этой области памяти расположилась уже какая-то новая строка.
И нафига такая "помощь" пользователю?
← →
Reindeer Moss Eater © (2007-11-09 13:43) [28]А теперь представь: было у тебя в датасете 30 записей. Стало 35, но 28 из них - другие. Даже при валидном букмарке (что сомнительно) ты перейдешь непонятно на что, т.к. в этой области памяти расположилась уже какая-то новая строка.
И нафига такая "помощь" пользователю?
А мне по барабану.
Я же сказал, что делаю так только если юзер сам три раза попросит меня об этом.
Кроме того, даже если я не попаду на старую запись, то "ничего не взорвется"
← →
zorik © (2007-11-09 14:26) [29]Ого! Какой интерес!
для Ega23 © (09.11.07 12:35) [6]
У меня так и есть. Я к похожему сам дошел. Есть форма редактирования в репозитории. Вызывается с параметром обозначающим добавление или редактирование, но вопрос именно в обновлении после изменений. Locate по ID работает идеально, но есть 3 но:
1. скорость
2. до вызова:
line 3
> line 4 <курсор здесь
line 5
line 6
после вызава:
line 1
line 2
line 3
> line 4 <курсор здесь
3. При удалениии курсор на первой позиции. Но с этим можно справится.
Использовать один TIBQuery для отображения и модификации даже с применением раздельных транзакций для чтения и записи ИМХО нехорошо не только из-за боязни там что-то потерять или не закрыть, а еще потому что запрос может быть сложным и состоять со сплошных join-ов.
Редактировать в гриде, тоже плохой вариант. Если есть всяческие комбобоксы, справочники и т.д. Да и как подтверждать запись. А так модальное окно -- и у пользователя нет вариантов -- или ok или cancel. Это не обсуждается
← →
Reindeer Moss Eater © (2007-11-09 14:31) [30]Маета это ненужная.
А печаль по поводу второго пункта вообще вне конкуренции.
← →
Reindeer Moss Eater © (2007-11-09 14:33) [31]Сделай позиционирвание опциональным.
Хочется юзеру изврата - пусть использует идеальный локейт, не хочет - не пользует.
← →
Sergey13 © (2007-11-09 14:40) [32]> [29] zorik © (09.11.07 14:26)
> Использовать один TIBQuery ...
Во первых не квери а датасет. Во вторых запрос на модификацию с джоинами это нонсенс в данном случае - редактируется одна таблица. В третьих переоткрывать на каждый чих сложной запрос состоящий из сплошных join-ов - уж куда как хорошо.
> и как подтверждать запись.
Как обычно commit-ом.
← →
Ega23 © (2007-11-09 14:47) [33]
> 3. При удалениии курсор на первой позиции. Но с этим можно
> справится.
Ну запоминай перед удалением ID Next или Prior записи. Потом Locate на неё.
← →
zorik © (2007-11-09 14:58) [34]Sergey13 © (09.11.07 14:40) [32]
Сейчас попробую реализовать для одного датасета
← →
Anatoly Podgoretsky © (2007-11-09 15:23) [35]> Ega23 (09.11.2007 14:47:33) [33]
Только NEXT, обычно операции удаления делают сверху вниз
Только кража, только ограбление - сами знаете кто.
← →
Ega23 © (2007-11-09 15:43) [36]
> Только NEXT, обычно операции удаления делают сверху вниз
сначала не понял. Потом понял. Тогда так:with dataSet do
if not isEmpty then
if Eof then Prior else Next.
← →
Anatoly Podgoretsky © (2007-11-09 16:12) [37]> Ega23 (09.11.2007 15:43:36) [36]
Подходит, только вторая строка лишняя, достаточно if Eof, но это не существенно.
← →
Ega23 © (2007-11-09 16:13) [38]
> только вторая строка лишняя
Не, я к тому, чтобы ID не брать у записи, которой нет.
← →
Anatoly Podgoretsky © (2007-11-09 17:03) [39]> Ega23 (09.11.2007 16:13:38) [38]
Оно и не будет браться, я постоянно использую подобный механизм, что бы после удаления курсор был на следующей записи, если EOF то назад, если после удаления не найдено, то на последнею запись, но как я сказал могут быть варианты, которые не изменят сути.
← →
PEAKTOP © (2007-11-09 22:37) [40]> zorik © (09.11.07 14:26) [29]
Я так понял, ты хочешь получить грид а-ля Excel, чтобы все "в живую" плюс изменения других пользователей ?
Возьми FIBPlus, почитай про транзакции у Димки Кузьменко (http://ibase.ru) и все у тебя получиться путем выставления свойств объектов :)
А InterBaseExpress - не более чем чудесная поделка от дяди Джеффа Овекэша :)
Страницы: 1 2 вся ветка
Форум: "Базы";
Текущий архив: 2008.04.06;
Скачать: [xml.tar.bz2];
Память: 0.56 MB
Время: 0.008 c