|  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), Eldar9x (3), lev (5), Logger (5). | |
|  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  хотелось бы убедится ещё и в том как именно хранится буфер временной таблицы в оперативной памяти. Как строка в одном месте или фрагментировано в разных связанных областях? Для общего развития так сказать. Просто когда представляешь себе как это там на самом деле всё происходит многие вещи становятся понятнее. Например почему таки нельзя просто взять и скопирования буфер временной таблицы так же как строку или контейнер? | 
|  |