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


Автор: demoded 20.2.2009, 14:46
грид привязан к ADODataSet, после добавления/удаления записи делаю
Close и Open

как реализовать восстановление курсора на туже позицию?
фактически сохраненные BookMark работают, но после закрытия датасета они становятся невалидными, но встают на нужное мето тем не менее smile

сейчас реализовано так:
при редактировании - нормально BookMark срабатывает
при добавлении - получаю ID добавленной записи и руками встаю на нее
проблемы начинаются при удалении... можно конечно запомнить ID следующей и предыдущей записи... но что то как-то некрасиво мне кажется так будет.

Автор: pseud 20.2.2009, 17:20
Цитата(demoded @  20.2.2009,  14:46 Найти цитируемый пост)
как реализовать восстановление курсора на туже позицию?

важно курсор установить на нужную позицию в конечном визуализаторе (TDBGrid, TdxDBTreeList, etc.), а не в датасете.

Автор: demoded 22.2.2009, 13:01
Цитата(pseud @ 20.2.2009,  17:20)
Цитата(demoded @  20.2.2009,  14:46 Найти цитируемый пост)
как реализовать восстановление курсора на туже позицию?

важно курсор установить на нужную позицию в конечном визуализаторе (TDBGrid, TdxDBTreeList, etc.), а не в датасете.

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

Автор: Hexel 23.2.2009, 22:11
Еслия я правильно понял, ты хочешь восстановить курсор не на ту запись, которую удалил) Тогда на мой взгляд лучше Locate ничего не придумать, его ж не просто так придумали. Вот сохраняешь ID записи, потом его находишь снова

 smile если все же удаляешь именно эту запись, то после делете делаешь next и запоминаешь уже вновь полученный ID

Автор: Kbl4AH 24.2.2009, 22:12
Код

var
  N, C: Integer;
begin
  N := ADODataSet1.RecNo;
  C := ADODataSet1.RecordCount;
  ... // добавление/удаление записи, Close и Open 
  if ADODataSet1.RecordCount > C then // вставка
    ADODataSet1.RecNo := N + 1;
  if ADODataSet1.RecordCount = C then // редактирование
    ADODataSet1.RecNo := N;
  if ADODataSet1.RecordCount < C then // удаление
    if N = 1 then
      ADODataSet1.RecNo := N          // 1-й записи
    else
      ADODataSet1.RecNo := N - 1;     // не 1-й записи
end;

Автор: Deniz 25.2.2009, 06:55
Цитата(pseud @  20.2.2009,  20:20 Найти цитируемый пост)
важно курсор установить на нужную позицию в конечном визуализаторе (TDBGrid, TdxDBTreeList, etc.), а не в датасете. 
это шутка такая?  smile 

Kbl4AH, весьма спорный код.
В многопользовательской работе даже добавив запись RecordCount после Close/Open может вернуть меньшее кол-во.

demoded, а чем так не нравится locate?
При добавлении/удалении DataSet перемещается на нужную запись.
После удаления вопрос, что хочет увидеть пользователь? Первую, последнюю, следующую после удаленной, предыдущую?
Спроси у заказчика что ему надо, обычно нужно следующую после удаленной.

Автор: Kbl4AH 25.2.2009, 09:05
Цитата(Deniz @  25.2.2009,  06:55 Найти цитируемый пост)
Kbl4AH, весьма спорный код.В многопользовательской работе даже добавив запись RecordCount после Close/Open может вернуть меньшее кол-во.

Бесспорно... Для многопользовательской работы не подойдет...
Как, по-моему, и не подойдет Locate для такой работы... Никогда с ним не сталкивался, сейчас глянул... Как после открытия датасета искать запись, которой в результате многопользования может уже не быть?
Deniz, приведи пример с использованием Locate, а то я более-менее однозначный алгоритм не могу сочинить (а мне иногда требуется, как и demoded, четкий алгоритм  для таких же целей).

Автор: demoded 25.2.2009, 13:33
Цитата(Deniz @ 25.2.2009,  06:55)
demoded, а чем так не нравится locate?
При добавлении/удалении DataSet перемещается на нужную запись.
После удаления вопрос, что хочет увидеть пользователь? Первую, последнюю, следующую после удаленной, предыдущую?
Спроси у заказчика что ему надо, обычно нужно следующую после удаленной.

locate всем устраивает и использется, но при удалении (допустим надо перейти на следующую запись) приходится руками отслеживать ситуацию если удалили последнюю запись в ДатаСете и надо перейти не на следующую а на предыдущую.
хотелось завернуть это дело раз и навсегда в какой-нибудь собственный BookMark, но что-то опыта маловато. оставил пока так:
Код

  ADODataSet1.DisableControls;
  ID:=ADODataSet1['BookNMKID'];
  ADODataSet1.Next;
  nextID:=ADODataSet1['BookNMKID'];
  if ID=nextID then begin ADODataSet1.Prior; nextID:=ADODataSet1['BookNMKID']; end;
  Update; // тут какраз .Close/.Open
  if not ADODataSet1.Locate('BookNMKID',ID,[loCaseInsensitive]) then
    if not ADODataSet1.Locate('BookNMKID',nextID,[loCaseInsensitive]) then ADODataSet1.First;
  ADODataSet1.EnableControls;

Автор: Deniz 25.2.2009, 14:49
Цитата(Kbl4AH @  25.2.2009,  12:05 Найти цитируемый пост)
Deniz, приведи пример с использованием Locate, а то я более-менее однозначный алгоритм не могу сочинить
все достаточно тривиально, но на один select больше.
Сделаем некоторые допущения:
1. Алгоритм работает для удаления (для insert/update не вижу смысла)
2. После удаления, должна быть активна следующая за удаленной запись.
3. Если удаляемая запись была последней, то активной будет последняя.
4. Есть набор полей, по которым сортируется набор данных
5. Добавление к ним ID сделает набор уникальным. (для примера возмем сортировку по уникальному табельному номеру, тогда добавление ID не потребуется)
Идея:
1. Сохраняем в параметры набор полей из допущения 4
2. Удаляем запись.
3. Close Open
4. В дополнительном запросе делаем что-то типа 
Код
select min(ID) from table where tabnum > :tabnum_parameter

5. 
Код
if not dataset.locate (id, 'ID', []) then dataset.last

Примерно такой алгоритм будет работать в многопользовательской среде, и в четверге тоже  smile 
Можно дорабатывать.

Автор: Akella 25.2.2009, 16:36
DatasSet1.lookup(....) работает быстрее за счёт того, что курсор не бегает по набору данных

Автор: pseud 25.2.2009, 16:53
demoded, 
Если речь идет о TDBGrid, то ИМХО стоит привязываться за DataSet.RecNo
что-то типа
Код

i := DataSet.RecNo;
// удаление
// обновление
if not DataSet.IsEmpty then
begin
  if i > DataSet.RecordCount then
    i := DataSet.RecordCount;
  DataSet.RecNo := i;
end;

  
Если в качестве визуализатора использовать нечто типа "DBTreeList", то фокусировка должна завязываться за свойства трилиста.
FocusedNode... и т.д. 
Если актуально - дораспишу.

Автор: Kbl4AH 25.2.2009, 17:01
Не понял, зачем тут доп. запрос...
А если после открытия датасет в нем ни одной записи не останется - ошибка?
ЗЫ. Пост для Deniz.

Автор: pseud 25.2.2009, 18:14
Цитата(Kbl4AH @  25.2.2009,  17:01 Найти цитируемый пост)
А если после открытия датасет в нем ни одной записи не останется - ошибка?

для этого и написана проверка
Код

if not DataSet.IsEmpty then

Автор: Kbl4AH 25.2.2009, 19:31
Цитата(pseud @  25.2.2009,  18:14 Найти цитируемый пост)
для этого и написана проверка

pseud, я длительное время не обновлял форум, поэтому, адресуя сообщения Deniz, не заметил сообщения Akella и твое...
Хотя и из контекста видно, что мой пост являлся ответом не на твой...
Так что не сердись smile 

Автор: Deniz 26.2.2009, 06:41
Цитата(Akella @  25.2.2009,  19:36 Найти цитируемый пост)
DatasSet1.lookup(....) работает быстрее за счёт того, что курсор не бегает по набору данных 
все равно перемещаться придется.

Цитата(Kbl4AH @  25.2.2009,  20:01 Найти цитируемый пост)
Не понял, зачем тут доп. запрос...
доп. запрос нужен для определения сл. записи после удаленной.

Цитата(Kbl4AH @  25.2.2009,  20:01 Найти цитируемый пост)
А если после открытия датасет в нем ни одной записи не останется - ошибка?
я, конечно, могу за тебя весь код написать, со всеми проверками и т.д., но стОит ли?

Цитата(pseud @  25.2.2009,  19:53 Найти цитируемый пост)
Если речь идет о TDBGrid, то ИМХО стоит привязываться за DataSet.RecNo
все таки привязываться к номеру записи не лучший вариант.

Автор: Kbl4AH 26.2.2009, 08:50
Цитата(Deniz @  26.2.2009,  06:41 Найти цитируемый пост)
я, конечно, могу за тебя весь код написать, со всеми проверками и т.д., но стОит ли?

Конечно, не нужно...
Цитата(Deniz @  26.2.2009,  06:41 Найти цитируемый пост)
все таки привязываться к номеру записи не лучший вариант

Для случая с удалением вариант pseud имхо - лучший из рассмотренных...
Хотя и вариант с Locate не стоит сбрасывать со счетов, но применение его я пока вижу только в частном случае изменения номера записи после апдейта из-за сортировки записей средствами грида, а не датасета... но доп. запрос точно не нужен... можно и без него определить следующую запись...
ЗЫ. получается, что универсального решения, все делают так, как предпочтительнее...

Автор: pseud 26.2.2009, 10:42
Цитата(Deniz @  26.2.2009,  06:41 Найти цитируемый пост)
все таки привязываться к номеру записи не лучший вариант

не помню, что там с сортировками у TDBGrid.
побыстрому пробежав по TDBGrid и TDataSet, пришел к выводу что сортировка таки средствами SQL.
Следовательно завязываться за номер записи - приемлемый вариант.

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