|
21.02.2007, 16:00 | #1 |
Участник
|
Kashperuk Ivan: Dynamics AX TutorialsHello, everyone.I was goi...
Источник: http://kashperuk.blogspot.com/2007/0...-everyone.html
============== Dynamics AX Tutorials Hello, everyone. I was going through the Jobs node in my application recently, and stumbeled upon a lot of good examples of different programming technics. I thought it would be nice to share what I have :) So with this post I will start a series of tutorials on Axapta development. Today's post is about selecting multiple records on a form (using checkboxes instead of standard Axapta method) The homepage for this tutorial in on Axaptapedia It is a simple tutorial form based on InventTable datasource. You can select multiple lines and process the lines by pressing Process lines button. Here is a short list of what is covered in the tutorial besides the main point of processing selected lines:
Источник: http://kashperuk.blogspot.com/2007/0...-everyone.html |
|
21.02.2007, 16:40 | #2 |
Участник
|
Потенциально это очень опасный метод.
класс Set "живет" и хранит свои данные в памяти (или в свопе) компьютера. Поскольку это множество хранит данные с формы, то, скорее всего, он живет и хранит свои данные в памяти клиентского компьютера. Со всеми вытекающими последствиями к железу и свопу, если будет отмечено много записей. Кроме того, данные из класса Set нельзя будет использовать в запросе. Это значит, что обработка этих галочек также будет выполняться, скорее всего, на клиентском компьютере. Пожалуйста, не превращайте Аксапту в 1С. В качестве образца используйте маркировку при сопоставлении (таблица SpecTrans) Это тоже не фонтан. Но гораздо лучше, чем гонять данные на клиента. |
|
|
За это сообщение автора поблагодарили: EVGL (-1). |
21.02.2007, 21:28 | #3 |
Участник
|
а еще енумератор лучше итератора
|
|
|
За это сообщение автора поблагодарили: kashperuk (2). |
21.02.2007, 21:34 | #4 |
Участник
|
Я считаю, что подход Ивана вполне резонный. Но чтобы избежать обработки выбранных записей на клиенте я бы посоветовал либо перекрыть метод clicked() на BtnProcessLines и вызвать из ней класс (у которого поставить св-во выполняться на сервере) и передать ему сформированный set упакованный в контейнер.
Либо, если есть желение сделать это через menuitem то на форме добать метод возвращающий упакаванный в контейнер set и вызывать его из класса, запущенного на сервере, чтобы получить выбранные записи. Способ через промежуточную таблицу, ИМХО для таких случаев слишком громоздок. |
|
|
За это сообщение автора поблагодарили: kashperuk (2). |
21.02.2007, 22:21 | #5 |
Участник
|
Ребята.
Необходимо внести определенные разъяснения. В самом блоге я как-то не все описал. А в сам проект на axaptapedia видимо никто не посмотрел. (ничего, учту в след. раз). По ссылке было описано замечание как раз по поводу работы на сервере/клиенте. Вот, вырезал (это из метода обработки строк) Цитата:
This method should not be implemented on the form and is merely here to avoid creating another object for the example
The processing should be implemented on a server based class To pass the selected lines to the class for processing use the pack method of the set object, itemIdSet.pack() This will create a container that you will pass on to the class. Then you unpack the container into a Set object Set processLinesSet = Set::create(_packedSet), where _packedSet is the passed container Прежде всего, спасибо за чтение, критику и рекомендации. Очень полезно мне и другим. Цитата:
Сообщение от mazzy
Потенциально это очень опасный метод.
класс Set "живет" и хранит свои данные в памяти (или в свопе) компьютера. Поскольку это множество хранит данные с формы, то, скорее всего, он живет и хранит свои данные в памяти клиентского компьютера. Со всеми вытекающими последствиями к железу и свопу, если будет отмечено много записей. Этот механизм хорош для работы именно с ограниченным набором значений. К примеру, у нас что-то подобное используется при обработке строк закупки (перед обработкой накладной) А даже если бы и выделяли 1000 строк, то это ни заняло бы мизерное количество памяти клиентской машины (да у меня электронная NoteZilla в 6-7 раз больше кушает (причем, на постоянной основе, а не временно - до передачи в класс) Не совсем понятно, зачем. Хотя, возможно, это и недостаток. Кстати, опять же на Аксаптапедии, разместил снизу ссылку на использование стандартного подхода - http://www.axaptapedia.com/Multiple_grid_selections Не знаю почему, но юзерам так этот 1С нравится. Что они в нем нашли? Расскажи, расскажи про приемущества. Никогда енумераторы не пользовал. Всегда итераторы предпочитал. Цитата:
Завтра, если время найду, оформлю с использованием обработки через класс. Еще раз, спасибо |
|
|
За это сообщение автора поблагодарили: mazzy (5). |
21.02.2007, 23:44 | #6 |
Участник
|
Юзерам нравится не 1С, а свобода однопользовательской системы.
Напомню, что юзерам также нравится Outlook... Хорошо, выражусь по-другому. Не превращайте многопользовательскую, хорошо работающую с тонкими каналами, не требовательную к железу программу в однопользовательскую, жадную до железа и пропускной способности каналов программу. |
|
21.02.2007, 23:39 | #7 |
Участник
|
Цитата:
Сообщение от petr
Я считаю, что подход Ивана вполне резонный. Но чтобы избежать обработки выбранных записей на клиенте я бы посоветовал либо перекрыть метод clicked() на BtnProcessLines и вызвать из ней класс (у которого поставить св-во выполняться на сервере) и передать ему сформированный set упакованный в контейнер.
Цитата:
...для каждой строчки ...или весь set подумайте еще раз. Прикиньте как это будет работать для нескольких десятков, сотен, тысяч, миллионов записей. Цитата:
Цитата:
Запоминать упакованный класс будете? Нафиг. |
|
22.02.2007, 00:03 | #8 |
Участник
|
Цитата:
а еще енумератор лучше итератора
|
|
22.02.2007, 13:01 | #9 |
Участник
|
Позволю себе ответить цитатой:
Цитата:
Сообщение от belugin
1. Не надо два раза писать тип коллекции Enumerator i = list.getEnumerator()
2. Нет способа пропустить next и получить бесконечный цикл 3. Он всегда на том же звене что и колекция, если сделать итератор и коллекцию на разных звеньях могут быть глюки |
|
|
За это сообщение автора поблагодарили: petr (1). |
22.02.2007, 00:18 | #10 |
Участник
|
Цитата:
Угу. И для отображения галочек на клиенте гонять данные между клиентом и сервером...
...для каждой строчки ...или весь set To Иван Я скачал проект, и мельком все просмотрел. Но твои коментарии пропустил. Так что извини за мои коментарии. Я считаю подход правильным. Еще, конечно, необходимо убедиться, что при простановке галочек нет нележательных побочных эффектов. Но это вопрос дисскусии и эксперимента. А вообще хорошо, что мы подняли этот вопрос. Такая необходимость (дать возможность пользователю отметить несколько записей из всего грида) возникает время от времени, а я пока нигде не встречал готорого паттерна для решения такой задачи. Так что если мы вместе с этим разберемся, то будет новый паттерн для аксапты, который новички, и продвинутые программисты смогут использовать в своих разработках. |
|
22.02.2007, 00:26 | #11 |
Участник
|
To mazzy:
Я выступаю за разграничение скажем так ответственности. Если необходимо запоминать выбор пользователя, и воможно из других участков программы проверять проставлены ли эти галочки (т.е. промаркирована ли та или иная запись или нет), то конечно лучше использовать таблицу из AOT. И эти единственный выход. Но если в определенный форме, необходимо дать пользователю возможность отметить несколько записей, то мне кажется вариант Ивана (и он, кстати не из головы его придумал, а такой подход используеся и в самой Аксапте) то правильный. Во всяком случае он не использует временные таблицы для хранения отмеченных записей, и не добавляет новое поле (для галочки) в саму таблицу и подобные ошибки. Сам из когда то допускал, и не хочу чтобы их повторяли другие. |
|
22.02.2007, 00:36 | #12 |
Участник
|
Цитата:
Этот случай я уже критиковал Kashperuk Ivan: Dynamics AX TutorialsHello, everyone.I was goi... Цитата:
http://www.axaptapedia.com/Multiple_grid_selections Стандартный паттерн называется multiSelect. Он даже имеет свойство для menuitem. Обрабатывается ядром на клиенте. Цитата:
Но сначала таки прочитайте про multiSelect. Цитата:
2. галочка отдельным полем есть в сводном планировании. Галочка отдельным полем очень даже подходящее решение, если для всех пользователей набор галочек общий Еще раз - если речь идет о НЕСКОЛЬКИХ записях, то не надо ничего придумывать и программировать классы - просто обрабатывайте стандартное выделение нескольких строк. (Кстати, этот способ не требует программирования, если пользователь захочет выделить все строки) Если же речь идет о массовой расстановке галочек, то галочки нельзя хранить в свопе клиента. Не стоит делать массовые галочки, по которым не работает фильтр и сортировка. Не стоит делать массовые галочки, которые нельзя обработать на SQL-запросом. Не стоит делать массовые галочки, которые требуют большого траффика между клиентом и сервером. |
|
22.02.2007, 11:45 | #13 |
Banned
|
Цитата:
Мне кажется, не стоит устраивать тут религиозные войны. Попробую обобщить: +) Вариант с "крестиком" позволяет пользователю подумать. Он не мучается, придерживая Ctrl. -) Вариант с "крестиком" требует написания большего количества кода +) Вариант с multiSelect хорош, когда выделяемых строк мало -) Вариант с multiSelect медленнее, чем "крестик", поскольку работает не с одной переменной, а с целым буфером записи из datasource, хотя эффект, наверное, исчезающе мал +) Вариант крестика с Set хорош тем, что его проще запаковать и передать на сервер -) Вариант с временной таблицей хорош тогда, когда таблица имеет композитный ключ, а индекса по RecId нет. Для Set пришлось бы строить какой-то hashStr, а потом его еще и разбирать. Последний раз редактировалось EVGL; 22.02.2007 в 11:47. |
|
22.02.2007, 12:58 | #14 |
Участник
|
Еще информация для размышлений:
Вот job для экспериментов X++: static void tutorial_Job_getMemAlloc(Args _args) { HeapCheck heapHeck = new HeapCheck(); int allocFirst; Set set1; Set set2; Set set3; int i; timeOfDay time1; TmpInventTable tmpIT; Counter recIdCount; ; recIdCount = 40000; allocFirst = heapHeck.bytesAllocated(); info(strfmt("%1 - До заполнения", allocFirst)); time1 = timeNow(); set1 = new Set(Types::Integer); for (i = 1; i <= recIdCount; i++) set1.add(i); allocFirst = heapHeck.bytesAllocated(); info(strfmt("%1 - %2сек - заполнили Set(Types::Integer)", allocFirst, timeNow() - time1)); time1 = timeNow(); set1 = new Set(Types::String); for (i = 1; i <= recIdCount; i++) set1.add(strFmt("Item%1", i)); allocFirst = heapHeck.bytesAllocated(); info(strfmt("%1 - %2сек - заполнили Set(Types::String)", allocFirst, timeNow() - time1)); time1 = timeNow(); for (i = 1; i <= recIdCount; i++) { tmpIT.ItemId = strFmt("Item%1", i); tmpIT.insert(); } allocFirst = heapHeck.bytesAllocated(); info(strfmt("%1 - %2сек - заполнили временную таблицу из одного поля - ItemId", allocFirst, timeNow() - time1)); } 28 939 792 - До заполнения 30 413 632 - 1сек - заполнили Set(Types::Integer) 30 401 280 - 1сек - заполнили Set(Types::String) 32 763 840 - 13сек - заполнили временную таблицу из одного поля - ItemId Обращу внимание на время, требуемое для заполнения временной таблицы таким большим кол-вом записей. SET заполняется почти мгновенно. (правда у других проверяющих время заполнения меньше для таблицы - видимо это связано с тем, что винт у меня на ноутбуке не очень быстрый) Оговорка: Результаты по выделению памяти приблизительные, так как Цитата:
Сообщение от AndyD
Память выделяется кусками. Т.е. если объект в памяти занимает меньше места, чем свободно - то выделение не происходит, а размещается в свободном куске
Анализ результатов (краткий): первые два заполнения - 2 Мб выделилось приблизительно, (на двоих) на табличку - еще столько же где-то. Учитывая это и время заполнения, использование временной таблицы ставится под вопрос. + большой конечно, что можно ее потом использовать в запросах. Правда и в этом нужно быть осторожным, так как нужно учитывать, где формировалась эта таблица (первая запись). У кого какие соображения? |
|
|
За это сообщение автора поблагодарили: EVGL (3). |
22.02.2007, 00:55 | #15 |
Участник
|
Вообщем, после того как меня ткнули (спасибо mazzy) лицом в эту ссылку http://www.axaptapedia.com/Multiple_grid_selections то я даже не знаю, что ответить. Вообщем стандартный паттерн - это хорошо (как это я раньше его не встречал?, хотя учиться никогда не поздно) и лучше всегда его использовать.
Если же пользователи все-таки хотят галочек и их никак не переубедить, то я не знаю. Пуска сам решает сам, или слушает совета более опытных (mazzy или Ивана) To mazzy Цитата:
Почему вы считаете временную таблицу ошибкой?
Цитата:
галочка отдельным полем есть в сводном планировании. Галочка отдельным полем очень даже подходящее решение, если для всех пользователей набор галочек общий
|
|
22.02.2007, 11:16 | #16 |
Участник
|
Цитата:
Кстати, опытные разработчики рекомендуют все-равно использовать временную таблицу. Попробуйте написать прототипы и с тем, и с другим, и проверить производительность в вашем случае. |
|
|
За это сообщение автора поблагодарили: kashperuk (10). |
22.02.2007, 00:58 | #17 |
Участник
|
И еще всем. Прошу прощения за обилие грамматических ошибок и опечеток. Не научился я еще вслепую на родном языке печатать, а русских букв на клавиатуре нет. Еще раз прошу прощения.
|
|
22.02.2007, 14:13 | #18 |
Участник
|
Вот еще цитата, про стандартный подход
http://www.axaptapedia.com/Multiple_grid_selections Цитата:
Сообщение от AndyD
Наличие стандартного метода, конечно, хорошо. Но, есть пара моментов, которые мне не нравятся.
1. Не очень удобный выбор - ткнет пользователь без шифта или контрола и начинай сначала. 2. Перейдет пользователь в конец таблицы - и все сбросится (при этом кнопки без мультиселекта так и останутся неактивными). 3. Выбор находится на клиенте и что-бы обработать на сервере надо будет как-то организовывать передачу. |
|
Теги |
download, как правильно, полезное, производительность, axapta |
|
|