AXForum  
Вернуться   AXForum > Microsoft Dynamics AX > DAX: Программирование
DAX
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 13.01.2021, 13:48   #1  
Ace of Database is offline
Ace of Database
Участник
Аватар для Ace of Database
 
870 / 637 (23) +++++++
Регистрация: 14.10.2004
А если просто в журнале базы данных SysDatabaseLog искать все записи за последнюю минуту, у которых нужный TableId ?
__________________
Мои утилиты для Аксапты версий 3.0-2012: http://aceofdatabase.blogspot.com/
Старый 13.01.2021, 13:57   #2  
Ace of Database is offline
Ace of Database
Участник
Аватар для Ace of Database
 
870 / 637 (23) +++++++
Регистрация: 14.10.2004
Я как-то делал отчет, который из журнала базы данных достает историю изменения выбранных полей. Вроде довольно быстро работает на базе в 500 Гб. Правда там журнал базы данных хранился только за последние 2 недели, а потом обрезался.
А вам всего-то надо узнать какие записи изменились из списка нужных вам таблиц.
__________________
Мои утилиты для Аксапты версий 3.0-2012: http://aceofdatabase.blogspot.com/
Старый 13.01.2021, 14:29   #3  
Vadik is offline
Vadik
Модератор
Аватар для Vadik
Лучший по профессии 2017
Лучший по профессии 2015
 
3,631 / 1849 (69) ++++++++
Регистрация: 18.11.2002
Адрес: гражданин Москвы
Цитата:
Сообщение от Ace of Database Посмотреть сообщение
Я как-то делал отчет, который из журнала базы данных достает историю изменения выбранных полей. Вроде довольно быстро работает на базе в 500 Гб
"Довольно быстро", или "достаточно быстро чтобы непрерывно делать это 10+ раз в минуту", учитывая других читателей-писателей в лог ?
__________________
-ТСЯ или -ТЬСЯ ?

Последний раз редактировалось Vadik; 13.01.2021 в 14:53.
Старый 13.01.2021, 15:37   #4  
Ace of Database is offline
Ace of Database
Участник
Аватар для Ace of Database
 
870 / 637 (23) +++++++
Регистрация: 14.10.2004
Цитата:
Сообщение от Vadik Посмотреть сообщение
"Довольно быстро", или "достаточно быстро чтобы непрерывно делать это 10+ раз в минуту", учитывая других читателей-писателей в лог ?
Я делал отчет, который парсил контейнер, чтобы достать значения конкретных полей. И еще надо поймать момент изменения именно нужного поля среди прочего мусора. Поэтому основное время уходило на этот парсинг.
А запрос к таблице SysDatabaseLog вроде быстро выполнялся. Прошло уже несколько лет с того времени. По-любому надо пробовать. По-моему это самый простой способ решить данную проблему. А начинать пробовать надо с простых способов.
Хотя все-таки поймать изменение конкретного поля через таблицу SysDatabaseLog - задача не очень тривиальная, но пример как это сделать есть. Даже на этом форуме выкладывали.
__________________
Мои утилиты для Аксапты версий 3.0-2012: http://aceofdatabase.blogspot.com/
Старый 13.01.2021, 15:39   #5  
Ace of Database is offline
Ace of Database
Участник
Аватар для Ace of Database
 
870 / 637 (23) +++++++
Регистрация: 14.10.2004
Запустил у себя сейчас такой джоб.
Для 26 тысяч клиентов он отработал примерно за 2 минуты (если убрать вывод в инфолог)
Это для Аксапты версии 3.0

X++:
static void sysDatabaseLogFieldChangedCustAxForum(Args _args)
{
    CustTable                    custTable;
    SysDatabaseLog               SysDatabaseLog;

    int                          i;
    container                    tmp;

    SysOperationProgress         sysOperationProgress = new SysOperationProgress(1);
    int                          stepCount;
    int                          total;
    UserInfo                    UserInfo;

;
    select count(RecId) from custTable;
    total = custTable.RecId;

    sysOperationProgress.setTotal(total);

    while select custTable
    {
        stepCount ++;
        sysOperationProgress.setCount(stepCount);
        sysOperationProgress.setText(strFmt("%1 запись из %2", stepCount, total));

        while select SysDatabaseLog order by createdDate, createdTime
            where SysDatabaseLog.LogRecId == custTable.RecId
              &&  SysDatabaseLog.table    == custTable.TableId
        {
            if (typeOf(conpeek(SysDatabaseLog.Data, 1)) == Types::Container)
            {
                for ( i = 1; i <= conlen(SysDatabaseLog.data); i ++)
                {
                    tmp = conpeek(SysDatabaseLog.Data, i );
                    if (fieldExt2Id(conpeek(tmp, 1)) == fieldnum(custTable, zResponsibleDivision))
                    {
                        if(conpeek(tmp, 3) != conpeek(tmp, 2))
                        {
                            select firstonly UserInfo where UserInfo.Id == SysDatabaseLog.createdBy;
                            info(strfmt("%1 ~ %2 ~ %3 ~ %4 ~ %5", custTable.AccountNum, UserInfo.name,  SysDatabaseLog.createdDate, conpeek(tmp, 3),conpeek(tmp, 2) ));
                        }
                    }
                }
            }
        }
    }
}
__________________
Мои утилиты для Аксапты версий 3.0-2012: http://aceofdatabase.blogspot.com/

Последний раз редактировалось Ace of Database; 13.01.2021 в 15:41.
Старый 13.01.2021, 14:52   #6  
Pustik is offline
Pustik
Участник
 
807 / 372 (14) ++++++
Регистрация: 04.06.2004
Цитата:
Сообщение от Ace of Database Посмотреть сообщение
Правда там журнал базы данных хранился только за последние 2 недели, а потом обрезался.
А вам всего-то надо узнать какие записи изменились из списка нужных вам таблиц.
Там еще хотят запускать за определенные периоды :
Цитата:
Сообщение от trud Посмотреть сообщение
в нормальном режиме будут запускать раз в минуту по группе(т.е. в минуту будет даже больше запусков, несколько десятков)-это хотелось бы сделать быстро. но ничего не мешает запустить произвольный интервал, например за год
т.е. лог придется хранить для этих таблиц как минимум год. Но идея хорошая если лог небольшой и скорость будет приемлемая.Опять таки надо пробовать.
На худой конец можно создать свой лог-таблицу под эту задачу.
У нас практикуется репликация о которой говорил axm2017.
Цитата:
Сообщение от axm2017 Посмотреть сообщение
Типичное ( во всяком случае видел реализации подобной идеи на пакете)

Параметр - время запуска

При запуске процесса выбираем все измененные записи от параметра до текущего момента (ессно при включенном modified time).

Далее после обработки сохраняем в параметре текущее время.
правда без ограничения на изменение определенных полей и без такого чуда как LOGISTICSELECTRONICADDRESS(слава богу).Работает массово и стабильно уже много лет в пакетах.

Цитата:
Сообщение от Vadik Посмотреть сообщение
"Довольно быстро", или "достаточно быстро чтобы непрерывно делать это 10+ раз в минуту", учитывая других читателей-писателей в лог ?
Если под эту задачу сделать свою таблицу, да с толковыми индексами, то будет очень быстро работать.
__________________
-Ты в гномиков веришь?
-Нет.
-А они в тебя верят, смотри, не подведи их.

Последний раз редактировалось Pustik; 13.01.2021 в 15:00.
Старый 13.01.2021, 16:29   #7  
trud is offline
trud
Участник
Лучший по профессии 2017
 
1,038 / 1629 (57) ++++++++
Регистрация: 07.06.2003
Записей в блоге: 1
Там главная проблема в том что связи сложны. Ну т.е. я там выше привел пример запроса который они сейчас используют. (Выгрузка измененных клиентов во внешнюю систему)
Т.е. понятно что для одной таблицы это все сделать просто. С outer join у вас будет 8 вариантов в различных комбинациях. Если делать с интервалом несколько часов(чтобы покрыть длинные транзакции) то данных будет много
Старый 13.01.2021, 16:38   #8  
Ace of Database is offline
Ace of Database
Участник
Аватар для Ace of Database
 
870 / 637 (23) +++++++
Регистрация: 14.10.2004
А если вот так сделать?
А потом уже сопоставлять отобранные записи вручную между собой через всякие Map'ы ?

X++:
while select SysDatabaseLog order by createdDate, createdTime
            where 
                SysDatabaseLog.table    == tableNum(custTable)
            ||  SysDatabaseLog.table    == tableNum(DIRPARTYLOCATION)
            ||  SysDatabaseLog.table    == tableNum(LOGISTICSELECTRONICADDRESS)
{
}
__________________
Мои утилиты для Аксапты версий 3.0-2012: http://aceofdatabase.blogspot.com/
Старый 13.01.2021, 16:45   #9  
Ace of Database is offline
Ace of Database
Участник
Аватар для Ace of Database
 
870 / 637 (23) +++++++
Регистрация: 14.10.2004
Вот так запихнуть всю историю в мапы, а потом мапы сопоставляеть между собой

X++:
Map mapCustTable = new Map(Types::String, Types::Container),
Map mapDIRPARTYLOCATION = new Map(Types::String, Types::Container),
Map mapLOGISTICSELECTRONICADDRESS = new Map(Types::String, Types::Container),

while select SysDatabaseLog order by createdDate, createdTime
            where 
                SysDatabaseLog.table    == tableNum(custTable)
            ||  SysDatabaseLog.table    == tableNum(DIRPARTYLOCATION)
            ||  SysDatabaseLog.table    == tableNum(LOGISTICSELECTRONICADDRESS)
{
    switch(SysDatabaseLog.table)
    {
        case tableNum(custTable):
            mapCustTable.insert(strfmt("%1_%2_%3", SysDatabaseLog.LogRecId, SysDatabaseLog.CreatedDate, SysDatabaseLog.CreatedTime), SysDatabaseLog.data);
            break;
    }
}
__________________
Мои утилиты для Аксапты версий 3.0-2012: http://aceofdatabase.blogspot.com/
Старый 13.01.2021, 16:50   #10  
Ace of Database is offline
Ace of Database
Участник
Аватар для Ace of Database
 
870 / 637 (23) +++++++
Регистрация: 14.10.2004
Т.е. у вас будет 8 мапов.
Например, если в мапе mapLOGISTICSELECTRONICADDRESS изменилось нужное вам поле, то вы уже можете обычным для Аксапты способом через таблицу LOGISTICSELECTRONICADDRESS выйти на того клиента, и узнать его код. И даже сопоставлять между собой эти 8 мапов не надо.
__________________
Мои утилиты для Аксапты версий 3.0-2012: http://aceofdatabase.blogspot.com/
Старый 13.01.2021, 17:10   #11  
Ace of Database is offline
Ace of Database
Участник
Аватар для Ace of Database
 
870 / 637 (23) +++++++
Регистрация: 14.10.2004
Вот как-то так:
X++:
    LogisticsElectronicAddress logisticsElectronicAddress;
    MapEnumerator me = new MapEnumerator(mapLogisticsElectronicAddress);
    CustTable custTable;
    RefRecId refRecId;
    while (me && me.moveNext())
    {
        refRecId = str2Int64(conPeek(str2Con_RU(me.currentKey(), "_"), 1));
        logisticsElectronicAddress = LogisticsElectronicAddress::findRecId(refRecId);
        custTable = CustTable::findByPartyRecId(logisticsElectronicAddress .PrivateForParty);
    }
__________________
Мои утилиты для Аксапты версий 3.0-2012: http://aceofdatabase.blogspot.com/

Последний раз редактировалось Ace of Database; 13.01.2021 в 17:13.
Старый 13.01.2021, 18:53   #12  
trud is offline
trud
Участник
Лучший по профессии 2017
 
1,038 / 1629 (57) ++++++++
Регистрация: 07.06.2003
Записей в блоге: 1
что-то я потерял идею
X++:
while select SysDatabaseLog order by createdDate, createdTime
            where 
                SysDatabaseLog.table    == tableNum(custTable)
            ||  SysDatabaseLog.table    == tableNum(DIRPARTYLOCATION)
            ||  SysDatabaseLog.table    == tableNum(LOGISTICSELECTRONICADDRESS)
Будут же какие-то другие условия? Если это дата - то какой интервал брать?
Старый 13.01.2021, 20:45   #13  
Ace of Database is offline
Ace of Database
Участник
Аватар для Ace of Database
 
870 / 637 (23) +++++++
Регистрация: 14.10.2004
Это пример был из АХ3. Там дата и время создания записи хранятся в отдельных полях
А для АХ 2012, чтобы вернуть все изменения за последнюю минуту, можно написать так:
X++:
    while select SysDatabaseLog order by createdDateTime
        where SysDatabaseLog.createdDateTime >= DateTimeUtil::addMinutes(DateTimeUtil::utcNow(), -1)
        && (SysDatabaseLog.table    == tableNum(custTable)
            ||  SysDatabaseLog.table    == tableNum(DIRPARTYLOCATION)
            ||  SysDatabaseLog.table    == tableNum(LOGISTICSELECTRONICADDRESS))
    {
    }
__________________
Мои утилиты для Аксапты версий 3.0-2012: http://aceofdatabase.blogspot.com/
Старый 14.01.2021, 01:53   #14  
trud is offline
trud
Участник
Лучший по профессии 2017
 
1,038 / 1629 (57) ++++++++
Регистрация: 07.06.2003
Записей в блоге: 1
Цитата:
Сообщение от Ace of Database Посмотреть сообщение
А для АХ 2012, чтобы вернуть все изменения за последнюю минуту, можно написать так:
X++:
    while select SysDatabaseLog order by createdDateTime
        where SysDatabaseLog.createdDateTime >= DateTimeUtil::addMinutes(DateTimeUtil::utcNow(), -1)
Ну это будут изменения за последнюю минуту по которым завершилась транзакция в момент запуска данного запроса. Также могут быть изменения за конкретно эту же минуту по которым транзакция еще не завершилась, они появятся позже, как она завершится. Как предлагаете их искать?
Старый 14.01.2021, 08:18   #15  
Pustik is offline
Pustik
Участник
 
807 / 372 (14) ++++++
Регистрация: 04.06.2004
Цитата:
Сообщение от trud Посмотреть сообщение
Ну это будут изменения за последнюю минуту по которым завершилась транзакция в момент запуска данного запроса. Также могут быть изменения за конкретно эту же минуту по которым транзакция еще не завершилась, они появятся позже, как она завершится. Как предлагаете их искать?
можно сохранять время запуска последней репликации в отдельной выделенной для этого табличке как у нас, т.е принцип такой :

1) запоминаем время запуска текущей репликации startDateTime = DateTimeUtil::utcNow()
2) достаем из таблички дату-время запуска последней репликации = lastDateTime
3) пошла репликация:
X++:
while select SysDatabaseLog order by createdDateTime
        where SysDatabaseLog.createdDateTime >= lastDateTime
        && (SysDatabaseLog.table    == tableNum(custTable)
            ||  SysDatabaseLog.table    == tableNum(DIRPARTYLOCATION)
            ||  SysDatabaseLog.table    == tableNum(LOGISTICSELECTRONICADDRESS))
    {
    }
4) сохраняем в табличке дату-время запуска текущей репликации startDateTime

PS: А меняя в этой табличке дату-время запуска последней репликации можно управлять интервалом минута, месяц, год и т.д.
__________________
-Ты в гномиков веришь?
-Нет.
-А они в тебя верят, смотри, не подведи их.

Последний раз редактировалось Pustik; 14.01.2021 в 08:26.
Старый 14.01.2021, 08:34   #16  
Ace of Database is offline
Ace of Database
Участник
Аватар для Ace of Database
 
870 / 637 (23) +++++++
Регистрация: 14.10.2004
Цитата:
Сообщение от trud Посмотреть сообщение
Также могут быть изменения за конкретно эту же минуту по которым транзакция еще не завершилась, они появятся позже, как она завершится. Как предлагаете их искать?
Сохранить максимальный RecId из таблицы SysDatabaseLog на момент срабатывания текущей обработки. Через одну минуту, при повторном срабатывании обработки, искать в таблице SysDatabaseLog все записи, у которых RecId больше, чем тот, который был в прошлый раз.И тогда не надо искать по полю CreatedDateTime за последнюю минуту

X++:
while select SysDatabaseLog order by createdDateTime
        where SysDatabaseLog.RecId > lastRecId
        && (SysDatabaseLog.table    == tableNum(custTable)
            ||  SysDatabaseLog.table    == tableNum(DIRPARTYLOCATION)
            ||  SysDatabaseLog.table    == tableNum(LOGISTICSELECTRONICADDRESS))
    {
    }
__________________
Мои утилиты для Аксапты версий 3.0-2012: http://aceofdatabase.blogspot.com/
Старый 14.01.2021, 11:02   #17  
trud is offline
trud
Участник
Лучший по профессии 2017
 
1,038 / 1629 (57) ++++++++
Регистрация: 07.06.2003
Записей в блоге: 1
RecId тоже непоследовательны. они выделяются пачками на клиента(по сто или около того) и потом расходуются по мере надобности

Последний раз редактировалось trud; 14.01.2021 в 11:39.
Старый 14.01.2021, 11:48   #18  
Ace of Database is offline
Ace of Database
Участник
Аватар для Ace of Database
 
870 / 637 (23) +++++++
Регистрация: 14.10.2004
Имеется в виду не RecId клиента, а RecId в таблице SysDatabaseLog
__________________
Мои утилиты для Аксапты версий 3.0-2012: http://aceofdatabase.blogspot.com/
Старый 14.01.2021, 12:00   #19  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Прежде всего, согласен с Vadik, требование опрашивать 6M записей с частотой 1 раз в минуту - это какой-то перебор.
Но скорее всего, заказчик хотел иметь возможность опрашивать часто и опрашивать повторно некоторые разрезы (по группам, по условиям платежей, по наличию скидочной карточки и т.п.)
поэтому простим такую формулировку.

Критика предыдущих предложений

1.
Change Tracking - хорош.
Но слишком привязывает в MS SQL. В наше непростое время Great Again вендор-lock - это серьезный недостаток

2.
ModifiedDateTime, RecID и прочие неубывающие последовательности - в топку,
поскольку именно этот статус позволяет узнать что изменилось во всем справочнике, но не позволяет запросить измененные только в некоторых записях,
и вынуждает делаеть полные запросы по всем 6M записей
(а время еще и требует филигранной синхронизации времени на разных аосах/клиентах)

3.
перехватывать событие/триггера изменений и записывать логи - чревато DDOS системы
на расчетных полях типа себестоимости в складских проводках, алгоритм долбит обновлениями до посинения.
(особенно категорически не надо использовать SysDatabaseLog)

Что есть в стандартной Аксапте?
4.
в аксапте уже есть поле recVersion.
Ядро Аксапты использует это поле в рамках механизма оптимистической конкуренции в формах для того, чтобы узнать изменилась ли запись в других Аксаптах.

Это то, что нам нужно!

подход с recVersion придумал не майкрософт, но почитать об этом подходе можно здесь
https://docs.microsoft.com/ru-ru/sql...n-transact-sql

Кратко как поле RecVersion работает в аксапте:
1. RecVersion = 0 при создани записи
2. RecVersion = random(int) при любом обновлении записи (повторю: это делает ядро Аксапты, программировать это не надо)

Инвариант:
С огромной вероятностью recVersion после обновления будет отличаться от recVersion до обновления

(ах это "почти"... длинные рассуждения о почти уникальных GUID и о инженерном подходе "на практике работоспособно")

Что предлагается
5.

5.1. у вас есть справочник, состоящий из нескольких связанных таблиц (tab1, tab2 ... tabN)
5.2. у каждого справочника аксапта обслуживает служебное поле recVersion

5.3. Создайте shadow таблицу для вашего справочника tabShadow, в которой храните:
5.3.1. refRecVersion1, ... refRecVersionN - recVersion таблиц, которые вы выгрузили во внешнюю систему
5.3.2. [опционально] сериализованные значений полей, которые вы выгружаете. Важно, чтобы:
5.3.2.1. сериализованные значения можно было удобно сравнивать на равенство (изменились ли?)
5.3.2.2. сериализовать можно в аксаптовский container - тогда не надо будет программировать парсинг. Но конейнеры в MS SQL хранятся в (Memo)-полях. Со всеми вытекающими для производительности
5.3.3. FK к вашему справочнику, которые позволят однозначно связать shadow-запись и запись в справочнике (связь 0,1..0,1)

5.4. при каждой выгрузке обновляйте shadow-таблицу

5.5. shadow таблица позволит вам четко определить запросами 4 состояния:
5.5.1. есть запись в tab, нет записи в shadow - запись в справочнике создана, ни разу не выгружалась
5.5.2. есть запись в tab, есть запись в shadow, recVersion не совпадают - запись в справочнике изменилась, надо выгрузить
5.5.3. есть запись в tab, есть запись в shadow, recVersion совпадают - запись в справочнике не изменалась
5.5.4. ест записи в tab, есть запись в shadow - запись удалена, надо дать команду на удаление внешней системе

5.6. c shadow таблицей вы можете накладывать любые фильтры на справочник и получать измененные записи только среди отфильтрованных
5.7. shadow таблица не будет нагружать вашу систему паразитной нагрузкой в insert/update/delete и логах. будет работать только по запросу

там еще куча соображений.
но пока хватит.
__________________
полезное на axForum, github, vk, coub.

Последний раз редактировалось mazzy; 14.01.2021 в 12:07.
За это сообщение автора поблагодарили: sukhanchik (10), vmoskalenko (4).
Старый 14.01.2021, 13:00   #20  
DSPIC is offline
DSPIC
Боец
 
1,077 / 1234 (44) ++++++++
Регистрация: 11.04.2008
Цитата:
Сообщение от mazzy Посмотреть сообщение
Прежде всего, согласен с Vadik, требование опрашивать 6M записей с частотой 1 раз в минуту - это какой-то перебор.
Но скорее всего, заказчик хотел иметь возможность опрашивать часто и опрашивать повторно некоторые разрезы (по группам, по условиям платежей, по наличию скидочной карточки и т.п.)
поэтому простим такую формулировку.

Критика предыдущих предложений

1.
Change Tracking - хорош.
Но слишком привязывает в MS SQL. В наше непростое время Great Again вендор-lock - это серьезный недостаток

2.
ModifiedDateTime, RecID и прочие неубывающие последовательности - в топку,
поскольку именно этот статус позволяет узнать что изменилось во всем справочнике, но не позволяет запросить измененные только в некоторых записях,
и вынуждает делаеть полные запросы по всем 6M записей
(а время еще и требует филигранной синхронизации времени на разных аосах/клиентах)

3.
перехватывать событие/триггера изменений и записывать логи - чревато DDOS системы
на расчетных полях типа себестоимости в складских проводках, алгоритм долбит обновлениями до посинения.
(особенно категорически не надо использовать SysDatabaseLog)

Что есть в стандартной Аксапте?
4.
в аксапте уже есть поле recVersion.
Ядро Аксапты использует это поле в рамках механизма оптимистической конкуренции в формах для того, чтобы узнать изменилась ли запись в других Аксаптах.

Это то, что нам нужно!

подход с recVersion придумал не майкрософт, но почитать об этом подходе можно здесь
https://docs.microsoft.com/ru-ru/sql...n-transact-sql

Кратко как поле RecVersion работает в аксапте:
1. RecVersion = 0 при создани записи
2. RecVersion = random(int) при любом обновлении записи (повторю: это делает ядро Аксапты, программировать это не надо)

Инвариант:
С огромной вероятностью recVersion после обновления будет отличаться от recVersion до обновления

(ах это "почти"... длинные рассуждения о почти уникальных GUID и о инженерном подходе "на практике работоспособно")

Что предлагается
5.

5.1. у вас есть справочник, состоящий из нескольких связанных таблиц (tab1, tab2 ... tabN)
5.2. у каждого справочника аксапта обслуживает служебное поле recVersion

5.3. Создайте shadow таблицу для вашего справочника tabShadow, в которой храните:
5.3.1. refRecVersion1, ... refRecVersionN - recVersion таблиц, которые вы выгрузили во внешнюю систему
5.3.2. [опционально] сериализованные значений полей, которые вы выгружаете. Важно, чтобы:
5.3.2.1. сериализованные значения можно было удобно сравнивать на равенство (изменились ли?)
5.3.2.2. сериализовать можно в аксаптовский container - тогда не надо будет программировать парсинг. Но конейнеры в MS SQL хранятся в (Memo)-полях. Со всеми вытекающими для производительности
5.3.3. FK к вашему справочнику, которые позволят однозначно связать shadow-запись и запись в справочнике (связь 0,1..0,1)

5.4. при каждой выгрузке обновляйте shadow-таблицу

5.5. shadow таблица позволит вам четко определить запросами 4 состояния:
5.5.1. есть запись в tab, нет записи в shadow - запись в справочнике создана, ни разу не выгружалась
5.5.2. есть запись в tab, есть запись в shadow, recVersion не совпадают - запись в справочнике изменилась, надо выгрузить
5.5.3. есть запись в tab, есть запись в shadow, recVersion совпадают - запись в справочнике не изменалась
5.5.4. ест записи в tab, есть запись в shadow - запись удалена, надо дать команду на удаление внешней системе

5.6. c shadow таблицей вы можете накладывать любые фильтры на справочник и получать измененные записи только среди отфильтрованных
5.7. shadow таблица не будет нагружать вашу систему паразитной нагрузкой в insert/update/delete и логах. будет работать только по запросу

там еще куча соображений.
но пока хватит.
Ну... почти. Только корректно будет сравнивать не RecVersion, который обновляется при изменении совершенно любого поля записи. Нас же интересует изменение только того, что подлежит выгрузке. Поэтому, правильнее было бы опираться на свой собственный аналог RecVersion, который привязан к выгружаемой информации, а не всем 100500 полям документа.
Теги
aif, ax2012, change tracking, интеграция, как правильно

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
AX2012 Общие справочники поставщиков и клиентов PTG DAX: Функционал 2 11.06.2015 15:39
Импорт адресов для существующих клиентов и поставщиков IKA DAX: Программирование 0 10.12.2013 21:04
ax 3.0 Экспорт справочников во внешнюю систему, по какому ключу связаться? Shakr DAX: Программирование 2 11.11.2008 11:34
Сергей Герасимов: О технической поддержке клиентов по продуктам Microsoft Dynamics Blog bot DAX Blogs 4 13.02.2007 14:58
Коды клиентов в CRM - проблема Zabr DAX: Функционал 5 01.12.2003 12:41

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 15:16.
Powered by vBulletin® v3.8.5. Перевод: zCarot
Контактная информация, Реклама.