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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 29.05.2019, 12:57   #1  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
ax3,ax4,ax2009,ax2012: RunBaseBatch: как правильно добавить действия, которые должны быть выполнены на клиенте? например, импорт из Excel.
Предположим у нас есть RunBaseBatch.
Он делает что-то тяжелое. Мы конечно же хотим сделать так, чтобы он мог работать на пакетном сервере.
Но этот класс забирает данные из какого-нибудь файла, который находится на клиенте.

Как и куда правильно вставить действия, которые должны выполняться на клиенте?

Сейчас правильный способ видится таким:
* разбить процесс на два runBaseBatch класса: первый будет иметь свойство RunOn=Client, второй - RunOn=Server
* первый в методе run должен будет выполнить клиентские действия, создать второй класс на сервере и передать ему параметры и данные

Но что-то как-то слишком сложно. Очень напоминает overprogramming.

Может существует другой способ?
__________________
полезное на axForum, github, vk, coub.
Старый 29.05.2019, 13:25   #2  
Zabr is offline
Zabr
Участник
Axapta Retail User
 
1,200 / 345 (14) ++++++
Регистрация: 26.06.2002
Адрес: Москва
На каком именно клиенте?
Старый 29.05.2019, 13:55   #3  
TasmanianDevil is offline
TasmanianDevil
Мрачный тип
Аватар для TasmanianDevil
Злыдни
 
885 / 389 (14) ++++++
Регистрация: 24.01.2005
Адрес: Томск
IMHO, проще размещать файл на пакетнике или выделенном сетевом ресурсе с доступом для AOS и не дергать удачу за вымя, пытаясь обойти "радости" объемного клиент-серверного общения
__________________
Мы летаем, кружимся, нагоняем ужасы ...
За это сообщение автора поблагодарили: ax_mct (3).
Старый 29.05.2019, 14:24   #4  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от Zabr Посмотреть сообщение
На каком именно клиенте?

Шутку оценил. Смешно.

Цитата:
Сообщение от TasmanianDevil Посмотреть сообщение
IMHO, проще размещать файл на пакетнике или выделенном сетевом ресурсе с доступом для AOS и не дергать удачу за вымя, пытаясь обойти "радости" объемного клиент-серверного общения
Оно конечно понятно. Но такое решение выглядит костылем. А хотелось бы понять как правильно.

Костылем поскольку:
* не совсем правильно давать пользователям доступ в общий сетевой ресурс.
* не совсем правильно давать доступ АОСу к пользовательским сетевым папкам
* не совсем правильно заставлять пользователей перекладывать файлы с места на место (21 век на дворе жеж)


И это не попытка обойти объемное клиент-серверное общение. Это попытка понять как правильно разделить обязанности между клиентом и сервером.
__________________
полезное на axForum, github, vk, coub.
Старый 29.05.2019, 14:30   #5  
fed is offline
fed
Moderator
Аватар для fed
Ex AND Project
Соотечественники
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
2,890 / 5647 (194) ++++++++++
Регистрация: 13.03.2002
Адрес: Hüfingen,DE
Может быть можно использовать кастомизированную форму вместо диалога, и в этой форме сделать кнопочку для чтения файла, а потом этот файл, как контейнер, передавать назад в RunBaseBatch ? (Я этого никогда не пробовал, но в целом - может и взлететь).
Старый 29.05.2019, 15:02   #6  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,622 / 2922 (107) +++++++++
Регистрация: 16.01.2004
Записей в блоге: 5
Все зависит от того, насколько важна безопасность и легкость настройки по сравнению с местом для хранения временем переписывания.

1. run on server и где-то в диалоге переписать файл на сервер а в качестве параметров пакетного задания уже записывать путь на сервере (следует учесть, что в 2012 вызовы с сервера на клиент запрещены и надо будет как-то это обходить)

2. Дать доступ клиенту и серверу к одной папке и хранить путь там

3. Как 1 но в SysOperation framework: UIBuilder переписывает и кладет серверный путь в контракт. Я не помню, где исполняется UI builder в 2012 но, думаю, на клиенте.

см также копирование файловмежду уровнями

Последний раз редактировалось belugin; 29.05.2019 в 15:05.
Старый 30.05.2019, 00:16   #7  
gl00mie is offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,684 / 5788 (200) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
Записей в блоге: 3
Цитата:
Сообщение от mazzy Посмотреть сообщение
Предположим у нас есть RunBaseBatch.
Он делает что-то тяжелое. Мы конечно же хотим сделать так, чтобы он мог работать на пакетном сервере. Но этот класс забирает данные из какого-нибудь файла, который находится на клиенте. Как и куда правильно вставить действия, которые должны выполняться на клиенте?
Я лично в свое время для AX2009 делал условно базовый класс импорта из Excel, который при правильном использовании:
  • запускался на сервере (main)
  • переключался на клиента для отображения диалога (prompt) при этом позволял не только выбрать файл Excel, но и нужный лист в нем
  • потом переключался обратно на сервер (run)
  • в определенный момент создавал свою копию на клиенте по аналогии с тем, как это делает RunBase в prompt()
  • на клиенте начитывал данные из файла и сохранял их в контейнер
  • возвращался на сервер, получал контейнер с данными и начинал собственно их обработку, валидацию, вставку, обновление, вот это вот всё
При этом в классах-наследниках требовалось реализовать логику подбора листа по умолчанию, уточнения, откуда на листе считывать данные, и обработки считанных данных уже на сервере. Таким образом, клиент-серверное взаимодействие сводилось к минимуму. У коллег видел реализации импортов, которые просто через специально обученный клиентский класс в один присест получали на сервере данные из клиентского файла в виде опять же контейнера и дальше уже парсили их на сервере, но без интерактива в диалоге выбора файла.
Разумеется, в AX2012 появляются свои заморочки с вызовом клиентского кода, инициированным с сервера, но вроде все решается при желании. А предложенный подход с кастомизированной формочкой - это вроде как раз то, что приходится делать в D365O для импортов из Excel: брать клиентский файл, передавать его во временный каталог на АОСе и там уже с ним работать.
Старый 30.05.2019, 08:34   #8  
KiselevSA is offline
KiselevSA
Злыдни
Аватар для KiselevSA
Злыдни
Лучший по профессии 2015
 
958 / 333 (13) ++++++
Регистрация: 25.01.2002
Адрес: Москва
Есть одна, возможно дурацкая, идея:
- в диалоге пользователь указывает полный путь к файлу;
- если класс необходимо выполнить в пакетном режиме, в момент создания пакетного задания прикрепить к заданию файл;
- в обработке читать прикрепленный файл;
- в конце задания удалять прикрепленный файл из хранилища (с диска, из БД и т.п.)
__________________
люди...считают, что если техника не ломается, то ее не нужно ремонтировать. Инженеры считают, что если она не ломается, то нуждается в совершенствовании.
За это сообщение автора поблагодарили: ax_mct (3).
Старый 30.05.2019, 10:44   #9  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,651 / 1158 (42) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
Цитата:
Сообщение от mazzy Посмотреть сообщение
Предположим у нас есть RunBaseBatch.
Он делает что-то тяжелое. Мы конечно же хотим сделать так, чтобы он мог работать на пакетном сервере.
Но этот класс забирает данные из какого-нибудь файла, который находится на клиенте.

Как и куда правильно вставить действия, которые должны выполняться на клиенте?

Сейчас правильный способ видится таким:
* разбить процесс на два runBaseBatch класса: первый будет иметь свойство RunOn=Client, второй - RunOn=Server
* первый в методе run должен будет выполнить клиентские действия, создать второй класс на сервере и передать ему параметры и данные

Но что-то как-то слишком сложно. Очень напоминает overprogramming.

Может существует другой способ?
А по-моему - нормально. Я бы даже усугубил Класс-обработчик не запускать напрямую, а формировать пакетное задание.

Тогда то, что выполняется на клиенте - это запускает сам клиент (вместо RunBaseBatch - использовать RunBase), но результатом запуска становится не обработанные данные, а сформированное пакетное задание. Вот после обработки этого пакетного задания и получим результат

Т.е. логика такая

1. Клиент запускает пункт меню с классом RunBase. Это НЕ пакетное задание
2. Класс загружает нужные данные с клиента. Возможно, записывает в какие-нибудь parm-таблицы
3. Формирует пакетное задание на основе другого класса RunBaseBatch, который и выполняет собственно обработку
4. Для пользователя - работа пункта меню завершена. Но собственно обработка пока не выполнена. Это надо ждать завершение нового пакетного задания


Здесь единственный недостаток, что если по окончании обработки необходимо выполнить некие действия на клиенте, то не получится

Можно вообще разделить на 2 независимых пункта меню

1. Загрузка данных
2. Обработка ранее загруженных данных

Тут можно много всякого разного напридумывать при такой идеологии. И повторная обработка, и просмотр ошибок, и "разбор полетов" на предмет, что загрузили не то. Да мало ли... Но это если в этом есть необходимость, конечно...
__________________
- Может, я как-то неправильно живу?!
- Отчего же? Правильно. Только зря...
За это сообщение автора поблагодарили: mazzy (2), ax_mct (5).
Старый 30.05.2019, 11:00   #10  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,651 / 1158 (42) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
Почему я считаю разделение на 2 класса - нормальным

По той причине, что и собственно загрузка данных, и последующая обработка, очевидно, не тривиальные процессы (раз вообще возник вопрос о необходимости разделения). Т.е. наверняка много кода (много методов) будет как для загрузки, так и для обработки. И если это все пихать в один RunBase, то получим безумное количество методов в одном классе с которыми потом будет очень тяжело разбираться (есть печальный опыт )

Поэтому просто формальное разделение методов по разным классам - уже хорошо. Даже если это будет банальный вызов одного из другого без каких-либо пакетных заданий

1. RunBase - диалог с пользователем и "диспетчер" для вызова других классов
2. Класс - загрузчик данных
3. Класс - обработчик данных

Ну, а получив в явном виде разделение процессов по разным классам позже можно будет подумать о запуске этих процессов по отдельности. В разных пакетных заданиях, например...
__________________
- Может, я как-то неправильно живу?!
- Отчего же? Правильно. Только зря...
Старый 30.05.2019, 17:26   #11  
andiv is offline
andiv
Участник
 
16 / 34 (2) +++
Регистрация: 11.01.2007
msmq не подойдет?
Старый 30.05.2019, 20:10   #12  
ax_mct is offline
ax_mct
Banned
 
2,548 / 1091 (0) ++++++++
Регистрация: 10.10.2005
Адрес: Westlands
Цитата:
Сообщение от mazzy Посмотреть сообщение
Предположим у нас есть RunBaseBatch.
Он делает что-то тяжелое. Мы конечно же хотим сделать так, чтобы он мог работать на пакетном сервере.
Но этот класс забирает данные из какого-нибудь файла, который находится на клиенте.

Как и куда правильно вставить действия, которые должны выполняться на клиенте?

Сейчас правильный способ видится таким:
* разбить процесс на два runBaseBatch класса: первый будет иметь свойство RunOn=Client, второй - RunOn=Server
* первый в методе run должен будет выполнить клиентские действия, создать второй класс на сервере и передать ему параметры и данные

Но что-то как-то слишком сложно. Очень напоминает overprogramming.

Может существует другой способ?
Тяжелое, не тяжелое, а действия принципиально те же. Хватаем и тащим. И табуретки и пианино.

Клиентом пишем в базу. Можно при желании уменьшить обращения но это уже оптимизация редко нужная. Временная DB таблица или staging если нужна история.

Сервер берет из базы. В пакетнике или нет, не так важно.

Смысла жонглировать классами - не вижу. Практически всегда вдруг возникает требование видеть историю или статус валидации, а это staging. А там где staging все приходит к ParmId и Line Status и может еще пара параметров типа даты и пр.
За это сообщение автора поблагодарили: mazzy (2).
Старый 30.05.2019, 20:16   #13  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от ax_mct Посмотреть сообщение
Клиентом пишем в базу.
Прям руками? В отдельную таблицу?

Почему не saveLast? если saveLast, то в какое место класса RunBase вставить вызов?

если использовать стандартный вызов saveLast, то в какое место вставить импорт из Excel?
__________________
полезное на axForum, github, vk, coub.
Старый 31.05.2019, 02:47   #14  
ax_mct is offline
ax_mct
Banned
 
2,548 / 1091 (0) ++++++++
Регистрация: 10.10.2005
Адрес: Westlands
Цитата:
Сообщение от mazzy Посмотреть сообщение
Прям руками? В отдельную таблицу?

Почему не saveLast? если saveLast, то в какое место класса RunBase вставить вызов?

если использовать стандартный вызов saveLast, то в какое место вставить импорт из Excel?
Если пользователь выбирает файл на клиенте в диалоговой форме (RunBase.prompt) то я бы сделал эту форму статической (AOT формой) и добавил операцию загрузки данных на сервер как отдельный шаг и только тогда позволял бы нажимать OK (в пакетнике или нет, не важно).

Выделял бы RunId на каждый запуск и именно его бы и передавал помимо фильтров.
Операция загрузки данных на сервер в staging конечно руками и не так важно где этот код.

С точки зрения дизайна решения предварительная загрузка данных с клиента на сервер
мне кажется наиболее прямым решением. Можно и просто копировать файл на сервер, а не писать в базу. Но предварительная операция как загрузка на сервер как принцип.

То есть разбиваем на операции, а не классы. Если что-то реальное сложное то я бы даже предлагал бы wizard с шагами до кнопки OK пакетника. И солидно, и голова меньше болит когда логика по шагам.
Старый 31.05.2019, 03:04   #15  
ax_mct is offline
ax_mct
Banned
 
2,548 / 1091 (0) ++++++++
Регистрация: 10.10.2005
Адрес: Westlands
Цитата:
Сообщение от mazzy Посмотреть сообщение
Почему не saveLast?
Потому что страшно. Что он там и как сохраняет с какими таймаутами и размерами не подконтрольно. Может там TempDB потом взорвется или еще что. Не предназначено saveLast для данных в принципе.

Руками в свою таблицу и передача RecId как ссылки на загруженные в DB данные - оно более как то и спокойнее и проще.
Старый 31.05.2019, 08:35   #16  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от ax_mct Посмотреть сообщение
...и передача RecId как ссылки на загруженные в DB данные
Хорошо, возвращаемся к исходному вопросу:

RunBaseBatch: как правильно добавить действия, которые должны быть выполнены на клиенте? например, импорт из Excel подготовку списка RecId и передачу списка на сервер для дальнейшей обработки.
__________________
полезное на axForum, github, vk, coub.

Последний раз редактировалось mazzy; 31.05.2019 в 08:45.
Старый 31.05.2019, 10:23   #17  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,622 / 2922 (107) +++++++++
Регистрация: 16.01.2004
Записей в блоге: 5
getFromDialog вместо того, чтобы сохранять имя файла как есть (или вместе с этим если надо, например, в следующий раз показать тот же путь) выгружает на сервер и запоминает RecID в поле, recID входит в список упаковки и дальше обрабатывается так же как и все другие поля. Отличия только в UI
Старый 31.05.2019, 10:26   #18  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,622 / 2922 (107) +++++++++
Регистрация: 16.01.2004
Записей в блоге: 5
Цитата:
Сообщение от mazzy Посмотреть сообщение
Почему не saveLast? если saveLast, то в какое место класса RunBase вставить вызов?
Если кто-то запустит не в пакетном режиме, то для того, чтобы использовать saveLast надо как-то разделять SysLastValue по разным фактам запуска.

Еще, насколько я помню, при передаче больших файлов на сервер надо порциями передавать большой контейнер, чтобы он уместился в буфер RPC.
Старый 31.05.2019, 10:56   #19  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от belugin Посмотреть сообщение
getFromDialog ... выгружает на
getFromDialog в стандарте вызывается из метода closeOk/checkCloseOk
другими словами, getFromDialog вызывается ДО закрытия диалога

если в getFromDialog добавить долгую обработку, то диалог будет висеть перед пользователем очень долгое время и не реагировать ни на какие нажатия, что приводит пользователя в ступор.

если getFromDialog добавить долгую обработку И SysOperationProgress/RunBaseProgress, то Аксапта уводит окно с диалогом в background и пользователь как правило больше диалог достать не может

а если во время длинной операции внутри getFromDialog произойдет ошибка, то пользователь увидит инфолог, но диалог не закроется и не будет виден пользователю.

можно я повторю вопрос:
RunBaseBatch: как правильно добавить действия, которые должны быть выполнены на клиенте? например, импорт из Excel.


Цитата:
Сообщение от belugin Посмотреть сообщение
Если кто-то запустит не в пакетном режиме, то для того, чтобы использовать saveLast надо как-то разделять SysLastValue по разным фактам запуска.

Еще, насколько я помню, при передаче больших файлов на сервер надо порциями передавать большой контейнер, чтобы он уместился в буфер RPC.
Угу-угу.

Теперь мой вопрос понятен?

RunBaseBatch: как правильно добавить действия, которые должны быть выполнены на клиенте? например, импорт из Excel.
Миниатюры
Нажмите на изображение для увеличения
Название: 2009.PNG
Просмотров: 168
Размер:	33.3 Кб
ID:	12325  
Изображения
 
__________________
полезное на axForum, github, vk, coub.
Старый 31.05.2019, 15:33   #20  
ax_mct is offline
ax_mct
Banned
 
2,548 / 1091 (0) ++++++++
Регистрация: 10.10.2005
Адрес: Westlands
Цитата:
Сообщение от mazzy Посмотреть сообщение
RunBaseBatch: как правильно добавить действия, которые должны быть выполнены на клиенте? например, импорт из Excel.
Я бы предлагал сделать эти действия снаружи RunBaseBatch и передавать талончик туда на вход как параметр. Своя AOT форма на которой кнопка загрузить файл с прогресс-баром и кнопка вызова RunBaseBatch куда мы передаем номер взвешенного мяса для оплаты на кассе.
Одного единственного номера достаточно как HeaderRecId запуска для всех файлов.

Это конечно от UI если предполагается ручной выбор файла и одноразовый пакетник.
Если это папка то на клиенте ей делать нечего так как Batch это сервер.

Извиняюсь если сбиваю с темы расчленения RunBaseBatch.
Теги
как правильно

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
ax3,ax4,ax2009,ax2012: Есть ли красивый способ передать packable объект между клиентом и сервером? mazzy DAX: Программирование 20 09.06.2019 23:19
axaptacorner: How to read excel and update record in AX2012 through X++ code Blog bot DAX Blogs 0 04.01.2019 17:13
Скрипт для переноса данных Ax3.0 (Oracle) - Ax2009 (MSSQL) someOne DAX: Программирование 2 14.06.2011 14:53
axcoder: AxPath pugin for Tabax which works with Ax3, Ax4, Ax2009 Blog bot DAX Blogs 0 08.11.2008 02:11
Импорт из 'офисной БД' (Excel, Access) Gustav DAX: База знаний и проекты 4 07.06.2008 17:17
Опции темы Поиск в этой теме
Поиск в этой теме:

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

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

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

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