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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 28.02.2018, 08:37   #1  
Vasiliusis is offline
Vasiliusis
Участник
 
225 / 13 (1) ++
Регистрация: 30.01.2013
Update курсора таблицы, полученного из контейнера, не действует
Добрый день. Написан следующий абстрактный код:

X++:
    //объявления всех используемых переменных
    //...

    ttsbegin;

    select forupdate * from telegram
        where telegram.RecId == 5637147106;
    
    telegram.Sign += '-';
    telegram.update();
    ttscommit;
в результате все работает как надо, данные обновлены.

НО(!) есть и такой код:
X++:
    //объявления всех используемых переменных
    //...

    ttsbegin;

    select forupdate * from telegram
        where telegram.RecId == 5637147106;

    //Помещаем курсор таблицы в контейнер
    telegramCon = conins(telegramCon, 1, telegram);

    //... забываем на время...

    //...

    //вспоминаем, достаем обратно
    telegram = conpeek(telegramCon, 1);
    
    telegram.Sign += '-';
    telegram.update();
    ttscommit;
в результате ИЗМЕНЕНИЯ ИГНОРИРУЮТСЯ, в БД то же значение Sign

Почему, господа?
Старый 28.02.2018, 09:13   #2  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,867 / 3123 (112) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
Копайте в сторону orig() и места выполнения вашего кода (клиент/сервер)
Ядро при обновлении записи сраанивает текущие значения и orig() значения и различия сбрасывает в базу.
Для некоторых сценариев работы orig() был всегда равен самому буферу. Поэтому update ничего не обновлял.
Вероятно это ваш случай.

Можете еще посмотреть как устроено обновление InventTrans в пересчете себестоимости/закрытии склада. Там сделано похоже на ваш пример, но еще дергается skipTtsCheck() и.т.п.
За это сообщение автора поблагодарили: gl00mie (2).
Старый 28.02.2018, 09:31   #3  
Vasiliusis is offline
Vasiliusis
Участник
 
225 / 13 (1) ++
Регистрация: 30.01.2013
Цитата:
Сообщение от Logger Посмотреть сообщение
Копайте в сторону orig() и места выполнения вашего кода (клиент/сервер)
Место выполнения - сервер, абстрактный код тестируется в джобе, а это точно, я полагаю, не клиент

Цитата:
Сообщение от Logger Посмотреть сообщение
Ядро при обновлении записи сравнивает текущие значения и orig() значения и различия сбрасывает в базу.
Для некоторых сценариев работы orig() был всегда равен самому буферу. Поэтому update ничего не обновлял.
Вероятно это ваш случай.
различия есть, отдельно получено значение Sign и orig().Sign. Они разнятся...

Дело в использовании контейнера, однозначно. При десериализации, видимо что-то происходит... Кстати, когда курсор обратно получается из контейнера - в дебаггере видно, что "forupdate" утрачивается, приходится делать принудительно selectForUpdate(true)... но и без forupdate, как ни странно, не бросается исключение "запись не выбиралась для обновления"... в общем, чудеса в решете
Старый 28.02.2018, 09:40   #4  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,867 / 3123 (112) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
см.
\Classes\InventCostItemDim\updateInventTrans
и все места где он используется.

Там все работает.
Старый 28.02.2018, 09:50   #5  
Vasiliusis is offline
Vasiliusis
Участник
 
225 / 13 (1) ++
Регистрация: 30.01.2013
Цитата:
Сообщение от Logger Посмотреть сообщение
см.
\Classes\InventCostItemDim\updateInventTrans
и все места где он используется.

Там все работает.
Простите мне мою непроницательность, но там же не используется контейнер?..

X++:
protected void updateInventTrans(InventTrans _inventTrans)
{
    ;

    if (_inventTrans.RecId)
    {
        _inventTrans.skipTTSCheck(true);
        this.updateCostAmountStd(_inventTrans);
        _inventTrans.update();
    }

    if (mapInventTrans)
        mapInventTrans.insert(_inventTrans.RecId, _inventTrans);
}
без контейнера и у меня работает...
Старый 28.02.2018, 10:14   #6  
skuull is offline
skuull
Участник
Most Valuable Professional
Лучший по профессии 2014
 
699 / 752 (27) +++++++
Регистрация: 08.03.2013
Адрес: ХЗ
А зачем это принципиальное использование контейнера? Я всегда пользовался map как в updateInventTrans и небыло проблем. Контейнер же для value типов, а запись она такая особенная
Старый 28.02.2018, 10:21   #7  
Vasiliusis is offline
Vasiliusis
Участник
 
225 / 13 (1) ++
Регистрация: 30.01.2013
Цитата:
Сообщение от skuull Посмотреть сообщение
Я всегда пользовался map как в updateInventTrans и не было проблем
стоит попробовать, спасибо

В общем, не помог map

Последний раз редактировалось Vasiliusis; 28.02.2018 в 10:27.
Старый 28.02.2018, 10:47   #8  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,651 / 1158 (42) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
Ну, Вам же уже сказали, что проблема в orig(). Простейший тест покажет проблему

X++:
custTable   custTable;
custTable   custTableOrig;
Container   conValue;

select firstonly custTable;
conValue = conIns(conValue, 1, custTable);
custTable = null;

// А теперь смотрим, что у нас в контейнере
custTable = conPeek(conValue, 1);
custTableOrig = custTable.orig();

info(strFmt('custTable.RecId = %1', custTable.RecId));
info(strFmt('custTableOrig.RecId = %1', custTableOrig.RecId));
Orig() - пустой. Там вообще нет данных! Тут, скорее, надо удивляться, что на методе update() ошибка не возникает. Т.е. подтверждается предположение, что контейнер - это хранение скалярных данных, а упакованная в него Records также рассматривается как набор скалярных данных. Некий вложенный контейнер

Соответственно, если Вы все-равно хотите использовать контейнер, то после извлечения из него записи надо через buf2buf() скопировать набор "скаляров" в поля реальной записи. Ну, как-то так

X++:
custTableCon = conPeek(conValue, 1);
select firstonly forupdate custTable where custTable.RecId == custTableCon.RecId;
global::buf2buf(custTableCon, custTable);
__________________
- Может, я как-то неправильно живу?!
- Отчего же? Правильно. Только зря...
Старый 28.02.2018, 11:09   #9  
Vasiliusis is offline
Vasiliusis
Участник
 
225 / 13 (1) ++
Регистрация: 30.01.2013
Цитата:
Сообщение от Владимир Максимов Посмотреть сообщение
Соответственно, если Вы все-равно хотите использовать контейнер, то после извлечения из него записи надо через buf2buf() скопировать набор "скаляров" в поля реальной записи.
Была такая идея, но я посчитал ее чересчур неспортивной... видимо, другого выхода нет, спасибо
Старый 28.02.2018, 11:21   #10  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от Vasiliusis Посмотреть сообщение
Почему, господа?
Как уже сказали выше - поводом является отсутствие orig().

причиной является то, что в контейнер аксапта (версии 2009 и младше, 2012 без CIL) запоминает не ссылку на объект, а сериализованную строку.

причем в контейнер сериализуются не все аспекты record, а только поля записи.
Подозреваю, что не сериализуются приватные поля record-объекта. В том числе буфер, который используется для orig().

в 2012 CIL и выше в качестве контейнера используется системный Array<Object>.
Поэтому такой проблемы быть не должно пока не будет происходить явная сериализация через sysLastValue или подобное.

кстати, в 2012 CIL были замечены странные эффекты "переходного периода" - иногда работает так, а иногда иначе.
в акс7 контейнер - всегда массив объектов, хранящий ссылки.

кстати 2: контейнер в акс2012 и младше - не мутабельный объект. контейнер всегда пересоздается при любой правке контейнера.
а точно ЛЮБОЕ изменение приводит к пересозданию контейнера? даже conpoke?

Поэтому, например, KeySum - антипаттерн в младших версиях и вполне терпимая штука, начиная с 2012 CIL.
Постарайтесь использовать меньше операций по модификации контейнера
__________________
полезное на axForum, github, vk, coub.

Последний раз редактировалось mazzy; 28.02.2018 в 11:24.
За это сообщение автора поблагодарили: user_ax (2), Logger (3).
Старый 28.02.2018, 14:10   #11  
user_ax is offline
user_ax
Участник
Аватар для user_ax
 
599 / 39 (3) +++
Регистрация: 07.10.2012
Адрес: ZP
Извините, а зачем вообще в контейнер пихать рекорд? Почему бы не положить recid и сделать в дальнейшем дополнительный find. Так точно будет работать. Или интересно поискать особенности работы ядра аксапты?) Map, list - будут получше, как уже выше писали про проводки складские.

Сергей, спасибо за информацию про контейнеры, увлекательно, плюсую
Старый 01.03.2018, 06:46   #12  
TasmanianDevil is offline
TasmanianDevil
Мрачный тип
Аватар для TasmanianDevil
Злыдни
 
885 / 389 (14) ++++++
Регистрация: 24.01.2005
Адрес: Томск
Цитата:
Сообщение от mazzy Посмотреть сообщение
Постарайтесь использовать меньше операций по модификации контейнера
Регулярно вижу такую рекомендацию на предмет "кабы чего не вышло".

Была в AOT ( вплоть до 2012-й, за еретическую и богопротивную 7-ку не знаю) такая map'а, LogMap кличется, и есть у этой map'ы метод, setData() называется.
Занимаются там компоновкой контейнера состояния записи для разных системных журналов (в 2009-й - для журнала БД, журнала оповещений и какого-то еще "шлака" по эстонской функциональности) - т.е. дёргается оно на исполнение, мягко говоря, не так уж и редко.

Люди, писавшие в упомянутом методе упомянутого объекта на слое SYS наполнение контейнера путем цикличной модификации исходного контейнера оператором "+=", в курсе этих рекомендаций ?
__________________
Мы летаем, кружимся, нагоняем ужасы ...
Старый 01.03.2018, 07:39   #13  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от TasmanianDevil Посмотреть сообщение
Люди... в курсе этих рекомендаций ?
нет.
__________________
полезное на axForum, github, vk, coub.
Теги
container, update, курсор, не работает

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Kashperuk Ivan: Tutorial: Update product receipts for loads and how to handle items missing from ASN Blog bot DAX Blogs 0 22.09.2014 18:11
emeadaxsupport: Calling the Update Operation on Services in AX 2012 Blog bot DAX Blogs 0 22.05.2012 02:12
fed: Net requirements update in MRP Module and Working Set of MRP Blog bot DAX Blogs 14 08.05.2012 13:09
В AX2009 не вызываются методы insert/update/delete временной таблицы S.Kuskov DAX: Программирование 14 24.06.2011 19:24
Потеря активного буфера записи при вызове super() в update() таблицы TasmanianDevil DAX: Администрирование 13 01.10.2008 11:36
Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

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

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

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