C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
FIB Plus и Refresh()
*Helly*
Отправлено: 30.12.2003, 13:40


Не зарегистрирован







Добрый день!
Такой вопрос.

Есть DataSet, открытый только для чтения. Для добавления и изменения записей используется хранимая процедура. При выполнении Refresh() после вставки записи новая запись в DataSet не отражается. Можно ли как нибудь заставить работать Refresh() без перечитывания всего набора данных?
Nick
Отправлено: 31.12.2003, 09:45


Машинист паровоза

Группа: Участник
Сообщений: 247



Поставь poRefreshAfterPost = false
Но если процедура изменяет какието поля в зависимости от изменений других полей
Допустим
В базе хранится Количество и Сумма, Цена расчитывается в запросе.
При изменении Суммы если ты сама не пересчитываешь уже в гриде цены, она визуально для пользователя неизменится, так как в случае
poRefreshAfterPost = false не выполнится Refresh для измененной записи.

Есть еще возможность оставить poRefreshAfterPost = false.
Но тебе надо определять значение ключевого поля.
Или поставить Генератор на ключевое поле или в событии AfterInsert вызывать процедуру возвращаюшую Новое ID ключевого поля и самой присвавать.

Вот пример RefreshSQL из моего проекта.

SELECT
NAKLDATA_ID, DATA_ID, DOCUMENTS_ID,
DET_ID, NAME, AMOUNT, CENA, SUMMA,
OLDCENA, NEWCENA, PERCENT, RESERVE,
PART, PARTNAME, NAL, NOTE, NDS, NLSP,
AKCIZ, NDSSUMMA, NLSPSUMMA, AKCIZSUMMA
FROM
DOCS_DATA_2
(
:IPDOCS_ID
)
WHERE
(
DATA_ID = :OLD_DATA_ID )

DATA_ID = :OLD_DATA_ID — указывает что RefreshSQL выполняется для измененной (добавленной) записи по ключевому полю DATA_ID
** pasha
Отправлено: 31.12.2003, 13:16


Не зарегистрирован







QUOTE
Можно ли как нибудь заставить работать Refresh() без перечитывания всего набора данных?


Скорее всего нельзя.
(ведь я так понимаю, свойства SQLs: Update/Insert/Delete пусты,
да к тому-же и не через них происходит изменения таблицы)

Наверное придется использовать pFIBDataSet->CloseOpen(false);

*Helly*
Отправлено: 05.01.2004, 11:59


Не зарегистрирован







Я попробовала каждый раз заново перестраивать запрос в RefreshSQL,
подставляя вместо значений OLD_XXX значения из новой записи. В этом случае TDataSet считывает из базы новую запись, но в гриде она
перезаписывается на место той записи, которая была активной перед вставкой новой. sad.gif
Nick
Отправлено: 05.01.2004, 13:06


Машинист паровоза

Группа: Участник
Сообщений: 247



Не надо перестраивать запрос.
Его я привел для того что бы показать
Запрос Refresh работает по ключевому полю.
Если ключевое поле новой записи программе неизветно то и
Refresh не покажет эту запись.
*Helly*
Отправлено: 05.01.2004, 13:13


Не зарегистрирован







Так в том то весь и прикол, что если я перестраиваю RefreshSQL,
то новая запись появляется в гриде, но только вместо той, на которой стоял курсор.
*Helly*
Отправлено: 05.01.2004, 17:03


Ученик-кочегар

Группа: Участник
Сообщений: 12



Вроде бы получилось обновлять грид, путем работы с кешем набора данных:

делаю добавление пустой записи в кэш таблицы
int intArr[2] = {0,1};
const int* Ar = intArr;
Variant vFields;
vFields << NULL << NULL;
dsView->CacheAppend(Ar,sizeof(intArr),&vFields,sizeof(vFields));

тогда при выполнении Refresh() (с подстановкой конкретных значений вместо OLD_XXX) новая запись отображается на месте пустой smile.gif

Один только вопрос, как реально проверить, что рефрешится только одна запись, а не весь набор данных?
Nick
Отправлено: 06.01.2004, 09:11


Машинист паровоза

Группа: Участник
Сообщений: 247



Слов нет.

Пришли кусок проекта, подправлю где надо.
Soltami@yandex.ru
Bubble
Отправлено: 23.01.2004, 00:36


Не зарегистрирован







А чем плох-то CloseOpen(false)?

Зачем с рефрешем мучиться. Или я не понимаю чего-то?
Nick
Отправлено: 23.01.2004, 08:52


Машинист паровоза

Группа: Участник
Сообщений: 247



Зачем пересчитывать Шоколад в одном ящике.
Лучше открыть весь камаз пересчитать все ящики и закрыть (зкрыть сначала-забылся).
** pasha
Отправлено: 25.01.2004, 21:32


Не зарегистрирован







Остаюсь при своем мнении: CloseOpen(false)
Это работает корректно.

А вот в вашем варианте возможны различные глюки.
Nick
Отправлено: 26.01.2004, 08:45


Машинист паровоза

Группа: Участник
Сообщений: 247



Кто же делает CloseOpen после добавления всего одной записи.
Тем более курсор упадет на первую запись а не на новую.
** Deem
Отправлено: 17.02.2004, 17:13


Не зарегистрирован







Вобще, вопрос это больной. Только Закрытие/открытие увидит новую запись (я уже собрался писать свой DBGrid, задолбало). Можно запомнить ключевое поле записи, на которой стоит курсор, закрыть/открыть запрос и выйти на запомненную запись. Правда, в гриде записи могут переместиться, и выбранная запись часто оказывается в самом низу (что на нервы действует).
В FB+ при добавлении записи можно генерировать ключ на клиенте, а не в триггере. Тогда клиент знает ключ новой записи и выходит на нее.
Если новая запись добавляется ХрПр, то она может возвращать клиенту ключевое поле новой записи, и тогда после CloseOpen можно перепрыгрнуть курсором на новую запись.
olegenty
Отправлено: 18.02.2004, 09:57


Ветеран

Группа: Модератор
Сообщений: 2412



Вот готовое решение. В него надо вникнуть, но оно работает, а опубликовано, кстати, давно.
http://ibase.ru/devinfo/ClientRefresh.htm

по всем вопросам об Interbase/Firebird/Yaffil рекомендую http://ibase.ru. проблемы у всех одни, а решены многие из них уже давно.

Вернуться в Работа с базами данных в C++Builder