powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / 5 буферизация
11 сообщений из 11, страница 1 из 1
5 буферизация
    #33713115
men dea
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В БД связаны 2 таблицы А и Б. В 5-м режиме буферизации обеих таблиц я вношу или удаляю данные. Referential Integrity установлено везде в RESTRICT.
Есть форма, на ней пара Гридов на базе каждой таблицы
Если я внесу записи в родительскую таблицу A, а затем связанные с ними записи в B, то при попытке сохранения всех изменений ошибка не возникнет в том случае, если порядок сброса буферов:
Tableupdate(.t.,.t.,'A')
Tableupdate(.t.,.t.,'B')

А если производится удаление записей, то согласно правилам RI, вначале нужно удалить в B, а затем в А. И тогда порядок полного сброса буферов
Tableupdate(.t.,.t.,'B')
Tableupdate(.t.,.t.,'A')

Но если проводится разноплановое изменение БД (и удаление, и ввод), то при любой очередности ошибки не избежать.

Что в таких случаях обычно делают для корректной обработки? Чтобы полегче было :)
1. Запрещают проводить операции другого типа, пока не было произведен сброс буферов в соответствующей таблице?
2. Или легче отказаться в RI от RESTRICT в пользу IGNORE?
3. Или еще проще перейти к 3-типу буферизации?
4. Или же ведется пошаговая обработка всех измененных записей?
...
Рейтинг: 0 / 0
5 буферизация
    #33714171
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Решения "в общем случае" сводится к построчному сбросу буфера. Т.е. не одна команда TableUpdate() сразу на все, а перебор в цикле по GetNextModified() и построчный сброс. В одном случае от главной к подчиненной, в другом - наоброт.

Но! Обсуждение "общего случая" - практически бесполезное занятие. Давай конкретную постановку задачи, там видно будет. Только не надо постановку задачи по типу как в фильме про Астерикса и Обеликса:

- Почему дверь на уровне второго этажа?
- А вдруг жилец захочет построить второй этаж, а дверь у него уже есть!

Т.е. не надо "а вдруг". Нужна конкретная задача.
...
Рейтинг: 0 / 0
5 буферизация
    #33715726
men dea
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вы, г-н Максимов, несмотря на всю "неконкретность" уже на 99% ответили на мой вопрос. Спасибо. И с праздником вас!
Теперь оставшийся 1% моего непонимания: (извиняюсь, но чуть усложню первоначальное условие)

В БД есть 3 связанных (все RI=Restrict) таблицы, в которых id -AutoInc:
Код: plaintext
1.
2.
filial (idFilial, cFilial)
otdel (idFilial, idOtdel, cOtdel)
kadr (idFilial, idOtdel, idKadr, cKadr).

На форме 3 Грида, каждый отвечает за соответствующую таблицу. Все таблицы находятся в 5-й буферизации. Записи вводятся, удаляются, корректируются. Корректность изменений отслеживается. С этим проблем нет.
Проблема при выходе, когда при наличии изменений на выходе из формы задается вопрос "Сохранить – Отменить?". Отмена изменений тривиальна. А вот, "сохранение" порождает описанный ранее trouble.

Как бы "покультурнее" обработать выход с использованием этой GETNEXTMODIFIED(), сохранив все изменения? Может, рекурсия какая-нибудь возможна?
А то у меня получается какая-то вавилонская башня из многочисленных циклов с проверкой всех таблиц. (На самом деле цепочка связанных таблиц у меня длиннее, но для моего понимания 3 будет вполне достаточно.)
...
Рейтинг: 0 / 0
5 буферизация
    #33715745
men dea
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Короче ничего не придумал. Да, и здесь время от времени Getnextmodified(lnCurRec) выдает значение -1. Что бы это означало?

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
Local lcALIAS, llOK, lnCurRec
Declare llOK( 3 )
Store .T. To llOK

Set Deleted Off
Begin Transaction

lnCurRec = Getnextmodified( 0 ,'kadr')	&& Start with the first modified record.
Do While lnCurRec> 0 						&& DO until all modified records are processed.
	Goto (lnCurRec) In kadr				&& Move to the current modified record.
	If Deleted('kadr')
		llOK( 3 )=Tableupdate(.F.,.T.,'kadr') And llOK( 3 )
	Endif
	lnCurRec = Getnextmodified(lnCurRec,'kadr')	&& Get the next modified record from here.
Enddo

lnCurRec = Getnextmodified( 0 ,'otdel')	&& Start with the first modified record.
Do While lnCurRec> 0 					&& DO until all modified records are processed.
	Goto (lnCurRec)	In otdel			&& Move to the current modified record.
	If Deleted('otdel')
		llOK( 2 )=Tableupdate(.F.,.T.,'otdel') And llOK( 2 )
	ENDIF
	lnCurRec = Getnextmodified(lnCurRec,'otdel')	&& Get the next modified record from here.
Enddo

llOK( 1 )=Tableupdate(.T.,.T.,'filial') And llOK( 1 )
llOK( 2 )=Tableupdate(.T.,.T.,'otdel') And llOK( 2 )
llOK( 3 )=Tableupdate(.T.,.T.,'kadr') And llOK( 3 )

Set Deleted On

If llOK( 1 ) And llOK( 2 ) And llOK( 3 )

	End Transaction
	=Messagebox('Saved')
Else
	Rollback
	=Messagebox('Saving Error: in ';
		+Iif(llOK( 1 ),' ',' filial');
		+Iif(llOK( 2 ),' ',' otdel');
		+Iif(llOK( 3 ),' ',' kadr'))
Endif
...
Рейтинг: 0 / 0
5 буферизация
    #33716180
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если таблица буферизирована, то при добавлении новой записи эта новая запись добавляется в буфер таблицы, но в самой таблице ее физически еще нет. Значит, она не может иметь физического номера записи.

Но как-то обрабатывать такие записи в буфере необходимо. Поэтому такие записи получают ОТРИЦАТЕЛЬНЫЙ физический номер записи. То, что возвращает функция Recno(). Первая добавленная запись -1, вторая -2, третья -3 и т.п.

Функция GetNextModified() также возвращает физический номер записи. Разумеется, для новых записей в буфере таблицы будет возвращено отрицательное значение. Ведь именно такое значение и имеет физический номер записи.

По поводу постановки задачи я уже сказал. НАПИШИТЕ ПОСТАНОВКУ ЗАДАЧИ.

Ну, не верю я, что у вас сильно навороченная форма с кучей таблиц. Пользователь несколько часов что-то с ней мудрит. Все это происходит в буфере. А потом, в конце рабочего дня нажимает кнопку "Сохранить".

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

Есть: Филиал, Отдел, Персонал. ЧТО ЭТО? КАКОВА ЦЕЛЬ этой формы? ЧТО пытаются при помощи нее сделать? Какой функционал реализовать?

Попробуйте хотя бы для себя ответить на эти вопросы. Потом поставьте вопрос так: а это ДЕЙСТВИТЕЛЬНО надо реализовать в одной форме? Вы не пытаетесь выдать собственное желание за реальную постановку задачи (а вдруг понадобиться второй этаж, а дверь уже есть)?

Как правило, просто ответ на эти вопросы снимает большинство проблем.
...
Рейтинг: 0 / 0
5 буферизация
    #33716605
men dea
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Признаюсь, я не знал про отрицательные номера записей. Я думал, что это - какая-то ошибка. В Help VFP-9 по функции GETNEXTMODIFIED() ничего об этом не сказано.

Я поэкспериментировал, и вижу, что переход на отрицательный номер в буфере вполне хорошо переваривается. Правда, в буфере эта новая запись стоит последней и имеет также вполне "земной" номер 43. И откликается на Go 43 с таким же успехом, как и на "инопланетное" на Go (-1).
Ну, да ладно: коль так сделали создатели, видимо, так нужно. Буду с этим чудом считаться.

Не очень-то мне понятно, каким образом постановка задачи "вяжется" с моим вопросом.
Ответить на него вам вполне успешно удалось. Но секрета из нее я делаю. Может, еще путный совет получу. Поэтому почти все:

На предприятии есть филиалы, которые открываются dOpen и закрываются dClosed.
Таблица-справочник filial (idFilial, cFilial, dOpen, dClosed).
В филиалах есть отделы: otdel (idFilial, idOtdel, cOtdel, dOpen, dClosed).
Есть набор лиц, которые работают на данном предприятии: таблица fio (idFio,cFio) . Есть набор должностей/рабочих мест/специальностей, которые представлены таблицей-справочником spec(idSpec,cSpec).
Данные лица могут одновременно работать в разных отделах-филиалах и по разным специальностям, когда-то увольняться (dOut) и вновь приниматься d(Inp). Поэтому создается таблица kadr (idKadr, idOtdel, idFio, idSpec, dInp, dOut, nProcent).

Почти все отделы ежемесячно зарабатывают некую сумму денег nSum (вводится одной записью в месяц по отделу), которая хранится в таблице dohod (idDohod, idOtdel, dDate, nSum). Потом эта заработанная за месяц сумма dohod.nSum распределяется по конкретным исполнителям, в зависимости от zarp.nProcent, который за основу берется из kadr.nProcent, но может также меняться ежемесячно:
Все это отражается в таблице zarp (idZarp, idKadr, dDate, nProcent).

В ранее указанной форме, из-за которой появился этот топик, я реализую структуру подразделения. Собственно, таблицу kadr, попутно позволяя юзеру разобраться с открытием-закрытием-ветвлением филиалов отделов.

На форме 3 Грида. Они отвечают за таблицы filial, otdel, kadr. В зависимости от того, по какой грид активен, с тем и производится ввод-корректировка-удаление-печать сводок. Для этого есть 3 кнопки (Новая, Удаление, Печать) + 3 дополнительных (Сохранить-Отменить-Выход). Хочет user – сохраняет изменения время от времени. Ленится – при нажатии на Выход выплывет запрос на Сохранение-Отмену.

Что-то вроде мобильного телефона: немного кнопок, но много функций. :))

Здесь ранее присутствовал еще 4 Грид по fio, чтобы не бегать в другую форму, добавлять нового работника, когда его забыли ввести. Но затем Грид удалил. Текучка кадров была небольшая, а проблем с синхронизацией 4-х Гридов было много.

Итак, в обсуждаемой форме, собственно, создаются idKadr- коды для кадров. Далее эти коды используются при заботе с другой формой, по распределению ежемесячных заработков по сотрудникам. Там задается рабочий месяц, user выбирает филиал-отдел, ему предоставляется список кадров, из которых выбираются счастливчики по принципу сороки из известной считалки: "этому дала, этому не дала.
Цель всей "компьютеризации" состоит в получении сводки по ежемесячным заработкам конкретного ФИО, распределения денег по отделам, филиалам и учета их доходов.

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

Фактически это - моя первая программа под WINDOWS+VFP. До этого я лет 10 "стряпал" на Clipper, Assembler, С. А теперь работодатели разбогатели и купили вместо 486,P-1 и матричных принтеров технику получше. XP+VFP уже поддерживается.
Возможно, ряд проблем был бы снят, если бы использовались Modeless формы. Тогда можно было бы каждую таблицу загнать в свою форму и не плодить по 3 Грида на одной. Но я столкнулся с кучей проблем при синхронизации независимых форм. И решил, что хотя бы от этого "головняка" откажусь.
...
Рейтинг: 0 / 0
5 буферизация
    #33716610
men dea
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Извиняюсь, небольшая ошибочка:
Таблица zarp имеет структуру не (idZarp, idKadr, dDate, nPROCENT), а (idZarp, idKadr, dDate, nSUMkadr). Потому, что изначально ежемесячная dohod.nSUM отдела распределятся на зарплаты избранных в этом месяце кадров, согласно kadr.nPROCENT. Поэтому сумма процентов не всегда 100%. Да, еще копейки при округлении. И user хочет корректировать суммы зарплат самостоятельно.

Вот, и ответьте мне: ДЕЙСТВИТЕЛЬНО ли излишне я реализовал в одной форме?
Мне кажется, что при таких желаниях пользователя, не только дверь на 2 этаж может понадобиться?
:))
...
Рейтинг: 0 / 0
5 буферизация
    #33719052
Igor Korolyov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Hi men dea!

> 4. Или же ведется пошаговая обработка всех измененных записей?

Да пошаговая, причём в 2 прохода (кроме самого верхнего уровня).

Сначала проводим сохранение "удалённых" записей, от самых "глубоких" наружу,
потом сохранение ВСЕХ в курсоре первого уровня, и наконец сохранение
добавленных и изменённых записей - но уже от "наружных" вглубь.

Т.е. если имеется схема вида

A->B->C

1) Циклом по GetNextModified() пропуская все где !DELETED() надо сохранить
С, B
2) Сохраняем все из A
3) Циклом по GetNextModified() - там уже естественно остались только новые и
изменённые записи - в порядке B,C

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

Posted via ActualForum NNTP Server 1.3
...
Рейтинг: 0 / 0
5 буферизация
    #33721722
men dea
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Игорь, хотя вы столь подробно описали, но я не все понял. Проблемы терминологии. :)

1. Что означает в вашем понимании "в курсоре первого уровня" и "от самых глубоких наружу"?

Курсор 1 уровня - это самый простой справочник или самый составной?
В моем случае – это filial или kadr ? "Наружу" это от filial к kadr или наоборот?

2. 1) Циклом по GetNextModified() пропуская все где !DELETED() надо сохранить С, B

Это:
а) один цикл, в котором обрабатываются сразу C и B?
б) два идущих вслед друг за другом цикла: сначала по C, потом по B?
в) два вложенных цикла: внешний по C, внутренний по B?

3) если имеется схема вида A->B->C

В моем случае A – это filial или kadr ?

4) Циклом по GetNextModified() - там уже естественно остались только новые и
изменённые записи - в порядке B,C

А разве нельзя сделать двумя командами

TableUpdated(.T., B)
TableUpdated(.T., С)

без цикла по GetNextModified() ? Ведь там уже не осталось необработанных "удаленных" ...

----------------------

Я подозреваю, что я сделал ранее предложенный кусок программы в соответствии с вашим советом. С единственной поправкой: следует заменить условие в циклах, учитывая замечания Владимира М., с

Код: plaintext
Do While lnCurRec> 0 	&& DO until all modified records

на

Код: plaintext
Do While lnCurRec# 0 	&& DO until all modified records


PS Мне кажется, что непринципиально начинать с удаленных, а потом переходить на новые и модифицированные. Можно и наоборот, только нужно сменить направление обработки. Или я тут ошибаюсь?
...
Рейтинг: 0 / 0
5 буферизация
    #33724882
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вообще-то, как сказал классик, "разруха начинается в головах". Итак, что я вынес (и унес с собой) из всего описанного ТЗ

Сейчас меня не интересует физическая основа всего этого (какие таблицы и какие поля). Меня интересует именно орагнизация процесса. Из организационной части имеем

men deaНа предприятии есть филиалы ...
В филиалах есть отделы...
Есть набор лиц, которые работают на данном предприятии...
Есть набор должностей/рабочих мест/специальностей...
Данные лица могут одновременно работать в разных отделах-филиалах и по разным специальностям...

отделы ежемесячно зарабатывают некую сумму денег...
Потом эта заработанная за месяц сумма ... распределяется по конкретным исполнителям...


Ключевой вопрос: ради чего все это затевается? Что должна обеспечить эта форма?

Это все затеяно ради кадрового учета (какой человек где работает) или ради финасового учета (какую сумму кому выплачивать)?

Смешивать эти функции - бессмысленно. Финансист не должен (и не будет) заниматься вопросами кадрового учета. С другой стороны, кадровик не должен (и не будет) заниматься вопросами начисления зарплаты.

С точки зрения финансиста - кадровая структура на момент начисления зарплаты есть величина постоянная. Не будет он заниматься созданием нового филиала или отдела. Ему всего-лишь надо знать общую структуру. Кто где находится.

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

men deaВ ранее указанной форме, из-за которой появился этот топик, я реализую структуру подразделения. Собственно, таблицу kadr, попутно позволяя юзеру разобраться с открытием-закрытием-ветвлением филиалов отделов.

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

Т.е. "переменной" величиной здесь является именно "кадр". Все остальное: филиал, отдел, должность, специальность - это вспомогательная информация. Набор справочников.

Причем эта информация никак, никоим образом, не зависит от этого самого "кадра". Это информация должна существовать самостоятельно и независимо от факт приема/увольнения/оформления человека.

Следовательно, непосредственно в данной форме можно редактировать только и исключительно записи таблицы kadr. Если возникает необходимость изменить содержимое таблиц филиалов, отделов, должностей, то это должно делаться в отдельных формах.

Как следствие, отпадает необходимость в "навороченном" режиме сохранения. Сохраняется только модификация одной единственной таблицы kadr. А тут уже все равно что ты с ней делал: удалял, создавал, модифицировал. Один TableUpdate() на эту таблицу и все.

Без крайней необходимости не надо смешивать в одной и той же форме несколько функций. Это ведет не только к существенному усложнению программного кода, но и к усложнению восприятия программы вообще. Самим пользователем.

Как правило, у разных пользователей разный круг интересов и "зоны ответственности":

Есть "большой начальник", которого интересует общая структура компании и он за это дело отвечает. Это уровень "Филиалов". Что там происходит внутри филиала - это для него уже слишком "мелко".

Начальник филиала уже заинтересован в том, чтобы разобраться с "отделами", но вникать в кадровый состав он вряд ли будет. Не барское это дело.

Соответственно кадровик уже всего-лишь распределяет персонал по ранее созданным филиалам и отделам.

А теперь представь, что кадровик получил возможность создать/удалить/изменить филиал. Ничего себе компания? Кто же ей управляет? Кадровик или тот самый "большой начальник"?

Да, разумеется, "большой начальник" скорее всего вообще не умеет работать на компьютере. Но дело это не меняет. Он назначит ответственного. За поддержание актуальности разной информации отвечают разные люди . А ты заставляешь их всех работать с информацией, которая им вообще не нужна!

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

Зачем при вводе нового человека мне создавать новый филиал? А по шее не дадут? Кто вообще тут управляет компанией (создает филиалы)? Какой-то кадровик или "большой начальник".

Даже если именно кадровику дали права на изменение записи о филиалах делать это изменение в общей форме - неразумно. Одно неверное движение и ...
...
Рейтинг: 0 / 0
5 буферизация
    #33725541
Igor Korolyov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Hi men dea!

> 1. Что означает в вашем понимании "в курсоре первого уровня"

это А - тот к которому всё привязано. "Шапка документа" в сложных
документах.

> и "от самых глубоких наружу"?

Если есть "шапка" и "строки", то строки это и есть внутренние, глубокие
уровни. В нарисованной схема B это второй уровень (записи подчинённые A), а
C в свою очередь это 3-й уровень, они подчинены записям из B.

> Курсор 1 уровня - это самый простой справочник или самый составной?

Речь тут не про справочники обычно идёт (я не считаю разумным править в
одной и той-же форме несколько справочников) - а про составные документы -
типа накладных. Там "шапка" и "строки" чётко между собой связаны, и не имеют
смысла сами по себе - т.е. вводятся они вместе, и отображать их тоже имеет
смысл одновременно.

> В моем случае - это filial или kadr ? "Наружу" это от filial к kadr или
> наоборот?

Я не вникал глубоко в твою схему данных, но в общем случае направление
задаётся имеющимися постоянными связями (те что прописаны в самой БД, с
которыми связаны ограничения целостности aka RI - не те временные связи что
устанавливаются для формы).
Т.е. если из A (шапки) нельзя удалить запись, пока в B (строках) есть
ссылающиеся на неё записи (RI ограничение типа Restrict) - то я считаю что А
это "наружняя" таблица, а B соответственно "внутренняя". Заодно опишем
словами и второе Restrict ограничение - на вставку - в B нельзя вставить
записи, ссылающиеся на отсутствующие в A записи.
Из этого и вытекают все мои рассуждения - удалять необходимо сначала из B и
лишь затем из А - а вот вставлять наоборот - сначала в A, а потом в B (т.е.
надо чтобы запись в A уже существовала на момент вставки в B). Также
уточним, что здесь под вставкой/удалением подразумевается работа с самой
таблицей, а не с буфером, или там LocalView - т.е. реально действия
иницииуюся по TableUpdate() а не по командам Delete/Insert/Update - которые
лишь меняют данные в буфере, и как-бы "запоминаются" до момента
tableupdate() чтобы потом выполнить те-же самые изменения но уже в реальных
таблицах.

>> 2. 1) Циклом по GetNextModified() пропуская все где !DELETED() надо
>> сохранить С, B
> Это:
> а) один цикл, в котором обрабатываются сразу C и B?
> б) два идущих вслед друг за другом цикла: сначала по C, потом по B?

Именно так.

> в) два вложенных цикла: внешний по C, внутренний по B?

Нет, вот наоборот в приниципе можно - т.е. крутить цикл по В, внутри него по
C, НО "сохранять" (т.е. реально это будет удаление) сначала записи из С, а
потом из B (ту самую на которую и ссылались только что удалённые из С). Но
это IMHO излишняя сложность - в варианте б) мы получим точно такой-же
результат но заметно проще (псевдо-конфликтов не будет, т.к. сначала мы
удаляем всё из C, и это позволит провести удаление из B). Правда у тебя
(теоретически) могут быть более сложные триггеры, которые потребуют
абсолютно точного соблюдения последовательности операций сохранения, но это
маловероятно, да и других проблем с сильно наворочеными триггерами будет
масса :)
Конечно возможны реальные конфликты - т.е. мы попытались удалить запись из
B, не удалив при этом хотя-бы одну запись из C - это отловится во время
попытки "сохранения" (удаления) этой самой записи из B.

> 3) если имеется схема вида A->B->C
> В моем случае A - это filial или kadr?

Видимо filial - т.к. именно в kadr имеется внешний ключ ссылающийся на
filial... Но тут уж тебе виднее схема.

>> 4) Циклом по GetNextModified() - там уже естественно остались только
>> новые и
>> изменённые записи - в порядке B,C
> А разве нельзя сделать двумя командами
> TableUpdated(.T., B)
> TableUpdated(.T., С)
> без цикла по GetNextModified() ? Ведь там уже не осталось необработанных
> "удаленных" ...

Можно (но конечно и тут 2-х строк не хватит :) ), но тогда сложее "поймать"
на какой из записей произошла ошибка сохранения - а так она уже "под
руками". Впрочем это больше вопрос написания кода - и так можно и этак :)

> Я подозреваю, что я сделал ранее предложенный кусок программы в
> соответствии с вашим советом.

Да вполне возможно :)

> PS Мне кажется, что непринципиально начинать с удаленных

Принципиально. Если в C были добавлены записи, а из B соответствующий
родитель был удалён, то мы получим ошибку при попытке сохранения B, тогда
как IMHO более логично говорить об ошибке в C. Есть и другие моменты -
например если сначала заниматься удалёнными, то для курсора самого верхнего
уровня (A) можно проводить сохранение упрощённо - в один проход - т.к. к
тому времени уже все потенциальные "нарушители" RI правила на удаление
фактически удалены из B.

> Можно и наоборот, только нужно сменить направление обработки.

Направление обработки, если под ним понимать последовательность обработки
таблиц (а не записей) зависит лишь от типа операции. Для удаления необходим
сначала удалить дочерние, а потом родительскую - для вставки наоборот.

Ещё один важный момент - такая схема подразумевает что всё сохранение
проводится в рамках одной транзакции (и если на каком-то этапе возникает
ошибка, то транзакция откатывается - и более того производится RECALL
удалённых записей в буфере - иначе просто невозможно будет исправить ряд
ошибок). Я не вижу такой тесной логической связи между твоими данными, чтобы
требовалась единая транзакция для их сохранения - поэтому скорее всего тебе
необходимо разбить форму на несколько более простых, но логически "цельных".
Т.е. говоря проще при вводе накладной не следует в той-же самой форме
вводить/править товары, клиентов/организации, банки и т.п. Так и тут - при
вводе сумм поощрений не следует в той-же форме править филиалы, организации,
сотрудников и т.п. Тогда форма у тебя получится скорее всего
"однотабличная" - в том смысле что изменения будут вносится в одну таблицу,
а прочие таблицы лишь будут служить для фильтрации и навигации (и не будут
изменяться в данной форме).

Posted via ActualForum NNTP Server 1.3
...
Рейтинг: 0 / 0
11 сообщений из 11, страница 1 из 1
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / 5 буферизация
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]