Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / FoxPro, Visual FoxPro Новый топик    Ответить
 Буферизация и индекс кандидат  [new]
Galyamov Rinat
Member

Откуда:
Сообщений: 658

Никогда не работал с буферизацией, и вот решил попробовать что же это такое.

Всегда внесение новой строки или изменение данных в имеющейся вешал на
отдельную форму, в которую пользователь вводил значения и,по кнопке
"сохранить", делал необходимые проверки (или переключал контроль ошибок в
режим "невидимый", т.е. чтобы пользователю не вываливалось сообщений об
ошибках правил таблицы или нарушения уникальности индексов). Если ошибок
нет - release`им форму, есть - сообщаем что не так, оставляем форму видимой,
для дальнейшей правки.

Тут по дизайнерской задумке решил разрешить вносить изменения прямо в
основном гриде. Сделал табличную буферизацию (грид отображает кусок таблици
по set key range). На выходе из формы повешал проверку на наличие изменений
в буфере и tableupdate. Вот тут бы и воткнуть все необходимые мне проверки
на корректность данных. Но. как всегда есть некое НО.

При внесении изменений в строку данных и переходе на другую запись ругается
на нарушении уникальности индекса.
Индекс на основной таблице. Убирать его считаю неправильным (контроль
превыше всего - и пусть он будет на уровне таблицы).

Внимание вопрос. Как можно отловить подобную ошибку. В каких методах ее
можно проверить (ну или в каком методе перехватить глобальный обработчик
ошибок, чтобы не пришлось делать реверт таблицы) и остаться на той записи,
которая вызывает ошибку уникальности ключа?


PS понимание того, что индексы в памяти строятся даже на буферизованный
кусок данных - есть. Проверку хотел прикрутить на lostfocus текстбокса
колонки, в которой вносятся индексируемые данные. Но чтобы проверить надо по
таблице "пройтись" в поисках дубля, а это в свою очередь вызывает уход с
текущей записи и попытке перестроить индекс с последующей ошибкой
уникальности. Открыть таблицу в другом алиасе, тогда данные внесенные в
буфер первого алиаса видны не будут (а вполне вероятно, что данные уже в
буфере изменены или внесены ДВЕ новые строки, которые и будут
конфликтовать). Т.е. второй алиас тоже не вариант.


Posted via ActualForum NNTP Server 1.4

16 июн 08, 08:23    [5803023]     Ответить | Цитировать Сообщить модератору
 Re: Буферизация и индекс кандидат  [new]
Galyamov Rinat
Member

Откуда:
Сообщений: 658
В связи с отсутствием ответов, боюсь, что слишком сложно задал вопрос. :-)

Поясню на примере, чего пытаюсь сделать:

Открываем форму (прилагается). Тыркаем кнопку "Добавить", в новую запись заносим в поле year значение "1111". Переходим на другую запись. Получаем ошибку.

Как (а главное где) ее правильнее отловить неотключая основной обработчик ошибок "on error"
16 июн 08, 11:55    [5803699]     Ответить | Цитировать Сообщить модератору
 Re: Буферизация и индекс кандидат  [new]
Galyamov Rinat
Member

Откуда:
Сообщений: 658
Само приложение.

К сообщению приложен файл (Buffer.rar - 1Kb) cкачать
16 июн 08, 11:56    [5803703]     Ответить | Цитировать Сообщить модератору
 Re: Буферизация и индекс кандидат  [new]
12345вышелзайчикпогулять
Guest
рекомендую использовать курсорадаптер

примеры использования КАДа с nativ источником
приводились
16 июн 08, 12:55    [5803985]     Ответить | Цитировать Сообщить модератору
 Re: Буферизация и индекс кандидат  [new]
Burn
Member

Откуда: Днепропетровск, Украина
Сообщений: 1167
Судя по всему у Вас 3-я буфферизация если сброс происходит автоматически при переходе от строки к строке. Ставте 5-ю. Хотя это все равно не гарантирует от проблем с кандидат индексом.
Если перешли на схему непосредственого ввода в Грид то проверяте поля по мере ввода - либо Valid/LostFocus теккстбоксов в колонках гридов или AfterRowColChange грида
16 июн 08, 14:43    [5804732]     Ответить | Цитировать Сообщить модератору
 Re: Буферизация и индекс кандидат  [new]
ВладимирМ
Member

Откуда: г. Москва
Сообщений: 7864
Burn
Судя по всему у Вас 3-я буфферизация если сброс происходит автоматически при переходе от строки к строке. Ставте 5-ю. Хотя это все равно не гарантирует от проблем с кандидат индексом.
Если перешли на схему непосредственого ввода в Грид то проверяте поля по мере ввода - либо Valid/LostFocus теккстбоксов в колонках гридов или AfterRowColChange грида

Это не поможет. Контроль индекса осуществляется еще ДО сброса буфера. По факту заполнения записи. Т.е. и в табличном режиме буферизации будет выскакивать сообщение об ошибке при попытке перейти на другую запись.

Единственный вариант в данном случае - это ручной перехват системной ошибки в событии формы Form.Error() или в аналогичном событии Grid.Error(). Код ошибки 1884.

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

В принципе, Александр предложил правильное решение. Работать не напрямую с таблицей, а с выборкой (копией) из этой таблицы.

Как эту копию организовать - через CursorAdapter, Local View, набор переменных или каким-нибудь еще способом - не важно. Важно, что работа будет осуществляться не с самой таблицей-источником (пусть и буферизированным), а с другими данными.

Как правило, в реальных приложениях напрямую с исходными таблицами работают крайне редко.

Другой вариант - это организовать контроль уникальности не через индекс, а через триггер на вставку. Вот триггер будет срабатывать только в момент сброса буфера. При определенных стандартах создания структуры базы данных можно написать универсальный (в рамках данной базы данных) триггер на контроль уникальности введенных данных.
16 июн 08, 19:47    [5806349]     Ответить | Цитировать Сообщить модератору
 Re: Буферизация и индекс кандидат  [new]
Galyamov Rinat
Member

Откуда:
Сообщений: 658

> Судя по всему у Вас 3-я буфферизация если сброс происходит
> автоматически при переходе от строки к строке. Ставте 5-ю. Хотя это все
> равно не гарантирует от проблем с кандидат индексом.

Так я же и говорю. стоит 5-я. проблемы с кандидат есть.


> Если перешли на схему непосредственого ввода в Грид то проверяте поля
> по мере ввода - либо Valid/LostFocus теккстбоксов в колонках гридов или
> AfterRowColChange грида

Спасибо за попытку совета, но если бы все было так просто.

Во первых valid мне ничего не даст (надо сравнивать со значениями других
строк). Во-вторых в AfterRowColChange - уже позно пытаться отловить ошибку
нарушения уникальности - она уже произошла.


Posted via ActualForum NNTP Server 1.4

17 июн 08, 04:54    [5807013]     Ответить | Цитировать Сообщить модератору
 Re: Буферизация и индекс кандидат  [new]
Galyamov Rinat
Member

Откуда:
Сообщений: 658

> Единственный вариант в данном случае - это ручной перехват системной
> ошибки в событии формы Form.Error() или в аналогичном событии
> Grid.Error(). Код ошибки 1884.

Перешел на строковую буферизацию с принудительным сбросом буфера в событии
beforerowcolchange
IF This.RowColChange= 1 OR This.RowColChange=3 AND
GETFLDSTATE('Year','limits')>1

IF !TABLEUPDATE( 1, .t. , 'limits')

NODEFAULT

RETURN .f.

ENDIF

ENDIF



Такой же механизм при попытке закрытия формы (т.е. самой таблицы)



При таком раскладе сообщение не выскакивает, а можно обработать через
четвертый параметр ф-ции tableupdate (пока еще не сделал)


> В принципе, Александр предложил правильное решение. Работать не
> напрямую с таблицей, а с выборкой (копией) из этой таблицы.

> Как эту копию организовать - через CursorAdapter, Local View, набор
> переменных или каким-нибудь еще способом - не важно. Важно, что работа
> будет осуществляться не с самой таблицей-источником (пусть и
> буферизированным), а с другими данными.

Раньше работал только через переменные (в ините модифицирующей формы
заполнял control.value, по кнопке "применить" - все необходимые проверки, в.
т.ч. позволяющие пробегать по таблице источнику). А тут вот решил освоить
что-то новое :)


> Как правило, в реальных приложениях напрямую с исходными таблицами
> работают крайне редко.
Дык я так понимаю что буферыы ввели как раз для того, чтобы не напрямую с
таблицами работать.

> Другой вариант - это организовать контроль уникальности не через
> индекс, а через триггер на вставку. Вот триггер будет срабатывать только в
> момент сброса буфера. При определенных стандартах создания структуры базы
> данных можно написать универсальный (в рамках данной базы данных) триггер
> на контроль уникальности введенных данных.

Индекс - это все таки индекс. Он и быстрее и надежнее отработает чем тригер.


Posted via ActualForum NNTP Server 1.4

17 июн 08, 05:15    [5807017]     Ответить | Цитировать Сообщить модератору
 Re: Буферизация и индекс кандидат  [new]
12345вышелзайчикпогулять
Guest
автор

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


еще раз советую - возьмите КАД.
там сделаете свой обработчик + будете использовать
доп.курсор для ввода изменений + если необх-мо проверки делать у др.источника +
получите локальный обработчик ошибки + получите правильные методы и события

пример

К сообщению приложен файл (Nativ_second.zip - 9Kb) cкачать
17 июн 08, 09:08    [5807154]     Ответить | Цитировать Сообщить модератору
 Re: Буферизация и индекс кандидат  [new]
ВладимирМ
Member

Откуда: г. Москва
Сообщений: 7864
Galyamov Rinat

> Единственный вариант в данном случае - это ручной перехват системной
> ошибки в событии формы Form.Error() или в аналогичном событии
> Grid.Error(). Код ошибки 1884.

Перешел на строковую буферизацию с принудительным сбросом буфера в событии
beforerowcolchange

IF This.RowColChange= 1 OR This.RowColChange=3 AND GETFLDSTATE('Year','limits')>1
	IF !TABLEUPDATE( 1, .t. , 'limits')
		NODEFAULT
		RETURN .f.
	ENDIF
ENDIF

Такой же механизм при попытке закрытия формы (т.е. самой таблицы)

При таком раскладе сообщение не выскакивает, а можно обработать через
четвертый параметр ф-ции tableupdate (пока еще не сделал)

На практике, это единственно возможный способ работы, в случае прямой модификации данных в Grid. Ведь признаком завершения модификации как раз и является попытка перехода на другую запись. Значит, вне зависимости от типа буферизации (можно и 5 режим использовать) необходимо выполнить контроль введенных данных в событии Grid.BeforRowColChange()

Galyamov Rinat

Раньше работал только через переменные (в ините модифицирующей формы
заполнял control.value, по кнопке "применить" - все необходимые проверки, в.
т.ч. позволяющие пробегать по таблице источнику). А тут вот решил освоить
что-то новое :)

И это правильно! Даже если не получится использовать новый метод все-равно приобретете ценный опыт и новые знания.

Galyamov Rinat

> Как правило, в реальных приложениях напрямую с исходными таблицами
> работают крайне редко.
Дык я так понимаю что буферыы ввели как раз для того, чтобы не напрямую с
таблицами работать.

Не совсем. Цель буфера - это "развести" процесс внесения изменений (который может длится часами - пользователь вышел пообедать) и процесс сохранения внесенных изменений (который должен выполняться максимально быстро).

Т.е. пользователь вносит изменения в некоторую копию данных, а сами исходные данные при этом остаются не изменными до момента сохранения внесенных изменений.

Просто буферизация в FoxPro позволяет создать эту копию автоматически. У программиста нет необходимости создавать эту копию вручную. Ну, как Вы раньше создавали набор переменных.

Однако прямая правка таблиц, пусть даже и буферризированных имеет ряд проблем. В частности при использовании индексов Primary и Candidad. Поэтому для редактирования все-таки создают копию данных, но не через набор переменных, а через запрос (Select-SQL).

Этот запрос "оборачивают" в класс. В младших версиях FoxPro - параметризированное Local View, а начиная с VFP8 - класс CursorAdapter. При этом, при определенных настройках, изменения сделанные в Local View или CursorAdapter также автоматически будут "сбрасываться" в исходную таблицу.

По сути, тот же "буфер", но другими средствами.

Galyamov Rinat

> Другой вариант - это организовать контроль уникальности не через
> индекс, а через триггер на вставку. Вот триггер будет срабатывать только в
> момент сброса буфера. При определенных стандартах создания структуры базы
> данных можно написать универсальный (в рамках данной базы данных) триггер
> на контроль уникальности введенных данных.

Индекс - это все таки индекс. Он и быстрее и надежнее отработает чем тригер.

Вопрос спорный и не однозначный. Впрочем, не думаю, что имеет смысл затевать дискуссию на эту тему. Кое-что на эту тему можно почитать здесь

Контроль уникальности данных при помощи индекса
17 июн 08, 15:43    [5809934]     Ответить | Цитировать Сообщить модератору
 Re: Буферизация и индекс кандидат  [new]
Плохой-советчик
Guest
А все же индексы типа Primary и Candidad, я всегда считал, что должны заполняться автоматом и нечего юзеру самому там ползать.
Прописал в табличке в значении default value поля ссылку на Stored Procedures, где генерится уникальный индекс и забыл про это :D
17 июн 08, 15:59    [5810058]     Ответить | Цитировать Сообщить модератору
 Re: Буферизация и индекс кандидат  [new]
ВладимирМ
Member

Откуда: г. Москва
Сообщений: 7864
Плохой-советчик
А все же индексы типа Primary и Candidad, я всегда считал, что должны заполняться автоматом и нечего юзеру самому там ползать.
Прописал в табличке в значении default value поля ссылку на Stored Procedures, где генерится уникальный индекс и забыл про это :D

Угу. Справочник контрагентов. Разумеется, названия контрагентов повторяться не должны. Разумеется, удаленные записи не должны включаться в контроль уникальности. Разумеется, легко написать Default Value, чтобы автоматом присвоить имя новому конрагенту.

С Primary-индексом, как правило, проблем нет. Разумеется, если используются суррогатные ключи. Проблемы начинаются с индексами Candidad. Тут довольно много "но" и "если"...
17 июн 08, 16:07    [5810129]     Ответить | Цитировать Сообщить модератору
 Re: Буферизация и индекс кандидат  [new]
Плохой-советчик
Guest
Трудно представить, что по названиям контрагента идет индекс, не правда ли?
А если существует другой контрагент с тем же названием? Может тогда какое либо предупреждение выдать клиенту, типа существует контрагент с таким именем, вы уверены, что хотите завести нового с тем же именем.
А если оператор занесет по разному одно и то-же предприятие? "Бриг" ООО и ООО "Бриг" :)
Может такие вещи не стоит весить на индекс кандидат, а делать отдельную обработку?
17 июн 08, 17:33    [5811069]     Ответить | Цитировать Сообщить модератору
 Re: Буферизация и индекс кандидат  [new]
Плохой-советчик
Guest
прошу прощения за оффтоп
И какие данные мне не приходят в голову, я их ни как не могу представить в гриде, только форма с текстовыми полями, данные по клиенту, коих немеряно и заносить их в гриде немерянной ширины - нет уж, увольте. Грид для поиска и удобной навигации, щелчек и выходиш в форму. Или в гриде править мелочевку некую.
17 июн 08, 17:48    [5811226]     Ответить | Цитировать Сообщить модератору
 Re: Буферизация и индекс кандидат  [new]
Galyamov Rinat
Member

Откуда:
Сообщений: 658

> А все же индексы типа Primary и Candidad, я всегда считал, что должны
> заполняться автоматом и нечего юзеру самому там ползать.
> Прописал в табличке в значении default value поля ссылку на Stored
> Procedures, где генерится уникальный индекс и забыл про это :D

Ты не путай первичный ключ и индекс кандидат.

Кандидат призван для контроля неповторяемости самих данных, тогда как
первичный ключ - это ключ однозначно идентифицирующий набор данных (строку)


Posted via ActualForum NNTP Server 1.4

18 июн 08, 05:13    [5812913]     Ответить | Цитировать Сообщить модератору
 Re: Буферизация и индекс кандидат  [new]
Galyamov Rinat
Member

Откуда:
Сообщений: 658

> Автор: Плохой-советчик
> И какие данные мне не приходят в голову, я их ни как не могу
> представить в гриде, только форма с текстовыми полями, данные по клиенту,
> коих немеряно и заносить их в гриде немерянной ширины - нет уж, увольте.

Я тебя, в общем-то, и не заставляю программить грид на редактирование. Это
во - первых. Во - вторых, ты же не видишь чего я редактирую, а уже
критикуешь.


Ну и плюс ко всему, есть грид, для просмотра. Все данные в него включены
(т.е. по любому все поля НАДО показать пользователю). Так почему бы не дать
пользователю возможность редактировать их прямо в гриде???


Полей действительно много - 37.

1 - I, 36 - N(12,3) т.е. довольно таки широкие. Но, не поверишь, они все
совершенно спокойно помещаются в одну ширину экрана в гриде.

Ведь в гриде данные можно отобразить и в несколько строк. Я посчитал, что
мне достаточно 3-х. Итого у меня получается 13 колонок. 1 год и 12 месяцев.
На каждый год/месяц - 3 строки. "Годов" может быть несколько для каждого
объекта - поэтому ГРИД. Но для каждого объекта не может быть только
одинаковых "ГОДОВ" - поэтому индекс кандидат.


Posted via ActualForum NNTP Server 1.4

18 июн 08, 05:25    [5812917]     Ответить | Цитировать Сообщить модератору
Все форумы / FoxPro, Visual FoxPro Ответить