Цитата:
Сообщение от
Dolores
Еще раз на примере: есть 2 базы Work и Test.
1) В приложении Test (в Axapta) создаем таблицу TestFile. При синхронизации эта таблица появляется в базе Test
2) В базе Work в SQL создаем таблицу TestFile с такой же структурой
3) В базе Test в SQL удаляем таблицу TestFile
4) В базе Test в SQL создаем представление TestFile, связанное с базой Work.
Таким образом, при работе в приложении Test c таблицей TestFile данные записываются в базу Work через представление.
Но при синхронизации таблиц в приложении Test возникнет ошибка, потому что мы удалили таблицу в базе Test в SQL.
В версии Ax2.5 я сделал следующее
Исходная таблица TestFile в базе Test не удаляется, а переименовывается.
ДО штатной синхронизации выполняется:
- Удаление существующего View с указанным именем
- Переименование таблицы со специфическим именем в имя, только что удаленного View
Затем запускается штатный режим синхронизации по реально существующей таблице
ПОСЛЕ штатной синхронизации выполняется:
- Переименование таблицы в специфическое уникальное имя
- Создание нового View
Специфическое имя таблицы формируется как Имя_Таблицы_GUID.
Т.е. в конец имени таблицы через символ подчеркивания дописывается GUID сформированный через функцию NewId() на MS SQL сервере
Все параметры, необходимые как для переименования, так и для создания View хранятся в специально для этого созданной настроечной таблице
В "псевдокоде" это выглядит так
X++:
\\ \Classes\Application\dbSynchronize
boolean dbSynchronize(tableId tableId = 0, ...)
{
MyClass_SqlView myClass_SqlView;
(...)
// Переименование таблиц ДО синхронизации
myClass_SqlView = new MyClass_SqlView();
myClass_SqlView.restoreOrigConfig(tableId);
// Собственно синхронизация
ok = super(tableId, syncAsNeeded, continueOnError, showProgress, checkSyncTables);
// Переименование таблиц ПОСЛЕ синхронизации
myClass_SqlView.replaceTableOnView(tableId);
(...)
}
Для MS SQL переименование - это хранимая процедура sp_rename. Использовать можно так
Код:
-- Скрипт MS SQL
if ObjectProperty(Object_Id('Старое_Имя'), 'IsUserTable') = 1
exec sp_rename 'Старое_Имя','Новое_имя'
Если в качестве параметра TableId передан 0, то переименовываются все View, имена которых хранятся в настроечной таблице
Соответственно, в рабочей базе просто надо удалить записи в этой настроечной таблице, чтобы использовалась сама таблица, а не создавалось View на ее основе.
View именно удаляются/создаются по той причине, что в исходную таблицу TestFile могут быть добавлены/удалены поля. Т.е. без пересоздания View может произойти рассинхронизация структуры View и таблицы-образца.
Тут есть некоторая проблема, связанная с тем, что в случае модификации структуры собственно настроечной таблицы, где хранятся имена для переименования, может возникнуть конфликт при выполнении myClass_SqlView.restoreOrigConfig(). Но вероятность такого конфликта не высока, а если он все-таки возник, то лучше "вручную" синхронизировать сначала эту настроечную таблицу, и только после этого выполнять синхронизацию View.
PS: У нас подобные View использовались для объединения данных из нескольких баз. Т.е. View - это Select * from Base1.dbo.Table1 UNION ALL Base2.dbo.Table1