|
MS SQL, VIEW в VFP и функции SETFLDSTATE( ), GETFLDSTATE( )
|
|||
---|---|---|---|
#18+
Кто VFP совместно с MS SQL не использует, может дальше не читать. Но если все-таки кто-то заинтересуется данной проблемой, буду благодарен! Ну ладно, ближе к телу! Нашел кое-какие функции в VFP, только никак не могу разобраться как они работают. Вернее или я их применяю не для того, для чего они нужны или они не работают с MS SQL серваком. Функции следующие: SETFLDSTATE( ) - Assigns a field or deletion state value to a field or record in a table or cursor. Т.е. назначает полю записи состояние, что оно редактируется или удалено GETFLDSTATE( ) - Returns a numeric value indicating if a field in a table or cursor has been edited or had a record appended, or if the deleted status of the current record has been changed. Т.е. возвращает состояние поля, что было ли оно - я так понимаю – раз поле, то и текущая запись отредактирована, добавлена, удалена. GETFLDSTATE( ) – возвращает 1 – если запись не редактировалась и не удалялась 2 – если запись изменялась или ее удалили Подробное описание этих функций есть в хелпе VFP7.0 Используя эти две функции, очень было бы удобно управлять совместным доступом к данным в сети (на SQL серваке в частности). Как я использую функцию GETFLDSTATE( ): У меня создан view к таблице (таблица на SQL-сервере). Таблица примерно следующая: num decimal – primary key naim char – наименование чего-то Перед тем как редактировать запись, я вызываю nState=GETFLDSTATE("num") IF nState=2 &&-проверка изменена ли запись WAIT 'Данная запись изменена другим пользователем' wind ELSE Do form (pathform+'Edit_form') &&- если нет, то редактирую ее ENDIF Но почему то GETFLDSTATE( ) не всегда правильно отрабатывает. Т.е. возвращает 1 когда текущая запись редактируется другим пользователем. Хотя как я понимаю должна возвращать 2. Может кто-то кроме меня уже работал с данными функциями. Или прочитав этот вопрос попробует их и быстрей меня «въедет с чем их едят». ... |
|||
:
Нравится:
Не нравится:
|
|||
06.01.2003, 12:19 |
|
MS SQL, VIEW в VFP и функции SETFLDSTATE( ), GETFLDSTATE( )
|
|||
---|---|---|---|
#18+
вот кусок из фоксового форума может поможет: Hi, ALL! Есть курсор с буферизацией по умолчанию (3) и связанный с ним Grid. Все поля выбраны для обновления, Send SQL Updates включен. В Grid.BeforeRowColChange отслеживаю изменения текущей записи с помощью GETFLDSTATE(). Если изменить какое-либо поле и сместиться в другое, оставаясь в текущей строке, а затем перейти в другую строку, то GETFLDSTATE() срабатывает. Если же после изменения сразу перейти в другую строку, то GETFLDSTATE() не срабатывает. Аналогично CURVAL() = OLDVAL() = старое значение. В чем может быть причина? Заранее спасибо тем, кто откликнется. RE: Cursor+Grid+GETFLDSTATE JS , 05/23/02 09:36:01 AM Привет! Было такое, но до конца разбираться, что к чему, не было времени, поэтому проверку делал в LostFocus() соответствующей колонки. Все работало. А с этим надо разобраться. Удачи! RE: Cursor+Grid+GETFLDSTATE Sergey Titow , 05/23/02 11:36:16 AM Вроде как проблема в этом - изменения в поле сбрасываются на сразу, а при выходе из текущего объекта. BeforeRowColChange выполняется ДО смены объекта - значит изменения еще не попали в источник. При переходе сначала по строке происходит смена объекта и соответственно обновление данных. Выходы: 1. Использовать BeforeRowColChange 2. В InteractiveChange объекта записывать его value в источник RE: Cursor+Grid+GETFLDSTATE Sergey Titow , 05/23/02 02:53:50 PM Извиняюсь - использовать, естественно, не BeforeRowColChange, а AfterRowColChange RE: Cursor+Grid+GETFLDSTATE bell , 05/23/02 05:02:21 PM Сергей, попробовал AfterRowColChange - не помогает. JS, у колонки нет события LostFocus. Ты имел в виду объект колонки? RE: Cursor+Grid+GETFLDSTATE JS , 05/24/02 12:34:56 AM Доброй ночи! Только, что вернулся поэтому задержка с ответом. Разумеется объекта колонки RE: Cursor+Grid+GETFLDSTATE Влад Гринчишин , 05/24/02 12:41:17 PM bell, ЛЮБАЯ перерисовка грида вызовет автоматическое обновление данных на сервере (автоматический tableupdate()). Это потому что для рисования записей грид сканирует записи или перемещает указатель записи, что, как известно, приводит к автоматическому обновлению при 3-ей буферизации. Оно и неудивиоельно что что-то не так <g> Рекоммендуется с гридами использовать только 5-ю буферизацию /-: RE: Cursor+Grid+GETFLDSTATE bell , 05/24/02 08:20:54 PM Влад, попробовал 5-ю буферизацию. Поведение изменилось, но все равно не то, что хотелось. При переходе на другую строку сразу после изменения GETFLDSTATE() по-прежнему не реагирует. А если потом вернуться на строку, где были изменения, и вновь ее покинуть, то GETFLDSTATE() срабатывает. Это, наверное, потому, что в Grid.AfterRowColChange есть Grid.Refresh. Пробовал вставить Grid.Refresh в Grid.BeforeRowColChange до GETFLDSTATE() - не помогает. JS, действительно GETFLDSTATE() в LostFocus срабатывает при первом переходе на другую строку. Но она срабатывает также и при переходе в другую колонку, даже если строка не изменяется. А нужно выдать подтверждение на сохранение изменений только при смене строки. Не могу сообразить, как отследить смену строки без BeforeRowColChange. Кроме того, неудобно, что это подтверждение прийдется вставлять в LostFocus объектов каждой колонки. RE: Cursor+Grid+GETFLDSTATE Влад Гринчишин , 05/27/02 01:28:02 PM bell, GETFLDSTATE() работает только для текущей записи. Скорее всего запись уже новая когда Вы пробуете использовать эту функцию. Попробуйте такую методику определения изменилась ли строка, которая заодно моможет и корректно вызвать GETFLDSTATE(): Заведите свойство формы (или грида - добавьте при помощи AddProperty() в Init), например, nRecNo. В свойстве будет хранится текущая запись в алиасе грида. В событии AfterRowColChange проверяйте изменилось ди RecNo() по сравнению с nRecNo. Если нет - это просто получение фокуса гридом или переход по колонкам грида. Если изменилось, имеет место переход на другую строку в гриде. Во втором случае запоминаем RecNo() во временной переменной, возвращаемся назад при момощи комманды GO и проверяем GETFLDSTATE(). Выдаем все что надо, если надо остаться там - остаемся и т.п., но если остаемся, надо обязательно вызвать Grid.Refresh. Если переход ok, делаем Go на запись, номер которой запомнили (запись на которую перезодим), обновляем содержимое nRecNo, и все... Кстати, nRecNo и методика его обновления используется также для подсветки строки в гриде при помощи DynamicBackColor. RE: Cursor+Grid+GETFLDSTATE bell , 05/27/02 06:43:37 PM Влад, большое спасибо за советы. Все получилось. RE: Cursor+Grid+GETFLDSTATE bell , 05/28/02 08:45:28 PM Влад, одна проблема все-таки осталась. :-(( Если исправить какое-либо поле и тут же закрыть форму с Grid, то Grid.AfterRowColChange не имеет места. Где тогда можно проверить, были изменения или нет? RE: Cursor+Grid+GETFLDSTATE Влад Гринчишин , 05/29/02 11:26:12 AM На выходе ыормы, естественно. Рекоммендую оформить код проверки как метод формы и вызывать его в соответствующих местах. Есть только одно "но". Если форма закрывается извне, по ON KEY LABEL или еще как-нибудь так, что не успевается вызваться событие Valid для контрола на форме (и соответственно, значение контрола еще не записанно в таблицу - в том-то и проблема), надо писать дополнительный код для насильного запиывания значения. Если надо, пришлю пример такого кода. RE: Cursor+Grid+GETFLDSTATE bell , 05/29/02 04:57:55 PM Влад, пример кода не помешает, пришли, пожалуйста. В каких "соответствующих" местах его вызывать? Что значит закрытие формы "извне"? RE: Cursor+Grid+GETFLDSTATE Влад Гринчишин , 05/29/02 05:16:18 PM >В каких "соответствующих" местах его вызывать? Ну, AfterRowColChange грида я уже указал. Другое место - при закрытии формы когда грид активен. >Влад, пример кода не помешает, пришли, пожалуйста. >Что значит закрытие формы "извне"? Извне значит по событиях извне формы: ON KEY LABEL, с меню, с toolbar и т.п., т.е. форма уничтожается тогда когда значение набранное в контроле еще не записанно в поле в ControlSource. Сорри, пример кода временно недоступен мне, но написать его просто. Вот он, но не проверил - набрал по памяти: && берем активный контрол oObj = thisform.ActiveControl if vartype(m.oObj) == "O" AND PEMSTATUS(m.oObj,"value",5) && проверяем грид ли он, если да, ищем текущий активный контрол if upper(m.oObj.BaseClass) == "GRID" nIndex = m.oObj.ActiveColumn for i=1 to m.oObj.ColumnCount if m.oObj.Columns(i).COlumnOrder = nIndex nIndex = i exit endif endfor oObj = m.oObj.Columns(nIndex) oObj = evaluate("m.oObj." + m.oObj.CurrentControl) endif && проверяем менялся ли контрол по сравнению со значением ControlSource if !(m.oObj.value==evaluate(m.oObj.ControlSource)) m.oObj.SetFocus && этого достаточно чтобы записать изменения в ControlSource end if end if RE: Cursor+Grid+GETFLDSTATE bell , 05/29/02 06:52:20 PM Влад, большое спасибо за пример. При закрытии формы - это Destroy или Unload? Еще мне бы хотелось вставить такую проверку при потере фокуса гридом. Но у него нет свойства LostFocus. Неужели прийдется вставлять проверку в LostFocus каждого контрола грида? RE: Cursor+Grid+GETFLDSTATE Влад Гринчишин , 05/30/02 02:14:01 PM При закрытии формы это QueryUnload и Release. В Destroy или Unload уже все контролы формы уничтоженны. Чтобы вернуться с Release без закрытия формы, используй nodefault. А еще лучше, чтобы все бфло в одном месте в форме, в Release формы поставь следйющее: if NOT this.QueryUnload() nodefault return .F. endif Т.о. в QueryUnload возвращай .F. если фрма не должна быть закрыта. Это будет работать как при закрытии форма программным образом (обычно это вызов thisform.Release по кнопке на форме), так и при закрытии формы нажатием "X" в правом-верхнем углу формы или дабл-клик на левом верхнем углу формы (закрывание через интерфейс Windows). RE: Cursor+Grid+GETFLDSTATE bell , 05/30/02 04:30:40 PM Влад, с закрытием формы все понятно. У меня еще был вопрос с проверкой по GETFLDSTATE() в момент потери фокуса гридом. Где ее делать? В LostFocus каждого контрола грида или в GetFocus других контролов формы (кроме грида есть еще кнопки типа "Добавить", "Удалить" и др.)? А нельзя ли это сделать где-то в одном месте? Пробовал Valid грида, но там видно курсор еще не обновился. RE: Cursor+Grid+GETFLDSTATE Влад Гринчишин , 05/30/02 04:49:41 PM Упс, сорри, пропустил этот вопрос. Грид можно положить внутрь контэйнера и ловить LostFocus контэйнера. RE: Cursor+Grid+GETFLDSTATE bell , 05/30/02 08:06:55 PM Спасибо всем, принявшим участие в обсуждении, особенно Владу Гринчишину. ... |
|||
:
Нравится:
Не нравится:
|
|||
06.01.2003, 20:42 |
|
MS SQL, VIEW в VFP и функции SETFLDSTATE( ), GETFLDSTATE( )
|
|||
---|---|---|---|
#18+
Прежде всего следует уяснить, что такое вообще технология клиент-сервер. В самых общих чертах суть сводится к следующему: Клиент посылает инструкцию на сервер. Сервер выполняет эту инструкцию и возвращает результат клиенту. Итого, когда ты сделал запрос SQLExec() или Remote View то в результате ты получил некоторую выборку (не саму таблицу), физически расположенную у клиента . Далее, в FoxPro есть такое понятие как "буферизация". Т.е. если таблица находится в каком-либо режиме буферизации, то любые изменения происходят не непосредственно с таблицей, а с ее "буфером". Другими словами с некоторой копией таблицы. Любое View в FoxPro открывается в режиме оптимистической буферизации строк (3) и может быть перключено только в режим оптимистической буферизации таблиц (5) и никак иначе. Результат выполнения SQLExec() в этом смысле обладает всеми свойствами Remote View. Итого, после выполнения SQLExec() или Remote View у клиента появляется: 1. Временная таблица, содержащая результат выборки 2. Буфер этой временной таблицы Все команды FoxPro типа GetFldState(), SetFldState(), OldVal(), CurVal(), GetNextModify() и т.п. работают только с файловыми таблицами. Т.е. применительно к Remote View сравнение идет между выборкой у клиента и буфером этой выборки у того же клиента. Эти команды просто ничего не могут сказать о том, что произошло на самом сервере. Для этого требуется сделать еще один запрос на сервер. Таким образом, в момент редактирования записи ты ничего не можешь сказать о том, редактирует ли кто-то еще ту же запись. Ты можешь сделать этот вывод только в момент записи внесенных изменений. Как это сделать? Обрати внимание на группу "SQL WHERE clause includes" на закладке "Update Criteria" в Remote View, а также внимательно прочитай описание использования второго параметра в команде TableUpdate(). ... |
|||
:
Нравится:
Не нравится:
|
|||
10.01.2003, 18:11 |
|
|
start [/forum/topic.php?fid=16&fpage=235&tid=1348951]: |
0ms |
get settings: |
9ms |
get forum list: |
16ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
26ms |
get topic data: |
12ms |
get forum data: |
3ms |
get page messages: |
99ms |
get tp. blocked users: |
1ms |
others: | 246ms |
total: | 418ms |
0 / 0 |