25.07.2012, 08:45 | #1 |
MCTS
|
передача временной таблицы с клиента на сервер
Есть диалог с датасорсом по временной таблице.
Есть серверный класс RunBase, который этот диалог вызывает и содержит в себе поле по этой временной таблице. Правильно ли я понимаю, что, если написать метод класса так: X++: public TmpTable parmTmpTable(TmpTable _tmpTable = tmpTable) { tmpTable = _tmpTable; return tmpTable; } но если написать метод так: X++: public TmpTable parmTmpTable(TmpTable _tmpTable = tmpTable) { if (!prmisdefault(_tmpTable)) tmpTable.setTmpData(_tmpTable); return tmpTable; } |
|
25.07.2012, 09:17 | #2 |
Ищущий знания...
|
не знаю уж откуда пошло, но я всегда при передаче временной таблицы (не зависимо от клиентов и серверов) использую конструкцию:
X++: tmpTable.setTmpData(...);
__________________
"Страх перед возможностью ошибки не должен отвращать нас от поисков истины." (с) С Уважением, Елизаров Артем |
|
25.07.2012, 09:37 | #3 |
Участник
|
Думаю, да. Это равносильно тому, если использовать insert_recordset VS insert внутри while-цикла.
__________________
С уважением, Александр. |
|
25.07.2012, 09:58 | #4 |
Участник
|
X++: tmpTable = _tmpTable; X++: tmpTable.setTmpData(_tmpTable); |
|
25.07.2012, 09:59 | #5 |
Administrator
|
Цитата:
Сообщение от Eldar9x
но если написать метод так:
X++: public TmpTable parmTmpTable(TmpTable _tmpTable = tmpTable) { if (!prmisdefault(_tmpTable)) tmpTable.setTmpData(_tmpTable); return tmpTable; } Копирование указателя через простое присваивание не является копированием в общем случае. Это просто передача указателя. В качестве проверки моих слов - попробуйте создать второй указатель через setTmpData, а затем измените в первом указателе какую-нибудь запись, после чего выберите ее во втором указателе. Увидите - что она тоже изменилась.
__________________
Возможно сделать все. Вопрос времени |
|
25.07.2012, 10:06 | #6 |
Участник
|
А о какой версии Аксаты идет речь?
Помнится, при попытке передать серверную временную таблицу на клиентский курсор с помощью вызова setTmpData() в трешке, валилась клиентская сессия. Вообще, setTmpData() ничего не копирует, а устанавливает указатель на тотже временный файл, что и у передаваемого аргумента. При этом табличная переменная, вызывающая метод, так же оказывается на той стороне, что и аргумент. При этом есть большой ньюанс. Если табличная переменная находится на противоположной стороне от агргумента, в табличной переменной аргумента не было вставлено данных и в момент вызова функции счетчик ссылок аргумента равен 1, то вызывающая табличная перенная не поменяет своего положения, но файл временной таблицы будет пересоздан. X++: server class MyTable MyClass // Экземпляр класса будет создан на сервере { MyTable myTable; } public MyTable MyClass.getMyTableTmp() { ; myTable.setTmp(); //табличная переменная создана на сервере //Здесь не важно заполнение. Клиентский курсор всегда переезжает на сервер return myTable; } static server MyTable MyClass::getMyTableTmpStatic() { MyTable myTable; ; myTable.setTmp(); //табличная переменная создана на сервере //Не заполняем myTable, если будет вставка, то клиентский курсор переедет на сервер return myTable; } static client void processMyTable() { MyTable myTable; MyClass myClass = new MyClass(); ; myTable.setTmp(); //Таблиная переменная создана на клиенте myTable.setTmpData(MyClass::getMyTableTmpStatic()); //табличная переменная указывает на клиентский временный файл myTable = null; myTable.setTmp(); //Таблиная переменная создана на клиенте myTable.setTmpData(myClass.getMyTableTmp()); // табличная переменная будет указывать на серверный временный файл, копирования на клиент не будет } Для более ранних версий, скорее всего, так же верно, но я не проверял Замечу еще, что setTmpData() не сбрасывае и не устанавливает данные в самой табличной переменной. Т.е. если до вызова функции установить значения каких-либо полей, то они останутся уставновленными и после вызова функции. Но в файле временной таблицы этих данных не окажется (если не были вставлены в передаваемом курсоре, естественно) - select их не вернет
__________________
Axapta v.3.0 sp5 kr2 Последний раз редактировалось AndyD; 25.07.2012 в 10:10. |
|
|
За это сообщение автора поблагодарили: sukhanchik (2), lev (5), Eldar9x (3). |
25.07.2012, 12:19 | #7 |
MCTS
|
Вот как, оказывается... А как тогда сделать, чтобы таблица на сервере оказалась реально серверной, а не указывающей на тот же файл клиента?
Цитата:
Если табличная переменная находится на противоположной стороне от агргумента, в табличной переменной аргумента не было вставлено данных и в момент вызова функции счетчик ссылок аргумента равен 1, то вызывающая табличная перенная не поменяет своего положения, но файл временной таблицы будет пересоздан.
Последний раз редактировалось Eldar9x; 25.07.2012 в 12:38. |
|
25.07.2012, 12:47 | #8 |
Участник
|
Цитата:
Пересоздан в том смысле, что если в табличную пременную ранее вставлялись данные, то после этой операции они будут утеряны
__________________
Axapta v.3.0 sp5 kr2 |
|
25.07.2012, 12:55 | #9 |
Участник
|
|
|
25.07.2012, 13:05 | #10 |
Участник
|
Цитата:
|
|
|
За это сообщение автора поблагодарили: MikeR (2). |
26.07.2012, 08:55 | #11 |
Участник
|
Недавно проводил эксперимент - отлично работает упаковка в контейнер в цикле на сервере + распаковка и копирование через .data() + insert на клиенте. Нужно было обработать до 1млн записей на сервере, сгруппировать и на клиенте вывести в отчет 20-50тыс. Проверял до 100тыс - переносится с сервера на клиент в контейнере без ошибок и выпадений около 5 мин.
Таблица постоянно временная - свойство Temporary = Yes. AX 2009 SP1 RU7 |
|
26.07.2012, 10:53 | #12 |
Участник
|
Не первый раз встречаюсь с реализацией предачи данных через контейнер. И всякий раз не понимаю зачем? Вот например Временная таблица, из контейнера в источник данных.
Разве insert из одной табличной переменной в другую не будет быстрее проще и правильнее? P.S.: Можно это даже отдельным методом оформить X++: void copyTmpData(Common _from, Common _to, boolean _replace = false) { ; #ASSERT(_from.isTmp() && _to.isTmp() && _from.TableId == _to.TableId); _to.ttsbegin(); if (_replace) { delete_from _to; } while select _from { _to.data(_from); _to.insert(); } _to.ttscommit(); } Последний раз редактировалось S.Kuskov; 26.07.2012 в 11:10. |
|
26.07.2012, 11:25 | #13 |
Moderator
|
Цитата:
Сообщение от S.Kuskov
Не первый раз встречаюсь с реализацией предачи данных через контейнер. И всякий раз не понимаю зачем? Вот например Временная таблица, из контейнера в источник данных.
Chatiness приложения сильно растет... |
|
|
За это сообщение автора поблагодарили: S.Kuskov (1). |
26.07.2012, 11:53 | #14 |
Участник
|
Ясно...
Да, жалко что нет инструмента копирования целиком табличного буфера без разделения на части или перепаковки. UPD: А такого инструмента наверное и не может быть. Ведь наверняка в общем случае буфер временной таблицы хранится фрагментированно совместно с другими данными в куче. И что бы передать его одним куском, этот один кусок сначала нужно собрать, на деле перепаковав табличный буфер в статическую непрерывную структуру вроде контейнера. Последний раз редактировалось S.Kuskov; 26.07.2012 в 12:09. |
|
26.07.2012, 12:17 | #15 |
Moderator
|
Цитата:
Сообщение от S.Kuskov
Ясно...
Да, жалко что нет инструмента копирования целиком табличного буфера без разделения на части или перепаковки. UPD: А такого инструмента наверное и не может быть. Ведь наверняка в общем случае буфер временной таблицы хранится фрагментированно совместно с другими данными в куче. И что бы передать его одним куском, этот один кусок сначала нужно собрать, на деле перепаковав табличный буфер в статическую непрерывную структуру вроде контейнера. |
|
|
За это сообщение автора поблагодарили: Logger (2). |
26.07.2012, 12:31 | #16 |
Участник
|
Это я уже понял. Просто хотел уточнить. Для того чтобы чохом передать нужно же и "чохом" хранить? Или не обязательно? Т.е. очень сомнительно, что за один "чох" можно передать, например, динамическую структуру типа Map? Мне почему-то кажется что должно выполнятся условие размещения данных в одном передаваемом куске памяти. Я ошибаюсь?
|
|
26.07.2012, 12:48 | #17 |
Участник
|
Цитата:
Сообщение от S.Kuskov
Это я уже понял. Просто хотел уточнить. Для того чтобы чохом передать нужно же и "чохом" хранить? Или не обязательно? Т.е. очень сомнительно, что за один "чох" можно передать, например, динамическую структуру типа Map? Мне почему-то кажется что должно выполнятся условие размещения данных в одном передаваемом куске памяти. Я ошибаюсь?
Либо в памяти (если не очень много успели записать), либо уже на диске, но все вместе Только RPC не надо идеализировать Большие контейнеры тоже будут передавать не целиком за раз, а разбиваться на куски. Соответственно, дополнительных вызовов будет достаточно много. Но, в любом случае, таких обменов будет меньше, чем при условии передачи по каждой отдельной записи
__________________
Axapta v.3.0 sp5 kr2 |
|
26.07.2012, 13:32 | #18 |
Участник
|
Цитата:
В любом случае, если бы была реализация копировани буфера временной таблицы на уровне ядра системы, то это бы помогло бы избежать ненужных накладных расходов на переупаковку данных и в тоже время не повысила бы Chattiness |
|
26.07.2012, 13:52 | #19 |
Участник
|
Так по сети передается контейнер ! А это элементарный тип с точки зрения аксапты, похожий на строку. Т.е. под него сразу фиксированный объем памяти выделяется ("чохом" как вы выразились) при приемке по сети, а потом при распаковке из него создается экземпляр мапа из которого уже данные пошагово достаются и кладутся во времянку, но сеть при этом не дергается. Сеть дергается только при передаче контейнера.
|
|
26.07.2012, 14:19 | #20 |
Участник
|
Logger, я всё это прекрасно понимаю. Я лишь хотел убедится, что "НЕ элементарные" типы передать за один/два RPC вызова нельзя. Но после сообщения AndyD
хотелось бы убедится ещё и в том как именно хранится буфер временной таблицы в оперативной памяти. Как строка в одном месте или фрагментировано в разных связанных областях? Для общего развития так сказать. Просто когда представляешь себе как это там на самом деле всё происходит многие вещи становятся понятнее. Например почему таки нельзя просто взять и скопирования буфер временной таблицы так же как строку или контейнер? |
|