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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 25.07.2012, 08:45   #1  
Eldar9x is offline
Eldar9x
MCTS
Аватар для Eldar9x
Oracle
MCBMSS
 
1,064 / 166 (8) ++++++
Регистрация: 29.09.2006
Адрес: Казань
передача временной таблицы с клиента на сервер
Есть диалог с датасорсом по временной таблице.
Есть серверный класс RunBase, который этот диалог вызывает и содержит в себе поле по этой временной таблице.
Правильно ли я понимаю, что, если написать метод класса так:

X++:
public TmpTable parmTmpTable(TmpTable _tmpTable = tmpTable)
{
   tmpTable = _tmpTable;
   return tmpTable;
}
то при вызове его на диалоге с передачей курсора датасорса этого диалога, мы в серверном классе получим ссылку на клиентский курсор временной таблицы, и пробежка по tmpTable приведет к трафику между клиентом и сервером.

но если написать метод так:

X++:
public TmpTable parmTmpTable(TmpTable _tmpTable = tmpTable)
{
   if (!prmisdefault(_tmpTable))
      tmpTable.setTmpData(_tmpTable);
   return tmpTable;
}
то в этом случае временная таблица с клиента будет передана в класс сразу скопом, и при дальнейшей пробежке по tmpTable клиент затрагиваться не будет?
Старый 25.07.2012, 09:17   #2  
lev is offline
lev
Ищущий знания...
Аватар для lev
Oracle
MCBMSS
Axapta Retail User
 
1,723 / 491 (20) +++++++
Регистрация: 18.01.2005
Адрес: Москва
не знаю уж откуда пошло, но я всегда при передаче временной таблицы (не зависимо от клиентов и серверов) использую конструкцию:
X++:
tmpTable.setTmpData(...);
З.Ы. да и не только при передаче, и при инициализации тоже.
__________________
"Страх перед возможностью ошибки не должен отвращать нас от поисков истины." (с)
С Уважением,
Елизаров Артем
Старый 25.07.2012, 09:37   #3  
samolalex is offline
samolalex
Участник
Аватар для samolalex
Самостоятельные клиенты AX
 
259 / 107 (4) +++++
Регистрация: 18.06.2010
Адрес: Москва
Думаю, да. Это равносильно тому, если использовать insert_recordset VS insert внутри while-цикла.
__________________
С уважением, Александр.
Старый 25.07.2012, 09:58   #4  
ice is offline
ice
Участник
Аватар для ice
Лучший по профессии 2014
 
1,688 / 405 (17) +++++++
Регистрация: 23.03.2006
X++:
  tmpTable = _tmpTable;
передает ссылку на курсор

X++:
tmpTable.setTmpData(_tmpTable);
передает ссылку на "место хранения"
Старый 25.07.2012, 09:59   #5  
sukhanchik is offline
sukhanchik
Administrator
Аватар для sukhanchik
MCBMSS
Злыдни
Лучший по профессии 2015
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,271 / 3465 (122) ++++++++++
Регистрация: 13.06.2004
Адрес: Москва
Цитата:
Сообщение от Eldar9x Посмотреть сообщение
но если написать метод так:

X++:
public TmpTable parmTmpTable(TmpTable _tmpTable = tmpTable)
{
   if (!prmisdefault(_tmpTable))
      tmpTable.setTmpData(_tmpTable);
   return tmpTable;
}
то в этом случае временная таблица с клиента будет передана в класс сразу скопом, и при дальнейшей пробежке по tmpTable клиент затрагиваться не будет?
Метод setTmpData не копирует буфер таблицы, а всего лишь создает второй указатель на этот буфер. Т.е. буфер в данном случае все равно останется на клиенте.

Копирование указателя через простое присваивание не является копированием в общем случае. Это просто передача указателя.

В качестве проверки моих слов - попробуйте создать второй указатель через setTmpData, а затем измените в первом указателе какую-нибудь запись, после чего выберите ее во втором указателе. Увидите - что она тоже изменилась.
__________________
Возможно сделать все. Вопрос времени
Старый 25.07.2012, 10:06   #6  
AndyD is offline
AndyD
Участник
КОРУС Консалтинг
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
2,560 / 2476 (88) +++++++++
Регистрация: 20.08.2005
А о какой версии Аксаты идет речь?

Помнится, при попытке передать серверную временную таблицу на клиентский курсор с помощью вызова 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()); // табличная переменная будет указывать на серверный временный файл, копирования на клиент не будет
}
Последнее утверждение верно для DAX2009RU7 и выше.
Для более ранних версий, скорее всего, так же верно, но я не проверял

Замечу еще, что 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  
Eldar9x is offline
Eldar9x
MCTS
Аватар для Eldar9x
Oracle
MCBMSS
 
1,064 / 166 (8) ++++++
Регистрация: 29.09.2006
Адрес: Казань
Вот как, оказывается... А как тогда сделать, чтобы таблица на сервере оказалась реально серверной, а не указывающей на тот же файл клиента?

Цитата:
Если табличная переменная находится на противоположной стороне от агргумента, в табличной переменной аргумента не было вставлено данных и в момент вызова функции счетчик ссылок аргумента равен 1, то вызывающая табличная перенная не поменяет своего положения, но файл временной таблицы будет пересоздан.
Будет пересоздан на исходной стороне или будет пересоздан на стороне вызывающей табличной переменной?

Последний раз редактировалось Eldar9x; 25.07.2012 в 12:38.
Старый 25.07.2012, 12:47   #8  
AndyD is offline
AndyD
Участник
КОРУС Консалтинг
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
2,560 / 2476 (88) +++++++++
Регистрация: 20.08.2005
Цитата:
Сообщение от Eldar9x Посмотреть сообщение
Будет пересоздан на исходной стороне или будет пересоздан на стороне вызывающей табличной переменной?
На стороне вызывающей табличной переменной.
Пересоздан в том смысле, что если в табличную пременную ранее вставлялись данные, то после этой операции они будут утеряны
__________________
Axapta v.3.0 sp5 kr2
Старый 25.07.2012, 12:55   #9  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,427 / 1771 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
Цитата:
Сообщение от Eldar9x Посмотреть сообщение
А как тогда сделать, чтобы таблица на сервере оказалась реально серверной, а не указывающей на тот же файл клиента?
"использовать insert_recordset или insert внутри while-цикла"
Старый 25.07.2012, 13:05   #10  
gl00mie is offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,684 / 5788 (200) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
Записей в блоге: 3
Цитата:
Сообщение от Eldar9x Посмотреть сообщение
А как тогда сделать, чтобы таблица на сервере оказалась реально серверной, а не указывающей на тот же файл клиента?
Поиск рулит: Как передать временную таблицу
За это сообщение автора поблагодарили: MikeR (2).
Старый 26.07.2012, 08:55   #11  
vanokh is offline
vanokh
Участник
 
108 / 63 (3) ++++
Регистрация: 23.10.2008
Недавно проводил эксперимент - отлично работает упаковка в контейнер в цикле на сервере + распаковка и копирование через .data() + insert на клиенте. Нужно было обработать до 1млн записей на сервере, сгруппировать и на клиенте вывести в отчет 20-50тыс. Проверял до 100тыс - переносится с сервера на клиент в контейнере без ошибок и выпадений около 5 мин.

Таблица постоянно временная - свойство Temporary = Yes.
AX 2009 SP1 RU7
Старый 26.07.2012, 10:53   #12  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,427 / 1771 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
Не первый раз встречаюсь с реализацией предачи данных через контейнер. И всякий раз не понимаю зачем? Вот например Временная таблица, из контейнера в источник данных.

Разве 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  
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
Цитата:
Сообщение от S.Kuskov Посмотреть сообщение
Не первый раз встречаюсь с реализацией предачи данных через контейнер. И всякий раз не понимаю зачем? Вот например Временная таблица, из контейнера в источник данных.
Ну так в том и смысл - запаковали таблицу в контейнер на одном слое исполнения, потом отправили ее как один параметр (и один RPC-вызов) на другой слой исполнения, там распаковали и обработали. А доступ к временной таблице живущей на другом слое исполнения, требует по одному (а может и больше) RPC на каждую операцию с нею...
Chatiness приложения сильно растет...
За это сообщение автора поблагодарили: S.Kuskov (1).
Старый 26.07.2012, 11:53   #14  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,427 / 1771 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
Ясно...

Да, жалко что нет инструмента копирования целиком табличного буфера без разделения на части или перепаковки.

UPD:
А такого инструмента наверное и не может быть. Ведь наверняка в общем случае буфер временной таблицы хранится фрагментированно совместно с другими данными в куче. И что бы передать его одним куском, этот один кусок сначала нужно собрать, на деле перепаковав табличный буфер в статическую непрерывную структуру вроде контейнера.

Последний раз редактировалось S.Kuskov; 26.07.2012 в 12:09.
Старый 26.07.2012, 12:17   #15  
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
Цитата:
Сообщение от S.Kuskov Посмотреть сообщение
Ясно...

Да, жалко что нет инструмента копирования целиком табличного буфера без разделения на части или перепаковки.

UPD:
А такого инструмента наверное и не может быть. Ведь наверняка в общем случае буфер временной таблицы хранится фрагментированно совместно с другими данными в куче. И что бы передать его одним куском, этот один кусок сначала нужно собрать, на деле перепаковав табличный буфер в статическую непрерывную структуру вроде контейнера.
Тут речь идет скорее не об одном буфере, а о том чтобы все записи таблицы в контейнер запаковать и потом чохом передать. Я для этого делал два метода в global - packTable и unpackTable... Да и дело тут не в памяти, а просто в экономии RPC при передаче параметров...
За это сообщение автора поблагодарили: Logger (2).
Старый 26.07.2012, 12:31   #16  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,427 / 1771 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
Цитата:
Сообщение от fed Посмотреть сообщение
чохом передать
Это я уже понял. Просто хотел уточнить. Для того чтобы чохом передать нужно же и "чохом" хранить? Или не обязательно? Т.е. очень сомнительно, что за один "чох" можно передать, например, динамическую структуру типа Map? Мне почему-то кажется что должно выполнятся условие размещения данных в одном передаваемом куске памяти. Я ошибаюсь?
Старый 26.07.2012, 12:48   #17  
AndyD is offline
AndyD
Участник
КОРУС Консалтинг
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
2,560 / 2476 (88) +++++++++
Регистрация: 20.08.2005
Цитата:
Сообщение от S.Kuskov Посмотреть сообщение
Это я уже понял. Просто хотел уточнить. Для того чтобы чохом передать нужно же и "чохом" хранить? Или не обязательно? Т.е. очень сомнительно, что за один "чох" можно передать, например, динамическую структуру типа Map? Мне почему-то кажется что должно выполнятся условие размещения данных в одном передаваемом куске памяти. Я ошибаюсь?
Так все в кучке и хранится.
Либо в памяти (если не очень много успели записать), либо уже на диске, но все вместе

Только RPC не надо идеализировать
Большие контейнеры тоже будут передавать не целиком за раз, а разбиваться на куски. Соответственно, дополнительных вызовов будет достаточно много.
Но, в любом случае, таких обменов будет меньше, чем при условии передачи по каждой отдельной записи
__________________
Axapta v.3.0 sp5 kr2
Старый 26.07.2012, 13:32   #18  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,427 / 1771 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
Цитата:
Сообщение от AndyD Посмотреть сообщение
Так все в кучке и хранится.
Либо в памяти (если не очень много успели записать), либо уже на диске, но все вместе
Т.е. вы хотите сказать, что под буфер временной таблицы сразу выделяется какой-то фиксированный максимальный размер памяти. Я считал что память под структуры таких размеров должна выделяться по мере необходимости, т.е. динамически. Возможно я немного переоцениваю объём памяти занимаемый временными таблицами.

В любом случае, если бы была реализация копировани буфера временной таблицы на уровне ядра системы, то это бы помогло бы избежать ненужных накладных расходов на переупаковку данных и в тоже время не повысила бы Chattiness
Старый 26.07.2012, 13:52   #19  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,860 / 3109 (111) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
Так по сети передается контейнер ! А это элементарный тип с точки зрения аксапты, похожий на строку. Т.е. под него сразу фиксированный объем памяти выделяется ("чохом" как вы выразились) при приемке по сети, а потом при распаковке из него создается экземпляр мапа из которого уже данные пошагово достаются и кладутся во времянку, но сеть при этом не дергается. Сеть дергается только при передаче контейнера.
Старый 26.07.2012, 14:19   #20  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,427 / 1771 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
Logger, я всё это прекрасно понимаю. Я лишь хотел убедится, что "НЕ элементарные" типы передать за один/два RPC вызова нельзя. Но после сообщения AndyD
Цитата:
Сообщение от AndyD Посмотреть сообщение
Так все в кучке и хранится.
Либо в памяти (если не очень много успели записать), либо уже на диске, но все вместе
хотелось бы убедится ещё и в том как именно хранится буфер временной таблицы в оперативной памяти. Как строка в одном месте или фрагментировано в разных связанных областях? Для общего развития так сказать. Просто когда представляешь себе как это там на самом деле всё происходит многие вещи становятся понятнее. Например почему таки нельзя просто взять и скопирования буфер временной таблицы так же как строку или контейнер?
 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
передача бинарных файлов с клиента на AOS и обратно corvax DAX: Программирование 9 01.04.2014 15:05
Join временной таблицы в запросе yahenz DAX: Программирование 12 24.04.2012 14:59
Display метод временной таблицы выполняется в компании DAT S.Kuskov DAX: Программирование 4 15.04.2011 20:11
Передача временной таблицы в batch DTD DAX: Программирование 10 30.04.2008 13:55
Передача временной таблицы 6apcyk DAX: Программирование 11 09.08.2006 17:32
Опции темы Поиск в этой теме
Поиск в этой теме:

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

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

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

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