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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 01.02.2010, 13:59   #1  
andriy_s is offline
andriy_s
Участник
 
54 / 13 (1) ++
Регистрация: 28.08.2009
? Как отследить все факты создания таблиц при постинге?
Мне нужно знать в какие таблицы создаются записи при постинге (например FreeTextInvoice). Не очень хочется отслеживать каждую строчку кода.

Пробовал с Профайлером:
- открыл профайлер
- запустил Start
- FreeTextInvoices ==> Posting (успешно завершен)
- профайлер Stop
- смотрю результаты (и хочу увидить вызовы insert методов) - но нет ничего похожего

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

Последний раз редактировалось andriy_s; 01.02.2010 в 14:02.
Старый 01.02.2010, 14:20   #2  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,438 / 1775 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
А вы с какой целью интересуетесь? Случайно, не ради ли Удаление разнесенного складского журнала.?
Старый 01.02.2010, 14:22   #3  
nix0root is offline
nix0root
Участник
 
67 / 16 (1) ++
Регистрация: 17.03.2009
Адрес: МО
Если Вы работаете на Oracle, то можно воспользоваться тригером на таблицу вида:

create or replace trigger имя_тригера
before delete on имя_таблицы
for each row
declare

begin
пишем в лог или еще куда-нибудь
end имя_тригера

Здесь я перекрыл before delete можно также criate и т.д.
За это сообщение автора поблагодарили: Gustav (2).
Старый 01.02.2010, 15:46   #4  
Zabr is offline
Zabr
Участник
Axapta Retail User
 
1,202 / 345 (14) ++++++
Регистрация: 26.06.2002
Адрес: Москва
1. Берете тестовую базу, чтобы кроме вас там никто не работал
2. входите в Аксапту
3. выполняете в SQL Server Management Studio запрос "DBCC showcontig with tabletesults" - получаете список всех таблиц с числом записей в них
4. делаете разноску
5. повторяете пункт 3
6. сравниваете результаты запросов до и после - получаете список изменившихся при разноске таблиц.
Немного долго, зато железно.
За это сообщение автора поблагодарили: mazzy (2), alex55 (1), driller (1), Proba (1), andriy_s (1).
Старый 01.02.2010, 16:02   #5  
alex55 is offline
alex55
MCTS
MCBMSS
 
224 / 145 (5) +++++
Регистрация: 13.02.2007
Адрес: Москва
Цитата:
Сообщение от Zabr Посмотреть сообщение
3. выполняете в SQL Server Management Studio запрос "DBCC showcontig with tabletesults" - получаете список всех таблиц с числом записей в них
Видимо "DBCC showcontig with tableResults".
За это сообщение автора поблагодарили: Zabr (1).
Старый 01.02.2010, 16:27   #6  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Неоднократно занимался подобной штукой в одиночестве на тестовой базе (Zabr абсолютно прав! ), причем, последний раз не так давно - 16.12.2009, как следует из условия в while select (см. в джобе). После постинга пробегался по всем таблицам Аксапты, имеющим записи и запоминал из них несколько (например, 200) самых последних по RecId. Дальше выгружал в Excel, сортировал по RecId и смотрел записи в районе тех RecId, в которых я был уверен, что они относятся к исследуемой операции (обычно известны RecId ранесенных записей из LedgerTrans). Пару раз обнаруживал таблицы, о которых откровенно не знал, что они задействованы при данной операции!

Вот мой джоб:
X++:
#CCADO
#define.rowLimit( 200 )

static void Job235_whereRecId(Args _args)
{
    Dictionary  dictionary = new Dictionary();
    TableId     tableId;
    DictTable   dictTable;
    Common      common;
    COM         rst, flds, fld;
    int         row, i, timeStart;
    ;

    timeStart = timenow();

    rst = AdoRst::openRecordsetInMemory([
            ['TableId'   , #adInteger  ],
            ['TableName' , #adVarChar  ],
            ['RecId'     , #adInteger  ]]);

    flds = rst.Fields();

    // цикл по таблицам
    for (i=1; i<= dictionary.tableCnt(); i++)
    {
        tableId   = dictionary.tableCnt2Id(i);
        dictTable = new DictTable(tableId);

        print strFmt('%1 -- %2', tableId, dictTable.name());

        // если в очередной таблице нет записей
        // то переходим к следующей
        if (! new SysDictTable(tableId).recordCount())
            continue;

        common = dictTable.makeRecord();

        row = 0;
        // цикл по последним записям таблицы
        while select common order by RecId desc
            where common.createdDate == 16\12\2009
               && common.createdBy   == 'MNY'
        {
            row++;
            if (row > #rowLimit) break;
            rst.AddNew();
                fld = flds.Item(0); fld.Value(tableId);
                fld = flds.Item(1); fld.Value(dictTable.name());
                fld = flds.Item(2); fld.Value(common.RecId);
            rst.Update();
        }
    }

    AdoRst::sendRecordsetToExcel(rst);

    info(strfmt('Время выполнения: %1 сек', timenow()-timeStart));
}
А это к нему используемая статика (класс у меня, как видно выше, называется AdoRst):

* Метод openRecordsetInMemory можно взять в моем блоге: http://axforum.info/forums/blog.php?b=60

* Метод sendRecordsetToExcel имеет следующий вид (и к нему еще внутри - deleteFilteredRecords):
X++:
// Created on 06 Ноя 2008 at 16:26:03 by KKU

// выводит в Excel переданный ADODB.Recordset (обычно это disconnected recordset в памяти)

// если записи выводятся на несколько листов, то рекордсет в процессе вывода "ломается"
// за счёт удаления уже выведенных в Excel записей

// возвращает false, если удалений записей не было (т.е. всё вывелось на один лист и рекордсет остался нетронутым)
// или true - если были удаления (rstWasChanged)
static boolean sendRecordsetToExcel( COM    _rst,
                                     int    _maxRows = 65000,
                                     int    _maxColumns = 0)
{
    COM         xlApp   = new COM('Excel.Application');
    COM         wbks    = xlApp.Workbooks();
    COM         wbk     = wbks.Add();
    COM         wkss    = wbk.Worksheets();
    COM         wks;
    COM         rng;
    COM         cell;

    COM         column;
    COM         rngCols;
    COMVariant  columnWidth;

    COM         flds    = _rst.Fields();

    int         i;
    // разобраться здесь _maxColumns- то считается с единицы
    int         iMax    = (_maxColumns) ? (min(_maxColumns,flds.Count())) : flds.Count();
    int         sheet   = 1;

    #CCADO
    ;

    // раз уж CopyFromRecordset, как выясняется, выводит без фильтра,
    // то на всякий случай еще и принудительно их удалим (а то вдруг починятся когда-нибудь у Microsoft)
    _rst.Filter('');
    _rst.Sort('');

    while (true)
    {
        // добавляем лист, если нужно
        if (sheet > wkss.Count())
            wkss.Add(COMArgument::NoValue, wkss.Item(wkss.Count()));

        wks = wkss.Item(sheet);
        wks.Activate(); // для отображения ДАТЫ как ДАТЫ на 2-м и 3-м существующих листах

        // выводим строку имен полей (1-я строка листа Excel)
        rng = wks.Range('A1');
        for (i = 1; i <= iMax; i++)
        {
            cell = rng.Offset(0, i-1);
            cell.Value2( COM::createFromObject( flds.Item(i-1) ).Name() );
        }
        rng = rng.CurrentRegion();
        COM::createFromObject( rng.Font() ).Bold(true); // делаем выведенные заголовки жирным шрифтом

        // выводим данные, начиная со 2-й строки листа Excel
        rng = wks.Range('A2');
        if ( !(_rst.BOF() && _rst.EOF()) ) // если есть записи
        {
            _rst.MoveFirst();
            if (_maxColumns)
                rng.CopyFromRecordset( _rst, _maxRows, _maxColumns );
            else
                rng.CopyFromRecordset( _rst, _maxRows);
        }

        // подгонка ширины колонок (с ограничением не более 35)
        rng = rng.CurrentRegion();
        rngCols = rng.Columns();
        COM::createFromObject( rngCols.EntireColumn() ).AutoFit();

        for (i = 1; i <= iMax; i++)
        {
            column = COM::createFromVariant( rngCols.Item(i) );
            columnWidth = column.ColumnWidth();

            if (columnWidth.double() > 35) column.ColumnWidth(35);
        }

        // здесь накручено, чтобы не пользоваться RecordCount
        // --------------------------------------------------
        // попытка достичь конца файла, продвинувшись от начала на количество выведенных записей
        // у нас это кол-во всегда одно - _maxRows, так как мы удаляем записи на каждом шаге
        // точнее ПОСЛЕ каждого (поэтому, если лист один, то рекордсет сохраняется в первозданном виде)
        if (!_rst.EOF())
            _rst.Move(_maxRows, #adBookmarkFirst);
        // если вдруг конец файла уже был достигнут ранее, то его обработает следующий оператор

        if (!_rst.EOF())
        {
            AdoRst::deleteFilteredRecords(_rst, _maxRows);
            sheet++;
        }
        else
        {
            break; // иначе завершаем цикл вывода на листы
        }
    }

    xlApp.Visible(true);

    if (sheet > 1)
        return true; // rstWasChanged - если листов более одного, то исходный рекордсет не сохранен
    else
        return false;
}

/*
    Удаляет "видимые" записи из текущего рекордсета.

    Если рекордсет был отфильтрован, то будут удалены только записи, соответствующие фильтру.

    Можно задать удаление не всех отфильтрованных записей,
    а только несколько первых (_numRecords > 0).
    В этом случае имеет смысл перед удалением применить сортировку,
    чтобы гарантировать определенный порядок удаляемых записей.
*/
static int deleteFilteredRecords(COM _rst, int _numRecords = 0)
{
    int affectedRecords = 0;
    int i;

    void deleteOneRecord()
    {
        affectedRecords++;
        _rst.Delete();
        _rst.MoveNext();
    }
    ;

    if (_rst.BOF() && _rst.EOF()) return 0;  // если набор пуст - выходим

    _rst.MoveFirst();
    if (_numRecords)
    {
        for (i=1;i<=_numRecords;i++)
        {
            if (!_rst.EOF())
                deleteOneRecord();
            else
                break;  // если _numRecords больше реального числа записей
        }
    }
    else
    {
        while (!_rst.EOF())
            deleteOneRecord();
    }
    _rst.MovePrevious(); /* так надо, так как после последнего удаления
                            указатель находится за последней записью (EOF=true),
                            но при этом BOF=false - так вот для этой коррекции и надо,
                            чтобы стало и BOF=true, и EOF=true

                            если же в наборе остались записи,
                            то это действие поставит указатель на последнюю запись
                         */
    return affectedRecords; // кол-во удаленных записей
}

Последний раз редактировалось Gustav; 01.02.2010 в 16:30.
За это сообщение автора поблагодарили: mazzy (2), alex55 (1), Proba (1), andriy_s (1).
Старый 01.02.2010, 16:44   #7  
raz is offline
raz
NavAx
Аватар для raz
NavAx Club
Лучший по профессии 2014
Лучший по профессии 2009
 
1,494 / 1065 (38) ++++++++
Регистрация: 22.07.2003
Адрес: МО
До операции включаем.

Сервис\Параметры\SQL\Мониторинг запросов SQL\Множественные запросы SQL\Вывод в файл

После выключаем и анализируем файл. Файл лежит в подкаталоге Log рядом с приложением.
За это сообщение автора поблагодарили: Proba (1).
Старый 01.02.2010, 16:56   #8  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от andriy_s Посмотреть сообщение
Пробовал с Профайлером:
...
- смотрю результаты (и хочу увидить вызовы insert методов) - но нет ничего похожего
Если у вас ax4.0 и выше, то в конфигурационной утилите нужно включить галочки "SQL statements", "Row fetch", "Bind variables" на закладке Tracing.

Сильные тормоза при разноске Заказа на продажу
Как убрать знаки вопроса в мониторе запросов SQL?
Аудит блокировок


Цитата:
Сообщение от raz Посмотреть сообщение
Сервис\Параметры\SQL\Мониторинг запросов SQL\Множественные запросы SQL\Вывод в файл
И для этого тоже нужно включить галочки в конфигурационой утилите, если у вас ax4.0 и выше.
__________________
полезное на axForum, github, vk, coub.
За это сообщение автора поблагодарили: andriy_s (1).
Старый 01.02.2010, 17:12   #9  
EVGL is offline
EVGL
Banned
Соотечественники
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
4,445 / 3001 (0) ++++++++++
Регистрация: 09.07.2002
Адрес: Parndorf, AT
Цитата:
Сообщение от raz Посмотреть сообщение
До операции включаем.

Сервис\Параметры\SQL\Мониторинг запросов SQL\Множественные запросы SQL\Вывод в файл

После выключаем и анализируем файл. Файл лежит в подкаталоге Log рядом с приложением.
Да, я тоже так делаю. В конце-концов, записи не только создаются, но и обновляются иногда.
За это сообщение автора поблагодарили: Kabardian (3).
Старый 01.02.2010, 17:54   #10  
raz is offline
raz
NavAx
Аватар для raz
NavAx Club
Лучший по профессии 2014
Лучший по профессии 2009
 
1,494 / 1065 (38) ++++++++
Регистрация: 22.07.2003
Адрес: МО
Цитата:
Сообщение от EVGL Посмотреть сообщение
Да, я тоже так делаю. В конце-концов, записи не только создаются, но и обновляются иногда.
И видно откуда в системе вызываются модификации БД.
Теги
insert, posting, profiler, профайлер

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
HRM,склонение ФИО и все все все OmenSore DAX: Функционал 22 09.02.2009 17:08
Query из 7 таблиц Cornflower DAX: Программирование 29 15.03.2007 11:27
Синхронизация таблиц м/у 2-мя компаниями sparur DAX: Программирование 15 12.12.2006 18:47
Все названия таблиц в инфо kas DAX: Программирование 10 17.07.2006 18:13
Дополнительные возможности временных таблиц: метод setTmpData vitk DAX: База знаний и проекты 1 19.06.2002 17:53

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

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

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 07:18.