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  
online
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,003 / 1632 (61) ++++++++
Регистрация: 12.10.2004
Копайте в сторону 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  
online
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,003 / 1632 (61) ++++++++
Регистрация: 12.10.2004
см.
\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
 
466 / 478 (16) +++++++
Регистрация: 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,373 / 861 (31) +++++++
Регистрация: 13.01.2004
Ну, Вам же уже сказали, что проблема в 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
Administrator
Аватар для mazzy
Most Valuable Professional
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
28,836 / 3726 (182) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Цитата:
Сообщение от Vasiliusis Посмотреть сообщение
Почему, господа?
Как уже сказали выше - поводом является отсутствие orig().

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

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

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

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

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

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

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

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

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

Люди, писавшие в упомянутом методе упомянутого объекта на слое SYS наполнение контейнера путем цикличной модификации исходного контейнера оператором "+=", в курсе этих рекомендаций ?
__________________
Axapta will die, MorphX stay forever
Старый 01.03.2018, 07:39   #13  
mazzy is offline
mazzy
Administrator
Аватар для mazzy
Most Valuable Professional
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
28,836 / 3726 (182) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Цитата:
Сообщение от TasmanianDevil Посмотреть сообщение
Люди... в курсе этих рекомендаций ?
нет.
__________________
GitHub, Facebook, mazzy.priot, mazzy.music, 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, время: 22:12.
Powered by vBulletin® v3.8.5. Перевод: zCarot
Контактная информация, Реклама.