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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 26.02.2019, 05:13   #1  
Blog bot is offline
Blog bot
Участник
 
25,459 / 846 (79) +++++++
Регистрация: 28.10.2006
TempDB table populated in CIL
Источник: http://alexvoy.blogspot.com/2019/02/...ed-in-cil.html
==============

We have multiple options to provide additional information to records in grids. Some of them, like display methods, are easy to implement. Some of them, like a temporary table, are not.

Let's consider a scenario when our lovely user wants to see reservation info directly in the transaction grid as filterable columns.





Evidently, we cannot use display methods because they cannot be filterable. Given the way this info calculated behind the curtain, there is no way to create a view to join InventTrans on InventTransItem form. So, the last feasible option is to create a temporary table and join it to the main form data source.

In order to populate this TempDB table (it is not enough to create an InMemory one) as much fast as possible, we have to run the logic in CIL.

The following shows how to work with such tables by passing their physical names.

First, create a TempDB table.



Then add it to the form data source so that it would be outer joined to InventTrans table



and place its Init() method, which links the local buffer with a populated TempDB on the SQL server side.

We also need to init its populating engine and calculate its data at least once when the form opens and maybe later via Refresh button for all or one particular item.

final class FormRun extends ObjectRun
{
wblInventSumFormEngine wblInventSumFormEngine;
}

void init()
{
super();
element.wblInitParameters();
}

private void wblInitParameters()
{
wblInventSumFormEngine = new wblInventSumFormEngine(element);
}

//wblTmpInventSum_DS.Init
public void init()
{
wblTmpInventSum wblTmpInventSumLoc;
wblTmpInventSumLoc.doInsert();
delete_from wblTmpInventSumLoc;
super();
wblTmpInventSum.linkPhysicalTableInstance(wblTmpInventSumLoc);
}

public void run()
{
super();
element.wblRecalcData();
}

public void wblRecalcData(boolean _forCurrentItemOnly = false)
{
wblInvenTransByItemDimView wblInvenTransByItemDimView;

if(_forCurrentItemOnly)
{
wblInventSumFormEngine.parmItemIdCalcFor(InventTrans.ItemId);
wblInventSumFormEngine.run();
}
else
{
wblInventSumFormEngine.parmItemIdCalcFor('');
// todo: uncomment if needed to measure the execution time
//wblInventSumFormEngine.parmShowCalcInfo(true);
startLengthyOperation();
wblInventSumFormEngine.run();
endLengthyOperation();
}
}


Now let's take a look at the populating class. It has parameters for showing elapsed time and run for a particular item id only.


///
/// Populating TempDB tables in CIL
///
///
/// Passing physical table names between CIL and form
///

public class wblInventSumFormEngine
{
// add more data sources to support multiple TempDB tables populating
FormDataSource fdsTmpInventSum;
wblTmpInventSum wblTmpInventSum;
ItemId itemIdCalcFor;
boolean showCalcInfo;
}

///
/// Gets TempDB tables physical names
///
///
/// Container with names
///
///
/// Creates buffers if not exist yet
///
private container getTempTablesNames()
{
if(!wblTmpInventSum.getPhysicalTableName())
{
select firstOnly wblTmpInventSum;
}
return [wblTmpInventSum.getPhysicalTableName()];
}

///
/// Creates new populating engine for a given form
///
///
/// Caller form
///
///
/// Looks for a particular data sources to link TempDB tables
///
public void new(FormRun _formRun = null)
{
Object formObject = _formRun;

if (_formRun)
{
fdsTmpInventSum = _formRun.dataSource(tableId2Name(tableNum(wblTmpInventSum)));
}
}

///
/// To calculate TempDB table for a particular item only
///
///
/// Item id to calculate data
///
///
/// Item id
///
///
/// If empty, then calculate for all items
///
public ItemId parmItemIdCalcFor(ItemId _parm = itemIdCalcFor)
{
itemIdCalcFor = _parm;
return itemIdCalcFor;
}

///
/// Show consumed time to populate TempDB tables
///
///
/// Shows if True
///
public boolean parmShowCalcInfo(boolean _parm = showCalcInfo)
{
showCalcInfo = _parm;
return showCalcInfo;
}

public void run()
{
str wblTmpInventSumTempDBTableName;
// add here more tempDB tables if needed
[wblTmpInventSumTempDBTableName] = this.getTempTablesNames();
[wblTmpInventSumTempDBTableName] = wblInventSumFormEngine::calc([itemIdCalcFor, wblTmpInventSumTempDBTableName, showCalcInfo]);
// push calculated data back to the form data source
if(fdsTmpInventSum)
{
// this assignment works only on the client tier outside of the populating method
fdsTmpInventSum.cursor().linkPhysicalTableInstance(wblTmpInventSum);
fdsTmpInventSum.research();
}
}

///
/// Launcher for CIL
///
///
/// Container with parameters and all TempDB tables physical names to populate
///
///
/// Container with all populated TempDB tables physical names
///
private static server container calc(container _cont)
{
container cont;
XppILExecutePermission xppILExecutePermission;
FromTime startTime = timeNow();
ItemId itemIdCalcFor = conPeek(_cont, 1);
boolean showCalcInfo = conPeek(_cont, 3);

xppILExecutePermission = new XppILExecutePermission();
xppILExecutePermission.assert();

cont = runClassMethodIL(
classStr(wblInventSumFormEngine),
staticMethodStr(wblInventSumFormEngine, calcIL),
_cont
);
CodeAccessPermission::revertAssert();

if(showCalcInfo)
{
info(strFmt("Refreshed for %1 in %2", itemIdCalcFor ? itemIdCalcFor : "all items", timeConsumed(startTime, timeNow())));
}

return cont;
}

///
/// Implements the calculating logic and populating TempDB tables
///
///
/// Container with parameters and all TempDB tables physical names to populate
///
///
/// Container with all populated TempDB tables physical names
private static server container calcIL(container _con)
{
WHSInventReserve whsInventReserve;
wblTmpInventSum wblTmpInventSum;
ItemId itemIdCalcFor = conPeek(_con, 1);
str wblTmpInventSumTempDBTableName = conPeek(_con, 2);
wblInvenTransByItemDimView wblInvenTransByItemDimView;
// Link to an exiting table
wblTmpInventSum.useExistingTempDBTable(wblTmpInventSumTempDBTableName);
// empty existing data
wblInventSumFormEngine::cleanTmpInventSum(wblTmpInventSum, itemIdCalcFor);
/***** Implements the calculating logic here *****/
while select whsInventReserve
join RecId from wblInvenTransByItemDimView
where
(!itemIdCalcFor || whsInventReserve.ItemId == itemIdCalcFor) &&
wblInvenTransByItemDimView.ItemId == whsInventReserve.ItemId &&
wblInvenTransByItemDimView.InventDimId == whsInventReserve.InventDimId
{
wblTmpInventSum.clear();
wblTmpInventSum.Itemid = whsInventReserve.itemId;
wblTmpInventSum.InventDimId = whsInventReserve.InventDimId;
wblTmpInventSum.AvailOrdered = whsInventReserve.AvailOrdered;
wblTmpInventSum.AvailPhysical = min(whsInventReserve.displayPhysAvailUpHierarchy(), whsInventReserve.AvailPhysical);
// here you can add any other method calls to get more info about reservation
wblTmpInventSum.AvailReservDelta = wblTmpInventSum.AvailPhysical - wblTmpInventSum.AvailOrdered;
wblTmpInventSum.insert();
}
// send tables physical names back to the form
return [wblTmpInventSum.getPhysicalTableName()];
}

///
/// Empties the whole table or for given item id only
///
///
/// TempDB table buffer to empty
///
///
/// Item id
///
static private void cleanTmpInventSum(wblTmpInventSum _wblTmpInventSum, ItemId _itemIdCalcFor = '')
{
delete_from _wblTmpInventSum
where
(!_itemIdCalcFor || _wblTmpInventSum.ItemId == _itemIdCalcFor);
}


As you can see the tricky point is to provide tables physical names to CIL and back in calc() and calcIL() methods.

Now you get it.


Do not forget to build CIL and check it in your Development user options.




Источник: http://alexvoy.blogspot.com/2019/02/...ed-in-cil.html
__________________
Расскажите о новых и интересных блогах по Microsoft Dynamics, напишите личное сообщение администратору.
Старый 27.02.2019, 09:31   #2  
trud is offline
trud
Участник
Лучший по профессии 2017
 
1,038 / 1629 (57) ++++++++
Регистрация: 07.06.2003
Записей в блоге: 1
Цитата:
In order to populate this TempDB table (it is not enough to create an InMemory one) as much fast as possible, we have to run the logic in CIL.
Что-то не очень понятна эта фраза, почему CIL в данном случае будет быстрее? Не сравнивали просто с выполнением на сервере?
Ну т.е. в данном случае наверное лучше было бы использовать RecordInsertList или insert_into, если это не упрощенный пример
Старый 01.03.2019, 21:07   #3  
wojzeh is offline
wojzeh
Участник
Аватар для wojzeh
Соотечественники
 
672 / 512 (19) +++++++
Регистрация: 27.04.2006
Адрес: Montreal
Цитата:
Сообщение от trud Посмотреть сообщение
Что-то не очень понятна эта фраза, почему CIL в данном случае будет быстрее? Не сравнивали просто с выполнением на сервере?
Ну т.е. в данном случае наверное лучше было бы использовать RecordInsertList или insert_into, если это не упрощенный пример
это пример того, как передавать временную таблицу при заполнении её в CIL. в данном конкретном случае никаких сложных вычислений не производится.
__________________
Felix nihil admirari
Старый 01.03.2019, 21:45   #4  
ax_mct is offline
ax_mct
Banned
 
2,548 / 1091 (0) ++++++++
Регистрация: 10.10.2005
Адрес: Westlands
Цитата:
In order to populate this TempDB table (it is not enough to create an InMemory one) as much fast as possible, we have to run the logic in CIL.
Стыдно признаться в своей некомпетентности но я не понимаю зачем runClassMethodIL и все такое в контексте AX2012.

То что в батче всегда CIL это я понимаю.
Если у пользователя включена галка "Запускать бизнес-логику в CIL" в параметрах пользователя то я полагаю что все тоже в CIL.

То есть если у пользователя галка не отключена (а эта галка она у всех обычно включена, за исключением тех кому дебажить надо) то так и так будет CIL и не нужно runClassMethodIL.

Где я ошибаюсь?
Старый 01.03.2019, 21:55   #5  
wojzeh is offline
wojzeh
Участник
Аватар для wojzeh
Соотечественники
 
672 / 512 (19) +++++++
Регистрация: 27.04.2006
Адрес: Montreal
Цитата:
Сообщение от ax_mct Посмотреть сообщение
Стыдно признаться в своей некомпетентности но я не понимаю зачем runClassMethodIL и все такое в контексте AX2012.

То что в батче всегда CIL это я понимаю.
Если у пользователя включена галка "Запускать бизнес-логику в CIL" в параметрах пользователя то я полагаю что все тоже в CIL.

То есть если у пользователя галка не отключена (а эта галка она у всех обычно включена, за исключением тех кому дебажить надо) то так и так будет CIL и не нужно runClassMethodIL.

Где я ошибаюсь?
вот норм чувачок объясняет за скоростя https://daxmusings.codecrib.com/2011...fast-lane.html
__________________
Felix nihil admirari
За это сообщение автора поблагодарили: ax_mct (3).
Старый 01.03.2019, 23:41   #6  
ax_mct is offline
ax_mct
Banned
 
2,548 / 1091 (0) ++++++++
Регистрация: 10.10.2005
Адрес: Westlands
Цитата:
Сообщение от wojzeh Посмотреть сообщение
вот норм чувачок объясняет за скоростя https://daxmusings.codecrib.com/2011...fast-lane.html
Не задумывался об этом. Интересный нюанс. Если стэк вызовов (execution path) начинается на клиенте то это не CIL.

Цитата:
In Dynamics AX 2012, X++ can actually run in the .NET CLR. What I've often heard is "X++ running on the server runs in IL". Well, that is somewhat true. But it doesn't mean setting your classes or menu items to "RunOn Server" makes them run in IL.

So what runs in the CLR "automatically"? Well, any execution path that starts on the server definitely does.
...
So does that mean code started from the AX client never runs as IL, even when it's set to run on the server tier? Well, not automagically.
Старый 01.03.2019, 23:43   #7  
wojzeh is offline
wojzeh
Участник
Аватар для wojzeh
Соотечественники
 
672 / 512 (19) +++++++
Регистрация: 27.04.2006
Адрес: Montreal
Цитата:
Сообщение от ax_mct Посмотреть сообщение
Не задумывался об этом. Интересный нюанс. Если стэк вызовов (execution path) начинается на клиенте то это не CIL.
собсно, пост не о силе, а о том, как перехоботнуть временную таблицу в этот ад и обратно пользователю
__________________
Felix nihil admirari
Старый 01.03.2019, 23:46   #8  
ax_mct is offline
ax_mct
Banned
 
2,548 / 1091 (0) ++++++++
Регистрация: 10.10.2005
Адрес: Westlands
Цитата:
Сообщение от wojzeh Посмотреть сообщение
собсно, пост не о силе, а о том, как перехоботнуть временную таблицу в этот ад и обратно пользователю
Для меня о силе У меня есть тяжелые операции начинающиеся с формы. Скажу клиенту что могу ускорить! Как-то совсем упустил этот момент с CIL.
Старый 02.03.2019, 06:04   #9  
trud is offline
trud
Участник
Лучший по профессии 2017
 
1,038 / 1629 (57) ++++++++
Регистрация: 07.06.2003
Записей в блоге: 1
Цитата:
Сообщение от wojzeh Посмотреть сообщение
собсно, пост не о силе, а о том, как перехоботнуть временную таблицу в этот ад и обратно пользователю
Так а какая цель то в этом действе? В ряде случаев в CIL временные таблицы будут создаваться медленнее чем в обычном режиме(т.е. это известная ошибка когда начинает тормозить система при отключении ключей конфигурации), я правда не знаю насколько это применимо здесь
Старый 05.03.2019, 18:23   #10  
wojzeh is offline
wojzeh
Участник
Аватар для wojzeh
Соотечественники
 
672 / 512 (19) +++++++
Регистрация: 27.04.2006
Адрес: Montreal
цель в том, чтоб заполнять временную таблицу в CIL, знать, как это правильно сделать, когда потребуется (в том оставшемся "ряде случаев", когда создавать их будет быстрее, чем в обычном режиме)
__________________
Felix nihil admirari
За это сообщение автора поблагодарили: trud (5).
Теги
cil

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
TempDB table on a form with multiple updates Blog bot DAX Blogs 0 10.03.2018 00:14
saurav-nav: NAV 2018 - Lots of New Objects! Blog bot NAV: Blogs 0 04.12.2017 10:11
wiki.dynamicsbook: Changes Made in Navision Attain 3.60 Blog bot Dynamics CRM: Blogs 0 02.09.2008 13:23
wiki.dynamicsbook: Changes Made in Navision Attain 3.01B Blog bot Dynamics CRM: Blogs 0 21.08.2008 20:43
wiki.dynamicsbook: Changes Made in Navision Attain 301 Blog bot Dynamics CRM: Blogs 0 19.08.2008 13:44
Опции темы Поиск в этой теме
Поиск в этой теме:

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

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

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

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