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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 26.02.2016, 12:11   #1  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,701 / 1195 (43) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
Создание новых записей и номерные серии
Проблема жива и в Ax2012, хотя тянется еще с ранних версий

Форма, источником данных которой является таблица, одно из полей которой формируется из номерной серии. Записи отображены списком в Grid и создание новой записи происходит там же в Grid без вызова дополнительной формы. Выполняем следующие действия

1. Создаем новую запись, заполняем все поля, обязательные к заполнению
2. Не сохраняя запись, пытаемся создать новую запись

Получаем исключение с сообщением об ошибке

Цитата:
Не удается назначить новый номер журнала, так как %1 не был сохранен или удален.

Причина ошибки очевидная. При создании новой записи сначала выполняется метод DataSource.create(), и только внутри этого метода (внутри super()) выполняются все остальные методы по сохранению текущей записи. Но! Стандартный код метода DataSource.create() на форме, если используется номерная серия имеет вид

X++:
// Form\DataSource\MyTable\create
void create(boolean append = false)
{
    ;

    element.numberSeqFormHandler().formMethodDataSourceCreatePre();

    super(append);

    element.numberSeqFormHandler().formMethodDataSourceCreate();
}
И вот в методе formMethodDataSourceCreatePre() и стоит проверка

X++:
void formMethodDataSourceCreatePre()
{
    ;
    validateWriteCalled = false;
    validateWriteFailed = false;

    if (lastNumber)
    {
        throw(error(strfmt("@SYS85169", lastNumber)));
    }
}
Но поскольку DataSource.create() оказался вызван до DataSource.write(), то номерная серия не была сохранена и значение переменной lastNumber не очищено.

В качестве решения проблемы напрашивается перемещение вызова formMethodDataSourceCreatePre() после вызова super()

X++:
void create(boolean append = false)
{
    ;

// Переносим после super()
//    element.numberSeqFormHandler().formMethodDataSourceCreatePre();

    super(append);

    element.numberSeqFormHandler().formMethodDataSourceCreatePre();

    element.numberSeqFormHandler().formMethodDataSourceCreate();
}

Насколько данное решение корректно? Есть ли другие варианты решения проблемы, кроме "забить"?
__________________
- Может, я как-то неправильно живу?!
- Отчего же? Правильно. Только зря...
За это сообщение автора поблагодарили: Logger (3).
Старый 26.02.2016, 12:38   #2  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,440 / 1775 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
Цитата:
Сообщение от Владимир Максимов Посмотреть сообщение
Есть ли другие варианты решения проблемы, кроме "забить"?
Сохранять предыдущую запись перед созданием новой
Запись не сохраняется при переходе на другую в гриде
Старый 26.02.2016, 13:38   #3  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,701 / 1195 (43) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
Цитата:
Сообщение от S.Kuskov Посмотреть сообщение
Сохранять предыдущую запись перед созданием новой
Запись не сохраняется при переходе на другую в гриде
Это не то. Запись в описанном сценарии сохраняется. Просто нарушена последовательность срабатывания методов сохранения. Точнее, нарушена не сама последовательность срабатывания, а последовательность срабатывания в перекрытых методах

Попробую по другому.

Если явным образом нажать "Сохранить", то выполнится метод DataSource.write(), где произойдет сохранение номерной серии и обнуление переменной lastNumber в классе-обработчике номерных серий

Если же нажать кнопку "Создать", то будет вызван метод DataSource.create(), а уже из него (внутри super()) будет вызван DataSource.write(). Но! Анализ значения переменной lastNumber в классе-обработчике номерных серий выполняется ДО вызова super(). Т.е. ДО фактического сохранения записи. Из-за чего и получаем проблему

Вы предлагаете вручную запустить сохранение записи? Повторить все то, что и так будет выполнено внутри super() но явным образом в коде?

-----

Чтобы совсем было понятно

DataSource.forceWrite() - это установка некоего флага, говорящего Axapta о том, что данная запись была изменена. Но анализ этого флага будет выполнен, очевидно, внутри super(). А проблема возникает ДО вызова super(). Т.е. до анализа данного признака дело еще не дошло
__________________
- Может, я как-то неправильно живу?!
- Отчего же? Правильно. Только зря...

Последний раз редактировалось Владимир Максимов; 26.02.2016 в 13:54.
Старый 26.02.2016, 13:55   #4  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,440 / 1775 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
Цитата:
Сообщение от Владимир Максимов Посмотреть сообщение
Если же нажать кнопку "Создать", то будет вызван метод DataSource.create(), а уже из него (внутри super()) будет вызван DataSource.write().
Удивительно.

Я честно говоря, думал что речь про ситуацию, при которой уход с записи DataSource.leaveRecord() не вызывает её сохранение.

По вашим же словам проблема возникает из-за того что leaveRecord первой записи вызывается позже чем Сreate для второй.

В любом случае, ситуация при которой мы можем получить несколько не сохранённых строк не будет вписываться в логику работы номерных серий, которые вообще говоря могут быть непрерывными.
Старый 26.02.2016, 14:10   #5  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,701 / 1195 (43) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
Цитата:
Сообщение от S.Kuskov Посмотреть сообщение
По вашим же словам проблема возникает из-за того что leaveRecord первой записи вызывается позже чем Сreate для второй.
Да. Именно так.

Цитата:
Сообщение от S.Kuskov Посмотреть сообщение
В любом случае, ситуация при которой мы можем получить несколько не сохранённых строк не будет вписываться в логику работы номерных серий, которые вообще говоря могут быть непрерывными.
А вот это не так

Внутри метода Create() сначала будут выполнены все методы обработки первой записи и только потом выполняются методы по созданию второй записи. Здесь все корректно и никаких проблем нет.

Проблема в том, что обработчик номерной серии - это некая внешняя "приблуда" не имеющая вообще никакого отношения к стандартным методам ядра. По факту, метод formMethodDataSourceCreatePre() выполняется слишком рано. Он должен был бы быть выполнен после DataSource.write(). Но влезть внутрь super() невозможно. Из-за чего и получаем проблему.

Как другой "костыль" - это "взведение" дополнительного флага внутри Create и его обработка в write
__________________
- Может, я как-то неправильно живу?!
- Отчего же? Правильно. Только зря...
Старый 26.02.2016, 14:44   #6  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,440 / 1775 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
Цитата:
Сообщение от Владимир Максимов Посмотреть сообщение
Внутри метода Create() сначала будут выполнены все методы обработки первой записи и только потом...
Ну как же? В оригинале вызов numberSeqFormHandler().formMethodDataSourceCreatePre() выполняется в самом начале метода Create(), т.е. до данных обработок. Другое дело, что это всего-лишь CreatePre, в котором по идее не должно быть критических операций.
Старый 29.02.2016, 11:40   #7  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,701 / 1195 (43) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
Цитата:
Сообщение от S.Kuskov Посмотреть сообщение
Ну как же? В оригинале вызов numberSeqFormHandler().formMethodDataSourceCreatePre() выполняется в самом начале метода Create(), т.е. до данных обработок. Другое дело, что это всего-лишь CreatePre, в котором по идее не должно быть критических операций.
По факту, вызов методов leaveRecord(), validateWrite(), write() для старой записи происходит внутри super() в методе create().

А это значит, что, с одной стороны, недопустимо в CreatePre() выполнять контроль факта завершения процесса сохранения записи (поскольку он просто еще не начался), а, с другой стороны, бессмысленно изменять значений флагов, которые как раз и устанавливаются внутри методов контроля и сохранения записи.

В результате, метод numberSeqFormHandler().formMethodDataSourceCreatePre() в существующем наполнении - не просто не имеет смысла (занимается не своим делом), но приводит к описанной проблеме.

Другими словами, вызов данного метода следует вообще исключить из процедуры create() на DataSource формы. В идеале, удалить этот метод из класса NumberSeqFormHandler, поскольку в существующей реализации он вводит в заблуждение разработчика. Ведь по факту, этот метод выполняется не перед созданием новой записи, а перед сохранением текущей записи. Что совсем не одно и то же...

Хотя, конечно, есть вероятность того, что новое значение номерной серии было создано вне стандартного функционала создания записей. Например, через программный вызов. Но контролировать эту ситуацию в методе CreatePre() явно избыточно. Избыточный контроль, который добавляет проблем, а не решает их...
__________________
- Может, я как-то неправильно живу?!
- Отчего же? Правильно. Только зря...
Теги
ax2009, ax2012, ax4.0, как правильно

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Создание номерной серии в DAX2012 Mila DAX: Программирование 5 04.04.2013 18:13
Номерные серии АХ2009 Caramba DAX: Администрирование 4 08.08.2011 15:01
Программное создание новых записей Владимир Максимов DAX: Программирование 35 06.03.2006 14:08
Номерные серии для Контактных лиц в Axapta CRM Alex-bs DAX: Функционал 2 10.02.2006 11:29
View's - возможность добавления новых записей Андре DAX: Программирование 13 16.02.2005 12:16

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

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

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