<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-1201535659745738271</id><updated>2011-12-14T14:52:50.420+01:00</updated><category term='RunBase'/><category term='disclaimer'/><category term='CLR'/><category term='SQL'/><category term='documentation'/><category term='client'/><category term='bug'/><category term='xRefs'/><category term='client server'/><category term='AX 2009'/><category term='intrinsic functions'/><category term='unit tests'/><category term='VS 2010'/><category term='UI'/><category term='IDE'/><category term='query'/><category term='X++ editor'/><category term='grid'/><category term='data modeling'/><category term='test'/><category term='inheritance'/><category term='UTCDateTime'/><category term='union'/><category term='navigation methods'/><category term='layers'/><category term='best practice'/><category term='attributes'/><category term='QnA'/><category term='Macro'/><category term='hotkey'/><category term='forms'/><category term='app'/><category term='Global class'/><category term='performance'/><category term='services'/><category term='AOT'/><category term='useless'/><category term='WinAPI'/><category term='intellisense'/><category term='Inventory dimensions'/><category term='virtual companies'/><category term='database'/><category term='debug'/><category term='table'/><category term='AX 2012'/><category term='reports'/><category term='AxUtil'/><category term='wizard'/><category term='tool'/><category term='AIF'/><category term='models'/><category term='CIL'/><category term='labels'/><category term='temporary table'/><category term='DateTimeUtil'/><category term='X++'/><category term='MenuItem'/><category term='Label editor'/><category term='unit of work'/><category term='feature'/><category term='RegExp'/><category term='WCF'/><category term='kernel'/><category term='index'/><category term='navigation pane'/><category term='exception'/><category term='dev'/><category term='metadata'/><category term='compiler'/><title type='text'>Dynamics AX Daily</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>97</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-8083954448647569699</id><published>2020-05-05T22:43:00.000+02:00</published><updated>2011-05-05T22:49:38.685+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='disclaimer'/><category scheme='http://www.blogger.com/atom/ns#' term='QnA'/><title type='text'>Collaboration request</title><content type='html'>I strongly believe that the blog content consists of two equally important parts – author's input (through the posts) and readers' input (through the comments). &lt;br /&gt;And so I decided to try to boost the second part a little bit and I need your help here.&lt;br /&gt;&lt;br /&gt;This post will stay on top since now and I am asking you to write in comments to this post anything you will be interested to read about in this blog. &lt;br /&gt;It can be a request to explain some AX 2012 feature, suggestion of the topic\tip\trick that might be interesting to others, bug report, … basically anything. And I will be replying to that with posts.&lt;br /&gt;&lt;br /&gt;And I would also like to welcome you to comment\ask questions\start discussions in all other posts as well.&lt;br /&gt;&lt;br /&gt;Thanks!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-8083954448647569699?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/8083954448647569699/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2011/05/collaboration-request.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/8083954448647569699'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/8083954448647569699'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2011/05/collaboration-request.html' title='Collaboration request'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-4022687766244567914</id><published>2011-05-13T23:14:00.001+02:00</published><updated>2011-05-13T23:18:17.127+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='VS 2010'/><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='debug'/><category scheme='http://www.blogger.com/atom/ns#' term='CIL'/><category scheme='http://www.blogger.com/atom/ns#' term='AX 2012'/><title type='text'>Debugging managed code in AX 2012</title><content type='html'>Since a lot of X++ code is now &lt;a href="http://axdaily.blogspot.com/2011/04/x-can-be-compiled-to-cil-in-ax-2012.html"&gt;executed in CLR&lt;/a&gt; there should be a possibility to debug it. The standard AX debugger cannot help here since it is capable of debugging interpreted code only. However, Visual Studio 2010 can do the job.&lt;br /&gt;There are few steps needed to be able to debug managed X++ execution using VS:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Breakpoints should be enabled on server (in AOS configuration).&lt;/li&gt;&lt;li&gt;Visual Studio should be started with elevated permissions (run as administrator).&lt;/li&gt;&lt;li&gt;Visual Studio should be attached to Ax32Serv.exe process (AOS process).&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;After that you can locate the source code and place the breakpoint. This can be done either using &lt;a href="http://axdaily.blogspot.com/2011/05/visual-studio-tools-for-ax-2012.html"&gt;Application Explorer&lt;/a&gt;, or by opening .xpp source file directly from the [AX server path]\bin\XppIL\Source folder. Each method of each class or table has a separate .xpp file  that is named [ClassName].[MethodName].xpp.&lt;br /&gt;&lt;br /&gt;And that’s it. Now the debugging will happen is visual studio. Call stack, watches, etc. are also available.&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/-lFQMGlCMI4I/Tc2fkE7ChOI/AAAAAAAAFPo/EsQ5RLvM_7c/s1600/vsdbg1.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 210px;" src="http://2.bp.blogspot.com/-lFQMGlCMI4I/Tc2fkE7ChOI/AAAAAAAAFPo/EsQ5RLvM_7c/s400/vsdbg1.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5606312553291613410" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-4022687766244567914?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/4022687766244567914/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2011/05/debugging-managed-code-in-ax-2012.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/4022687766244567914'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/4022687766244567914'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2011/05/debugging-managed-code-in-ax-2012.html' title='Debugging managed code in AX 2012'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-lFQMGlCMI4I/Tc2fkE7ChOI/AAAAAAAAFPo/EsQ5RLvM_7c/s72-c/vsdbg1.png' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-8214990766284082294</id><published>2011-05-10T23:56:00.003+02:00</published><updated>2011-05-11T00:01:01.607+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='VS 2010'/><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='AOT'/><category scheme='http://www.blogger.com/atom/ns#' term='AX 2012'/><title type='text'>Visual studio tools for AX 2012</title><content type='html'>Now it became really easy to develop managed components for AX. &lt;br /&gt;In order to do that you’ll need Visual Studio 2010 and Visual Studio Tools for AX 2012.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-ENRpnnHUTmk/Tcm0uEbrMyI/AAAAAAAAFPA/4dg-y4fwdVc/s1600/vstools1.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 384px;" src="http://3.bp.blogspot.com/-ENRpnnHUTmk/Tcm0uEbrMyI/AAAAAAAAFPA/4dg-y4fwdVc/s400/vstools1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5605209914796094242" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The first tool to mention is, of course, Application Explorer. It contains elements from AOT  (and it actually looks pretty much like AOT) and allows to perform some operations with them. For example, it is possible to open projects or SSRS reports stored in AOT in the same visual studio instance just by clicking edit on project node in application explorer.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-0mjdHuRF7Ms/Tcm0uV7JKLI/AAAAAAAAFPI/QrZZ9ou_Q0E/s1600/vstools2.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 311px; height: 400px;" src="http://2.bp.blogspot.com/-0mjdHuRF7Ms/Tcm0uV7JKLI/AAAAAAAAFPI/QrZZ9ou_Q0E/s400/vstools2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5605209919491483826" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Application Explorer also allows to generate proxies for AX tables, classes, enums and add them to the project. Just by dragging them from application explorer to solution explorer.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/--gv4Pli6xU0/Tcm0uhWdc6I/AAAAAAAAFPY/uSmdxbFgq-g/s1600/vstools4.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 197px;" src="http://3.bp.blogspot.com/--gv4Pli6xU0/Tcm0uhWdc6I/AAAAAAAAFPY/uSmdxbFgq-g/s400/vstools4.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5605209922558849954" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;It is also very important to mention that VS projects can now be stored in the AOT. That is convenient since they can be included into models, as well as all other AOT objects and thus packaged\deployed easily.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-Hl2uUyLkTDU/Tcm0u1MY4LI/AAAAAAAAFPg/omCJduLABIM/s1600/vstools5.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 272px; height: 120px;" src="http://3.bp.blogspot.com/-Hl2uUyLkTDU/Tcm0u1MY4LI/AAAAAAAAFPg/omCJduLABIM/s400/vstools5.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5605209927885316274" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Project can be added to the AOT from the Visual Studio directly.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-ub-mDfNDWQk/Tcm0uQL_YzI/AAAAAAAAFPQ/-HcQDP9qQFI/s1600/vstools3.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 346px; height: 400px;" src="http://4.bp.blogspot.com/-ub-mDfNDWQk/Tcm0uQL_YzI/AAAAAAAAFPQ/-HcQDP9qQFI/s400/vstools3.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5605209917951533874" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-8214990766284082294?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/8214990766284082294/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2011/05/visual-studio-tools-for-ax-2012.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/8214990766284082294'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/8214990766284082294'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2011/05/visual-studio-tools-for-ax-2012.html' title='Visual studio tools for AX 2012'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-ENRpnnHUTmk/Tcm0uEbrMyI/AAAAAAAAFPA/4dg-y4fwdVc/s72-c/vstools1.png' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-1473474231613911717</id><published>2011-05-04T20:57:00.004+02:00</published><updated>2011-05-04T21:18:31.724+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='data modeling'/><category scheme='http://www.blogger.com/atom/ns#' term='unit of work'/><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='navigation methods'/><category scheme='http://www.blogger.com/atom/ns#' term='table'/><category scheme='http://www.blogger.com/atom/ns#' term='AX 2012'/><title type='text'>Unit of Work</title><content type='html'>After the &lt;a href="http://axdaily.blogspot.com/2011/05/surrogate-keys-in-ax-2012.html"&gt;post&lt;/a&gt; about surrogate keys I was asked the following question:&lt;br /&gt;&lt;i&gt;There is the following problem with using surrogate keys.&lt;br /&gt;A record gets RecId value at the moment it is inserted into the database. What if we are doing bulk insert of a journal with many lines and the journal header contains some totals calculated based on its lines. It is impossible to insert lines before header since the value of the journal's surrogate key is unknown. But that would be so convenient because otherwise the header should be inserted first, then the lines and then the header should be updated with the calculated totals.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;The answer is – use &lt;a href="http://martinfowler.com/eaaCatalog/unitOfWork.html"&gt;Unit of Work&lt;/a&gt;. It allows to perform create, update and delete operations without worrying about the order of those and without a need to specify surrogate key values. It will all be done automatically in the kernel!&lt;br /&gt;&lt;br /&gt;Example:&lt;br /&gt;Let we have the following tables:&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/-fqWSHt4UbJQ/TcGiNiZJgPI/AAAAAAAAFOg/2gZ7auIhLuI/s1600/uow1.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 388px; height: 358px;" src="http://3.bp.blogspot.com/-fqWSHt4UbJQ/TcGiNiZJgPI/AAAAAAAAFOg/2gZ7auIhLuI/s400/uow1.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5602937764879892722" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The following job will insert the journal header with calculated totals and 10 lines. Note, that there is no place where surrogate keys are mentioned in the code. Business data only.&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/-cleG-dUI_jY/TcGiN0Ap4hI/AAAAAAAAFOw/1bLLX2r-d-U/s1600/uow3.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 390px; height: 393px;" src="http://4.bp.blogspot.com/-cleG-dUI_jY/TcGiN0Ap4hI/AAAAAAAAFOw/1bLLX2r-d-U/s400/uow3.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5602937769608995346" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;And here is the result.&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/-HQJYumZfGT0/TcGiN-2OdpI/AAAAAAAAFOo/XPzfD6OpAkk/s1600/uow2.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 277px;" src="http://1.bp.blogspot.com/-HQJYumZfGT0/TcGiN-2OdpI/AAAAAAAAFOo/XPzfD6OpAkk/s400/uow2.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5602937772518045330" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Some more details about the unit of work feature:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;All database operations happen only when saveChanges() method is invoked.&lt;/li&gt;&lt;li&gt;UnitOfWork class has insertOnSaveChanges(), updateOnSaveChanges() and deleteOnSaveChanges() methods for CUD operations.&lt;/li&gt;&lt;li&gt;Surrogate keys can be propagated automatically to related records if buffers are linked via navigation methods (AJournalLine.header() method in the example). Navigation methods can be created automatically from relations. I’ll write a separate post about them.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;And the last but not least. AX client has the great support of the unit of work as well. This means that form datasources can be grouped into a unit of work, so all the benefits of simultaneous commit and surrogate key propagation will be available on forms. There are a lot of possibilities and tricks there, so this topic worth one or more dedicated posts as well.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-1473474231613911717?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/1473474231613911717/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2011/05/unit-of-work.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/1473474231613911717'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/1473474231613911717'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2011/05/unit-of-work.html' title='Unit of Work'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-fqWSHt4UbJQ/TcGiNiZJgPI/AAAAAAAAFOg/2gZ7auIhLuI/s72-c/uow1.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-6426309964994056428</id><published>2011-05-03T22:43:00.003+02:00</published><updated>2011-05-03T22:52:48.766+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='data modeling'/><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='forms'/><category scheme='http://www.blogger.com/atom/ns#' term='index'/><category scheme='http://www.blogger.com/atom/ns#' term='best practice'/><category scheme='http://www.blogger.com/atom/ns#' term='table'/><category scheme='http://www.blogger.com/atom/ns#' term='AX 2012'/><title type='text'>Surrogate keys in AX 2012</title><content type='html'>Data modeling enhancements were prioritized really high in AX 2012. I already mentioned one earlier – &lt;a href="http://axdaily.blogspot.com/2011/04/table-inheritance.html"&gt;table inheritance&lt;/a&gt;, but there are a lot of other important features about data modeling.&lt;br /&gt;&lt;br /&gt;One such feature is the support of &lt;a href="http://en.wikipedia.org/wiki/Surrogate_key"&gt;surrogate keys&lt;/a&gt;. Surrogate keys recommended themselves as a very good solution for complex databases because of their beneficial properties, like immutability, robustness to redesign and performance. And now this best practice is coming to AX. It is the recommendation for AX 2012 to use surrogate keys for all new tables, unless there is a good reason not to do so. &lt;br /&gt;&lt;br /&gt;Actually, previous versions of AX already have surrogates – RecIds. And it was possible to introduce surrogate key just by setting CreateRecIdIndex table property to Yes. But there is a problem with the inconvenience of working with surrogates in the UI. Imagine InventTable using surrogate key and all other tables that have relations to InventTable using its surrogate key as a foreign key. Then on any form where ItemId should be displayed (let’s say on the SalesTable) an extra join to InventTable will be needed to fetch the ItemId. And what if user can change the item? Then even more custom logic is needed to resolve the entered ItemId to the corresponding surrogate key value and write it to the SalesLine.&lt;br /&gt;&lt;br /&gt;This inconvenience actually was a showstopper. But not anymore. AX 2012 got kernel support for surrogate key substitution. And not only in forms, but in Axd document services and even in the debugger.&lt;br /&gt;&lt;br /&gt;Let me show an example of how it works:&lt;br /&gt;UnitOfMeasure table uses surrogate key as a primary key. However, the user-friendly identifier of the UnitOfMeasure table records is the UnitOfMeasureSymbol field. This field is a part of the SymbolIdx index, which is specified as a replacement key on the UnitOfMeasure table. &lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-hTmAislXhJI/TcBphcK5wyI/AAAAAAAAFNc/4fiZl21gyLk/s1600/sknk1.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 292px;" src="http://1.bp.blogspot.com/-hTmAislXhJI/TcBphcK5wyI/AAAAAAAAFNc/4fiZl21gyLk/s400/sknk1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5602593959667417890" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This setup basically means that surrogate key values (RecIds) of the UnitOfMeasure table records will be automatically substituted in the UI with the replacement key values (UnitOfMeasureSymbols).&lt;br /&gt;UnitOfMeasureConversion table has a relation to the UnitOfMeasue table through the surrogate key.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-P8h-JWR6u_E/TcBphxVOmlI/AAAAAAAAFNs/M9OBwnvI-OU/s1600/sknk3.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 177px;" src="http://4.bp.blogspot.com/-P8h-JWR6u_E/TcBphxVOmlI/AAAAAAAAFNs/M9OBwnvI-OU/s400/sknk3.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5602593965347871314" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;As you can see, on the UnitOfMeasureConversion form there are only UnitOfMeasureConversion datasources. And you can notice new ReferenceGroup control which is bound to the FromUnitOfMeasure field (which contains surrogate values).&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-SWw_i5cs8p4/TcBphpHvYNI/AAAAAAAAFNk/11UQ8adwLNs/s1600/sdnk2.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 224px;" src="http://4.bp.blogspot.com/-SWw_i5cs8p4/TcBphpHvYNI/AAAAAAAAFNk/11UQ8adwLNs/s400/sdnk2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5602593963143815378" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;And in the UI it will look just like UnitOfMeasureSymbol field is shown instead. And it can also be modified and that will be handled automatically, without a single line of code.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-5JnO3AiKsSM/TcBpiQkjoPI/AAAAAAAAFN0/XoeNDLoYpzk/s1600/sknk4.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 140px;" src="http://3.bp.blogspot.com/-5JnO3AiKsSM/TcBpiQkjoPI/AAAAAAAAFN0/XoeNDLoYpzk/s400/sknk4.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5602593973733662962" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Actually ReferenceGroup control has much more interesting capabilities and thus deserves a separate post.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-6426309964994056428?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/6426309964994056428/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2011/05/surrogate-keys-in-ax-2012.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/6426309964994056428'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/6426309964994056428'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2011/05/surrogate-keys-in-ax-2012.html' title='Surrogate keys in AX 2012'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-hTmAislXhJI/TcBphcK5wyI/AAAAAAAAFNc/4fiZl21gyLk/s72-c/sknk1.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-5716886940644191906</id><published>2011-05-02T23:29:00.003+02:00</published><updated>2011-05-02T23:43:17.943+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='temporary table'/><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL'/><category scheme='http://www.blogger.com/atom/ns#' term='AX 2012'/><title type='text'>SQL temporary tables in AX 2012</title><content type='html'>In AX 2012 a new type of tables was introduced. &lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-g3imF-MPFzU/Tb8lDBOIFqI/AAAAAAAAFNU/VqGFaMBwh14/s1600/tempdb1.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 336px; height: 73px;" src="http://2.bp.blogspot.com/-g3imF-MPFzU/Tb8lDBOIFqI/AAAAAAAAFNU/VqGFaMBwh14/s400/tempdb1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5602237195269707426" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;In addition to Regular (permanent) tables and InMemory tables (known as temporary tables in previous versions of AX) we have got TempDB tables - SQL server temporary tables.&lt;br /&gt;&lt;br /&gt;I believe thit is the feature that many people expected for a long time. TempDB tables utilize the power of SQL tables - full support of joins, aggregation, indexes, all with great performance, but in the same time they have almost the same scoping mechanism as InMemory temporary tables have. &lt;br /&gt;That simplifies developer's life significantly. There is no more need to be aware of tricks like &lt;a href="http://axdaily.blogspot.com/2010/02/temporary-table-residing-tier.html"&gt;this&lt;/a&gt; or like &lt;a href="http://axatluegisdorf.blogspot.com/2010/01/join-queries-with-temporary-tables.html"&gt;this&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-5716886940644191906?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/5716886940644191906/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2011/05/sql-temporary-tables-in-ax-2012.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/5716886940644191906'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/5716886940644191906'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2011/05/sql-temporary-tables-in-ax-2012.html' title='SQL temporary tables in AX 2012'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-g3imF-MPFzU/Tb8lDBOIFqI/AAAAAAAAFNU/VqGFaMBwh14/s72-c/tempdb1.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-1201699656735878224</id><published>2011-04-29T22:35:00.003+02:00</published><updated>2011-04-29T22:48:31.484+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='services'/><category scheme='http://www.blogger.com/atom/ns#' term='AIF'/><category scheme='http://www.blogger.com/atom/ns#' term='WCF'/><category scheme='http://www.blogger.com/atom/ns#' term='AX 2012'/><title type='text'>WCF services in AX 2012</title><content type='html'>Since &lt;a href="http://axdaily.blogspot.com/2011/04/x-can-be-compiled-to-cil-in-ax-2012.html"&gt;X++ can be compiled to CIL in AX 2012&lt;/a&gt; it became possible to change the way how X++ services are implemented.&lt;br /&gt;Now all X++ services are &lt;a href="http://msdn.microsoft.com/en-us/netframework/aa663324"&gt;WCF&lt;/a&gt; services and they are executed in the WCF runtime hosted on the AOS.&lt;br /&gt;It is really hard to overestimate the benefits of this feature. Let me mention here just a few of those:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Every service has now &lt;a href="http://www.w3.org/TR/wsdl"&gt;WSDL&lt;/a&gt; definition. This means that it is extremely easy to generate proxy classes for those services for external clients using standard tools like &lt;a href="http://msdn.microsoft.com/en-us/library/aa347733.aspx"&gt;svcutil.exe&lt;/a&gt; (add service reference in VS) or &lt;a href="http://ws.apache.org/muse/docs/2.0.0/manual/tools/wsdl2java.html"&gt;WSDL2java&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;There is a new protocol to communicate with AOS now – WCF, in addition to the regular RPC.&lt;/li&gt;&lt;li&gt;Seamless integration with many applications\technologies, like MSMQ or BizTalk.&lt;/li&gt;&lt;li&gt;Simple and standard security model.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;It is really nice to see that powerful and standardized technologies are coming to AX.&lt;br /&gt;&lt;br /&gt;And one more thing to mention. In AX 2012 all AIF and services concepts were simplified significantly. Just look how AIF menu section was changed:&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/-qvdFFwmtscc/Tbshh1YjsZI/AAAAAAAAFM8/YZde3HtWxLc/s1600/wcf2.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 149px;" src="http://4.bp.blogspot.com/-qvdFFwmtscc/Tbshh1YjsZI/AAAAAAAAFM8/YZde3HtWxLc/s400/wcf2.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5601107426714825106" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;And most of the setup can be done now just from this very nice form:&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/-Fr3P2D4oFco/TbshhtSHyII/AAAAAAAAFM0/AC2WBv-17Dw/s1600/wcf1.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 202px;" src="http://3.bp.blogspot.com/-Fr3P2D4oFco/TbshhtSHyII/AAAAAAAAFM0/AC2WBv-17Dw/s400/wcf1.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5601107424540346498" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-1201699656735878224?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/1201699656735878224/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2011/04/wcf-services-in-ax-2012.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/1201699656735878224'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/1201699656735878224'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2011/04/wcf-services-in-ax-2012.html' title='WCF services in AX 2012'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-qvdFFwmtscc/Tbshh1YjsZI/AAAAAAAAFM8/YZde3HtWxLc/s72-c/wcf2.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-8477690170765802122</id><published>2011-04-29T00:00:00.005+02:00</published><updated>2011-04-29T00:07:38.927+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='forms'/><category scheme='http://www.blogger.com/atom/ns#' term='UI'/><category scheme='http://www.blogger.com/atom/ns#' term='AX 2012'/><title type='text'>AX 2012 user interface and style property</title><content type='html'>In AX 2012 user interface has been changed significantly. AX looks now much more modern and I would say, Office 2010-like.&lt;br /&gt;However there were not so many new controls added (I will write about each of them separately). The variety of different visual experiences can be achieved now with the new extremely cool property of form controls – Style. &lt;br /&gt;This property defines general look &amp; feel of the control, which can be then customized with other properties.&lt;br /&gt;&lt;br /&gt;For example, Tab control has the following styles:&lt;br /&gt;FastTabs&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-TBSHX6bBI-k/Tbnj0Hr1zqI/AAAAAAAAFME/vQVx2u59rvI/s1600/newUI1.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 156px;" src="http://1.bp.blogspot.com/-TBSHX6bBI-k/Tbnj0Hr1zqI/AAAAAAAAFME/vQVx2u59rvI/s400/newUI1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5600758096167554722" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;VerticalTabs&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-jmPEbWk-sW4/Tbnj0eoe-mI/AAAAAAAAFMM/_eXlwfJt6Xc/s1600/newUI2.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 317px;" src="http://3.bp.blogspot.com/-jmPEbWk-sW4/Tbnj0eoe-mI/AAAAAAAAFMM/_eXlwfJt6Xc/s400/newUI2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5600758102327491170" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;IndexTabs&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-13LYjHNl6qg/Tbnj5L33MiI/AAAAAAAAFMs/5DObwDV_rtc/s1600/newUI6.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 61px;" src="http://3.bp.blogspot.com/-13LYjHNl6qg/Tbnj5L33MiI/AAAAAAAAFMs/5DObwDV_rtc/s400/newUI6.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5600758183191065122" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;And regular AX 2009-like tabs, by the way, – Tabs.&lt;br /&gt;&lt;br /&gt;Action pane can be with Standard or Strip style.&lt;br /&gt;Standard&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-V96l29RVEgA/Tbnj1fMHUgI/AAAAAAAAFMk/KYXeqyagAjQ/s1600/newUI5.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 47px;" src="http://4.bp.blogspot.com/-V96l29RVEgA/Tbnj1fMHUgI/AAAAAAAAFMk/KYXeqyagAjQ/s400/newUI5.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5600758119656804866" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Strip&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-54HTbk6gsEI/Tbnj0iWqzMI/AAAAAAAAFMU/kXXNtkaIGoY/s1600/newUI3.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 295px; height: 37px;" src="http://4.bp.blogspot.com/-54HTbk6gsEI/Tbnj0iWqzMI/AAAAAAAAFMU/kXXNtkaIGoY/s400/newUI3.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5600758103326510274" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Form design has a lot of styles, like ListPage, DetailsFormMaster, Dialog, SimpleList, Lookup and others.&lt;br /&gt;DropDialog&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-GzeC_revL48/Tbnj1KEpQaI/AAAAAAAAFMc/KuRp_QlpiQY/s1600/newUI4.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 138px;" src="http://1.bp.blogspot.com/-GzeC_revL48/Tbnj1KEpQaI/AAAAAAAAFMc/KuRp_QlpiQY/s400/newUI4.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5600758113988329890" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Many other controls have style property as well. This property really helps to change the visual appearance of control in the very easy way.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-8477690170765802122?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/8477690170765802122/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2011/04/ax-2012-user-interface-and-style.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/8477690170765802122'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/8477690170765802122'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2011/04/ax-2012-user-interface-and-style.html' title='AX 2012 user interface and style property'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-TBSHX6bBI-k/Tbnj0Hr1zqI/AAAAAAAAFME/vQVx2u59rvI/s72-c/newUI1.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-4786461489219394947</id><published>2011-04-27T21:05:00.003+02:00</published><updated>2011-04-28T10:01:30.199+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='metadata'/><category scheme='http://www.blogger.com/atom/ns#' term='models'/><category scheme='http://www.blogger.com/atom/ns#' term='AxUtil'/><category scheme='http://www.blogger.com/atom/ns#' term='AOT'/><category scheme='http://www.blogger.com/atom/ns#' term='AX 2012'/><title type='text'>Models in AX 2012</title><content type='html'>There is a new concept in AX 2012 called model. Model is a container of metadata elements, like AOT objects, sources, label files, etc. The main benefit of models is the possibility to easily export and import them from\to AX. This means that model is a very convenient deployment mechanism – you can develop your feature in a separate model, export it and then deploy to production environment or distribute it to your customers.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-4jQLDphRgdg/TbhwRzQdJXI/AAAAAAAAFL0/HMAiW9CDLqc/s1600/models1.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 189px;" src="http://3.bp.blogspot.com/-4jQLDphRgdg/TbhwRzQdJXI/AAAAAAAAFL0/HMAiW9CDLqc/s400/models1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5600349587754526066" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;New command line tool AxUtil.exe is shipped together with AX 2012 and allows to perform operations with models in a very easy way.&lt;br /&gt;&lt;br /&gt;AX development workspace supports models very well. It is possible to see to which model any AOT element belongs to, move AOT elements between models, create project from model, etc. AX version control system integration has model support as well. For example, it is possible to store xpos for different models in different folders in the file system.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-0tIKXSyrsXA/TbhwSCmdQZI/AAAAAAAAFL8/dkVhb2ca8qE/s1600/models2.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 352px; height: 292px;" src="http://4.bp.blogspot.com/-0tIKXSyrsXA/TbhwSCmdQZI/AAAAAAAAFL8/dkVhb2ca8qE/s400/models2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5600349591873339794" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;You can read more about models in the great series of posts by mfp:&lt;br /&gt;&lt;a href="http://blogs.msdn.com/b/mfp/archive/2009/09/23/introducing-ax-models-part-1.aspx"&gt;AX models – Part 1 – Deploying models&lt;/a&gt;&lt;br /&gt;&lt;a href="http://blogs.msdn.com/b/mfp/archive/2009/09/29/introducing-ax-models-part-2.aspx"&gt;AX models – Part 2 – Manifest and signing&lt;/a&gt;&lt;br /&gt;&lt;a href="http://blogs.msdn.com/b/mfp/archive/2009/10/08/introducing-ax-models-part-3.aspx"&gt;AX models – Part 3 – Multiple models per layer&lt;/a&gt;&lt;br /&gt;&lt;a href="http://blogs.msdn.com/b/mfp/archive/2009/11/25/ax-models-part-4-working-with-models-inside-morphx.aspx"&gt;AX models – Part 4 – Working with models inside MorphX&lt;/a&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-4786461489219394947?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/4786461489219394947/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2011/04/models-in-ax-2012.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/4786461489219394947'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/4786461489219394947'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2011/04/models-in-ax-2012.html' title='Models in AX 2012'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-4jQLDphRgdg/TbhwRzQdJXI/AAAAAAAAFL0/HMAiW9CDLqc/s72-c/models1.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-2432635951179174592</id><published>2011-04-26T21:37:00.003+02:00</published><updated>2011-04-26T21:44:07.963+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='inheritance'/><category scheme='http://www.blogger.com/atom/ns#' term='forms'/><category scheme='http://www.blogger.com/atom/ns#' term='table'/><category scheme='http://www.blogger.com/atom/ns#' term='client'/><category scheme='http://www.blogger.com/atom/ns#' term='AX 2012'/><title type='text'>Table inheritance</title><content type='html'>AX 2012 supports table inheritance.&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/-3CKixB8idVs/Tbcfb_rR8-I/AAAAAAAAFLQ/WUZYyz9R_Nw/s1600/tableinheritance1.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 219px;" src="http://2.bp.blogspot.com/-3CKixB8idVs/Tbcfb_rR8-I/AAAAAAAAFLQ/WUZYyz9R_Nw/s400/tableinheritance1.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5599979227468395490" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Table inheritance is controlled by the following properties:&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/-C_CDnpcD5Gs/Tbcfcfc_wAI/AAAAAAAAFLo/Tc10R23J-Cg/s1600/tableinheritance4.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 319px; height: 73px;" src="http://2.bp.blogspot.com/-C_CDnpcD5Gs/Tbcfcfc_wAI/AAAAAAAAFLo/Tc10R23J-Cg/s400/tableinheritance4.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5599979235998416898" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;SupportInheritance – specifies if a table is a part of a hierarchy.&lt;/li&gt;&lt;li&gt;InstanceRelationType – specifies the field that is used as a type discriminator. TableIds of concrete types are used as values of the InstanceRelationType field.&lt;/li&gt;&lt;li&gt;Abstact – specifies if a table is abstract. Tables without derived tables cannot be abstract.&lt;/li&gt;&lt;li&gt;Extends – specifies table’s parent.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;Polymorphism is supported for table methods. All tables instance methods are virtual.&lt;br /&gt;&lt;br /&gt;There is also client support for table hierarchies. Whenever a table that has derived tables is added on a form as a datasource, all its children are added under the derived datasources node. Fields from derived datasources can be bound to form controls and derived datasources can be used in form query construction, e.g. other datasources can be joined to derived ones.&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/-bOaoiKYlHTg/TbcfbzTPCpI/AAAAAAAAFLY/xgeNecHcW_E/s1600/tableinheritance2.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 345px; height: 256px;" src="http://4.bp.blogspot.com/-bOaoiKYlHTg/TbcfbzTPCpI/AAAAAAAAFLY/xgeNecHcW_E/s400/tableinheritance2.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5599979224146315922" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Whenever a “New record” action is invoked on a form control that is bound to an abstract table, the following dialog will be presented to user where it is possible to select the concrete type of the record being created.&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/-jzTR2NQgDqs/Tbcfb9Y8GjI/AAAAAAAAFLg/7hy8spvJl3o/s1600/tableinheritance3.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 343px; height: 134px;" src="http://1.bp.blogspot.com/-jzTR2NQgDqs/Tbcfb9Y8GjI/AAAAAAAAFLg/7hy8spvJl3o/s400/tableinheritance3.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5599979226854595122" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-2432635951179174592?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/2432635951179174592/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2011/04/table-inheritance.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/2432635951179174592'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/2432635951179174592'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2011/04/table-inheritance.html' title='Table inheritance'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-3CKixB8idVs/Tbcfb_rR8-I/AAAAAAAAFLQ/WUZYyz9R_Nw/s72-c/tableinheritance1.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-4645057542260166489</id><published>2011-04-22T20:47:00.003+02:00</published><updated>2011-04-22T21:06:59.659+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='attributes'/><category scheme='http://www.blogger.com/atom/ns#' term='AX 2012'/><title type='text'>X++ attributes</title><content type='html'>AX 2012 supports &lt;a href="http://msdn.microsoft.com/en-us/library/z0w1kczw(v=VS.100).aspx"&gt;attributes&lt;/a&gt; for classes and methods. There are quite a lot of attributes provided out of the box, mostly in AIF, Services, Upgrade, SysTest areas and it is also possible to create new attributes by inheriting from the SysAttribute class.&lt;br /&gt;Attributes can really simplify many frameworks. For example, in the upgrade framework initPreSyncJobs() and initPostSyncJobs() methods, that contained usually quite a large amount of upgrade jobs and dependencies registration code, were effectively deprecated. All the registration is performed now via attributes that are attached to upgrade methods.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-zzq9wIEvB0o/TbHQ_9PdEYI/AAAAAAAAFK0/UGIH8K05YUA/s1600/attributes1.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 214px;" src="http://4.bp.blogspot.com/-zzq9wIEvB0o/TbHQ_9PdEYI/AAAAAAAAFK0/UGIH8K05YUA/s400/attributes1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5598485608987955586" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-4645057542260166489?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/4645057542260166489/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2011/04/x-attributes.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/4645057542260166489'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/4645057542260166489'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2011/04/x-attributes.html' title='X++ attributes'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-zzq9wIEvB0o/TbHQ_9PdEYI/AAAAAAAAFK0/UGIH8K05YUA/s72-c/attributes1.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-6952370093137199777</id><published>2011-04-21T21:52:00.005+02:00</published><updated>2011-04-21T22:39:48.384+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='services'/><category scheme='http://www.blogger.com/atom/ns#' term='CIL'/><category scheme='http://www.blogger.com/atom/ns#' term='CLR'/><category scheme='http://www.blogger.com/atom/ns#' term='AX 2012'/><title type='text'>X++ can be compiled to CIL in AX 2012</title><content type='html'>In AX 2012 X++ code can be compiled into &lt;a href="http://en.wikipedia.org/wiki/Common_Intermediate_Language"&gt;CIL&lt;/a&gt; and executed in &lt;a href="http://en.wikipedia.org/wiki/Common_Language_Runtime"&gt;CLR&lt;/a&gt; environment hosted on the application object server. This means X++ became almost a .NET language. Almost, because there are still some X++ artifacts that can only be interpreted, for example forms. However the vast majority of server-side code can be compiled into CIL. &lt;br /&gt;&lt;br /&gt;Because of that it is important to remember to regenerate CIL after changes have been done to the code. Since CIL compilation takes quite some time, it is not done automatically during regular X++ compilation. There are new compilation commands – Generate Incremental CIL (rebuilds assemblies that are affected by the change) and Generate Full CIL (rebuilds all assemblies). Those commands are applicable to the whole application and not to a specific X++ object (class, table, etc.). AX automatically determines what X++ objects should be compiled into CIL based on the registered entry points, e.g. if it is specified that some method should be executed in CLR, then the whole “using” reference tree of this method will be compiled into CIL.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-Aca-zZbwGnk/TbCUlXMBn9I/AAAAAAAAFKU/fcqP44Suqqs/s1600/cil1.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 257px; height: 54px;" src="http://1.bp.blogspot.com/-Aca-zZbwGnk/TbCUlXMBn9I/AAAAAAAAFKU/fcqP44Suqqs/s400/cil1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5598137706422050770" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;There are several ways to specify that some code should be executed in CLR instead of X++ interpreter. Right now I want to show only one of them just to illustrate how easy it can be.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-Yx5kLkLEch0/TbCVAKr1GHI/AAAAAAAAFKs/qQr-w8Kv4kc/s1600/cil3.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 349px;" src="http://4.bp.blogspot.com/-Yx5kLkLEch0/TbCVAKr1GHI/AAAAAAAAFKs/qQr-w8Kv4kc/s400/cil3.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5598138166922254450" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;TestILExecution job will be executed using X++ interpreter (just in the same way as in previous AX versions), but postSalesOrderPackingSlip() method will be executed in CLR. As you can see, postSalesOrderPackingSlip() method is a standard method of a standard X++ class. Switching will happen because this method is registered as a service operation of FormLetterService service, and the service itself is a member of the AxClient service group which is deployed on the AOS.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-DF25B9FXaic/TbCUllv3p3I/AAAAAAAAFKc/5wuvvFnUzFw/s1600/cil2.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 364px;" src="http://4.bp.blogspot.com/-DF25B9FXaic/TbCUllv3p3I/AAAAAAAAFKc/5wuvvFnUzFw/s400/cil2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5598137710330488690" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-6952370093137199777?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/6952370093137199777/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2011/04/x-can-be-compiled-to-cil-in-ax-2012.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/6952370093137199777'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/6952370093137199777'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2011/04/x-can-be-compiled-to-cil-in-ax-2012.html' title='X++ can be compiled to CIL in AX 2012'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-Aca-zZbwGnk/TbCUlXMBn9I/AAAAAAAAFKU/fcqP44Suqqs/s72-c/cil1.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-3948176883160093527</id><published>2011-04-20T23:07:00.005+02:00</published><updated>2011-04-20T23:24:09.348+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='intellisense'/><category scheme='http://www.blogger.com/atom/ns#' term='AX 2012'/><title type='text'>Intellisense in AX 2012</title><content type='html'>Intellisense in AX 2012 was significantly improved (or actually, redesigned). Now it is much closer to the visual studio intellisense. &lt;br /&gt;Suggestions are presented to the user while typing for types (tables, classes, extended data types, etc.), class members and methods, local variables, intrinsic and global functions, keywords. Namespaces and types from the referenced .NET assemblies are also suggested.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-kbWtlD2X4o0/Ta9MQaFTJdI/AAAAAAAAFKE/JdpzD5vZizE/s1600/intellisense1.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 362px; height: 230px;" src="http://2.bp.blogspot.com/-kbWtlD2X4o0/Ta9MQaFTJdI/AAAAAAAAFKE/JdpzD5vZizE/s400/intellisense1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5597776706607982034" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Descriptions for methods were also improved. Now they include XML documentation for the methods. That is really helpful.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-LXt4ypsK9JQ/Ta9Mtb5Ix3I/AAAAAAAAFKM/0-0UToJemD8/s1600/intellisense2.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 43px;" src="http://3.bp.blogspot.com/-LXt4ypsK9JQ/Ta9Mtb5Ix3I/AAAAAAAAFKM/0-0UToJemD8/s400/intellisense2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5597777205310048114" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-3948176883160093527?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/3948176883160093527/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2011/04/intellisense-in-ax-2012.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/3948176883160093527'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/3948176883160093527'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2011/04/intellisense-in-ax-2012.html' title='Intellisense in AX 2012'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-kbWtlD2X4o0/Ta9MQaFTJdI/AAAAAAAAFKE/JdpzD5vZizE/s72-c/intellisense1.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-2365158046034045778</id><published>2011-04-19T21:00:00.007+02:00</published><updated>2011-04-20T23:22:45.644+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='IDE'/><category scheme='http://www.blogger.com/atom/ns#' term='tool'/><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='hotkey'/><category scheme='http://www.blogger.com/atom/ns#' term='feature'/><category scheme='http://www.blogger.com/atom/ns#' term='X++ editor'/><category scheme='http://www.blogger.com/atom/ns#' term='AX 2012'/><title type='text'>Development environment in AX 2012</title><content type='html'>It wasn't easy to decide from what to start. There are so many new features and they are so important and interesting! However, there is one feature that every AX 2012 developer will use for sure.&lt;br /&gt;&lt;br /&gt;In AX 2012 the new development environment was introduced (click on the picture to enlarge).&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-iKsf62mPe7Q/Ta3ckgp1FSI/AAAAAAAAFJ8/3hAyRWZ-A9Y/s1600/devenv.png"&gt;&lt;img style="width: 400px; height: 250px; cursor: pointer;" id="BLOGGER_PHOTO_ID_5597372431690175778" border="0" alt="" src="http://3.bp.blogspot.com/-iKsf62mPe7Q/Ta3ckgp1FSI/AAAAAAAAFJ8/3hAyRWZ-A9Y/s400/devenv.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-OcIvZVaQzoQ/Ta3cAWmbdUI/AAAAAAAAFJ0/i1WK7PU6cqU/s1600/devenv.png"&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Now IDE is separated from the application. That means more space because of missing navigation pane, no interfering content pane that can be removed only using some &lt;a href="http://axdaily.blogspot.com/2010/01/hiding-content-pane-in-ax-2009.html"&gt;tricks&lt;/a&gt; and the development-specific main menu.&lt;br /&gt;&lt;br /&gt;You can also notice the beautiful visual studio-like code editor and compiler output window.&lt;br /&gt;&lt;br /&gt;Development tools are now much more accessible. Version control parameters, for example, do not require navigating 3-levels deep menu.&lt;br /&gt;&lt;br /&gt;Development workspace can be started by typing&lt;br /&gt;&lt;b&gt;ax32 - development&lt;/b&gt;&lt;br /&gt;from command line, or by&lt;br /&gt;&lt;b&gt;Ctrl+Shift+W&lt;/b&gt;&lt;br /&gt;combination from the application or another development workspace.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-2365158046034045778?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/2365158046034045778/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2011/04/it-wasnt-easy-to-decide-from-what-to.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/2365158046034045778'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/2365158046034045778'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2011/04/it-wasnt-easy-to-decide-from-what-to.html' title='Development environment in AX 2012'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-iKsf62mPe7Q/Ta3ckgp1FSI/AAAAAAAAFJ8/3hAyRWZ-A9Y/s72-c/devenv.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-8658084493420415430</id><published>2011-04-18T13:32:00.003+02:00</published><updated>2011-04-18T14:19:48.673+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='disclaimer'/><category scheme='http://www.blogger.com/atom/ns#' term='AX 2012'/><title type='text'>AX 2012 is on the way!</title><content type='html'>So, AX 2012 will be released very soon and it means that it is the time to share some more details about it. And it also means that it is the time to revive this blog!&lt;br /&gt;&lt;br /&gt;The amount of changes that were done in AX 2012 is just tremendous. A lot of new concepts, features, improvements and of course, small specialties and tricks! Describing all that should keep me busy for a while.&lt;br /&gt;&lt;br /&gt;The plan for now is to make an overview of the new technological features and then look into them in much more details. However, if you are interested in details for some particular feature, let me know by leaving a comment to this post.&lt;br /&gt;&lt;br /&gt;Ok, let’s get started! Just one very important thing prior to that:&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Disclaimer&lt;/h3&gt;&lt;b&gt;All the information about AX 2012 posted here is a pre-release. Any feature is a subject to be changed before the release without notice.&lt;br /&gt;This disclaimer is applicable to all posts about AX 2012 in this blog.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;And here is the link to get the first impression of what has been done:&lt;br /&gt;&lt;a href="http://www.microsoft.com/downloads/en/details.aspx?FamilyID=d38bb877-7cf8-400e-8a50-47d4ebbaf4a6&amp;amp;displaylang=en"&gt;New, Changed, and Deprecated Features for Microsoft Dynamics AX 2012&lt;/a&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-8658084493420415430?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/8658084493420415430/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2011/04/ax-2012-is-on-way.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/8658084493420415430'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/8658084493420415430'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2011/04/ax-2012-is-on-way.html' title='AX 2012 is on the way!'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-1247337422285447317</id><published>2010-05-03T23:40:00.001+02:00</published><updated>2010-05-03T23:58:18.961+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='layers'/><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='QnA'/><category scheme='http://www.blogger.com/atom/ns#' term='best practice'/><title type='text'>Overlay vs override</title><content type='html'>Microsoft is trying to achieve consistency among all the classes in AX to have the following condition met: &lt;br /&gt;Each class has construct method which takes no parameters. This constructor should be the primary entry point for class construction, e.g. any other constructor should use construct() inside. &lt;br /&gt;For the same reason, to avoid direct instantiation of the objects via new() method they are marked as protected. It is done in such way because it looks like overriding is much more maintainable than overlaying. It is better to create a sub-class in the outer layer that extends super-class in inner layer and overrides the required method + have construct() method overlaid to instantiate sub-class instead. Code upgrade in this case seems to be much cheaper comparing to the case when methods are overlaid directly on the super-class.&lt;br /&gt;&lt;br /&gt;So my question basically is, if this statement is correct or not? Are you writing code in the described way? If no, why? What are the cases when overlaying is better that overriding?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-1247337422285447317?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/1247337422285447317/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/05/overlay-vs-override.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/1247337422285447317'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/1247337422285447317'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/05/overlay-vs-override.html' title='Overlay vs override'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-5279551999237291521</id><published>2010-04-30T23:57:00.000+02:00</published><updated>2010-05-01T01:22:32.189+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='unit tests'/><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='AX 2009'/><title type='text'>Unit tests data setup and tear down</title><content type='html'>There are methods in AX to setup data before test execution and tear it down afterwards - SysTestCase.setup() and SysTestCase.tearDown(). Those methods will be executed before and after each test method in a unit test class. &lt;br /&gt;In AX 2009 two new methods were added - setupTestCase() and tearDownTestCase() which are executed only once per unit test class execution - before first test method and after last test method. But there is a problem with using them - by default each unit test method runs in a separate instance of the unit test class, so if you are setting up some data in the setupTestCase() method there will be no possibility to store a reference to it in the instance variable. &lt;br /&gt;To change this behavior useSingleInstance() method can be overridden to return true. In this case all test method as well as setupTestCase() and tearDownTestCase() method will be execute in one instance of the unit test class.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-5279551999237291521?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/5279551999237291521/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/05/unit-tests-data-setup-and-tear-down.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/5279551999237291521'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/5279551999237291521'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/05/unit-tests-data-setup-and-tear-down.html' title='Unit tests data setup and tear down'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-9162163476142732499</id><published>2010-04-28T23:55:00.004+02:00</published><updated>2010-04-29T00:05:45.089+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='client server'/><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='database'/><title type='text'>Record caching principle</title><content type='html'>Which statement will perform faster?&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;select inventTable&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;join inventItemGroup&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;where inventItemGroup.ItemGroupId == inventTable.ItemGroupId&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;amp;&amp;amp; inventTable.ItemId == 'A'; &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;or&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;select inventTable&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;where inventTable.ItemId == 'A';&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;select inventItemGroup&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;where inventItemGroup.ItemGroupId == inventTable.ItemGroupId; &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;From the first point of view it seems obvious that the first one with join, since it will result in only one database call and the second will result in two. However, it is not always the case. For example, if records that are being looked up in the second example are cached on the server (or even on the client) there will be no database calls at all, and may be even no client\server calls! The code from the first example will never hit the cache since caching is not supported for the queries with joins.&lt;br /&gt;Actually Dynamics AX caches records by their primary key value. So, if a query has no joins and has primary key in its where clause then it will hit the cache. Otherwise it won't.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-9162163476142732499?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/9162163476142732499/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/04/record-caching-principle.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/9162163476142732499'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/9162163476142732499'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/04/record-caching-principle.html' title='Record caching principle'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-4482510231018921609</id><published>2010-04-27T23:52:00.003+02:00</published><updated>2010-04-28T00:22:44.706+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='exception'/><category scheme='http://www.blogger.com/atom/ns#' term='CLR'/><title type='text'>Working with CLR null references</title><content type='html'>In C# if a method has return value of type string it is possible to return null. If you'll try to use this method from AX you'll get exception because null value cannot be marshaled to X++ string (it is not nullable).&lt;br /&gt;To avoid this failure there is a possibility to validate if returned value is null by using CLRInterop::isNull() method.&lt;br /&gt;Example:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;if (ClrInterop::isNull(myCLRObject.method1()))&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;info("Null value was returned");&lt;br /&gt;}&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-4482510231018921609?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/4482510231018921609/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/04/working-with-clr-null-references.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/4482510231018921609'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/4482510231018921609'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/04/working-with-clr-null-references.html' title='Working with CLR null references'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-1323746402507014735</id><published>2010-04-26T20:25:00.002+02:00</published><updated>2010-04-26T20:32:01.279+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='AX 2009'/><category scheme='http://www.blogger.com/atom/ns#' term='bug'/><category scheme='http://www.blogger.com/atom/ns#' term='CLR'/><title type='text'>Switch statement and CLR enums</title><content type='html'>There is a really weird bug in AX 2009 with CLR enumerations. If the code has "if" statement that validates value of a variable of CLR enum type everything is fine. However, the same "switch" statement fails with kernel exception.&lt;br /&gt;Example:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;MyNamespace.MyEnum enum;&lt;br /&gt;&lt;br /&gt;enum = MyNamespace.MyEnum::Value1;&lt;br /&gt;&lt;br /&gt;if (enum == MyNamespace.MyEnum::Value1)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;info("Everything is fine");&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;switch (enum)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;case MyNamespace.MyEnum::Value1 :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;info("And not so good here");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Result:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Error executing code: Wrong argument types for comparison.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-1323746402507014735?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/1323746402507014735/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/04/switch-statement-and-clr-enums.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/1323746402507014735'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/1323746402507014735'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/04/switch-statement-and-clr-enums.html' title='Switch statement and CLR enums'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-7796531707268182666</id><published>2010-04-22T23:49:00.004+02:00</published><updated>2010-04-23T00:06:25.649+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='query'/><category scheme='http://www.blogger.com/atom/ns#' term='bug'/><title type='text'>Magical FetchMode property</title><content type='html'>What does the FetchMode property on a query do? I will appreciate if someone will be able to give me very precise answer.&lt;br /&gt;I know only implication of this parameter. It matters when exist/notexist joined datasources on the query are forming a tree - not a chain. If the tree of datasources is quite complex then your query has a very good chance not to work if FetchMode is not set to One2One.&lt;br /&gt;To my knowledge it is related somehow to the way the kernel stores query datasources.&lt;br /&gt;So, my rule of thumb is the following: if a query datasources form tree-like structure, FetchMode must be set to One2One everywhere exist/notexist join is used.&lt;br /&gt;&lt;br /&gt;Example:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Query query;&lt;br /&gt;QueryBuildDataSource qbdsInventTable;&lt;br /&gt;QueryBuildDataSource qbdsInventItemGroup;&lt;br /&gt;QueryBuildDataSource qbdsInventModelGroup;&lt;br /&gt;;&lt;br /&gt;&lt;br /&gt;query = new Query();&lt;br /&gt;qbdsInventTable = query.addDataSource(tablenum(InventTable));&lt;br /&gt;&lt;br /&gt;qbdsInventItemGroup = qbdsInventTable.addDataSource(tablenum(InventItemGroup));&lt;br /&gt;qbdsInventItemGroup.relations(true);&lt;br /&gt;qbdsInventItemGroup.joinMode(JoinMode::ExistsJoin);&lt;br /&gt;qbdsInventItemGroup.fetchMode(QueryFetchMode::One2One);&lt;br /&gt;&lt;br /&gt;qbdsInventModelGroup = qbdsInventTable.addDataSource(tablenum(InventModelGroup));&lt;br /&gt;qbdsInventModelGroup.relations(true);&lt;br /&gt;qbdsInventModelGroup.joinMode(JoinMode::NoExistsJoin);&lt;br /&gt;qbdsInventModelGroup.fetchMode(QueryFetchMode::One2One);&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-7796531707268182666?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/7796531707268182666/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/04/magical-fetchmode-property.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/7796531707268182666'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/7796531707268182666'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/04/magical-fetchmode-property.html' title='Magical FetchMode property'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-6528092249809219598</id><published>2010-04-21T22:21:00.003+02:00</published><updated>2010-04-21T22:30:51.187+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='exception'/><category scheme='http://www.blogger.com/atom/ns#' term='CLR'/><title type='text'>Getting CLR exception message</title><content type='html'>An exception that appears in AX if something went wrong in the managed code you are running doesn't contain much information about what have happened. For example, it can be something like: Object 'CLRObject' could not be created. But, there is a trick which helps to get more meaningful message, actually the one that was thrown in CLR - AifUtil::getClrErrorMessage().&lt;br /&gt;&lt;br /&gt;Example:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ServiceNamespace.MyService service;&lt;br /&gt;&lt;br /&gt;try&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;service = new ServiceNamespace.MyService();&lt;br /&gt;}&lt;br /&gt;catch&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;throw error(AifUtil::getClrErrorMessage());&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Gives the following information:&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_M4Xc6T_bNcg/S89fYSs2UCI/AAAAAAAAE1g/m8ug89jD7bA/s1600/CLRexception.png"&gt;&lt;img style="WIDTH: 400px; HEIGHT: 55px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5462689743965147170" border="0" alt="" src="http://1.bp.blogspot.com/_M4Xc6T_bNcg/S89fYSs2UCI/AAAAAAAAE1g/m8ug89jD7bA/s400/CLRexception.png" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-6528092249809219598?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/6528092249809219598/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/04/getting-clr-exception-message.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/6528092249809219598'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/6528092249809219598'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/04/getting-clr-exception-message.html' title='Getting CLR exception message'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_M4Xc6T_bNcg/S89fYSs2UCI/AAAAAAAAE1g/m8ug89jD7bA/s72-c/CLRexception.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-9168311785783322331</id><published>2010-04-20T23:43:00.005+02:00</published><updated>2010-04-21T00:27:59.155+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='client server'/><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><title type='text'>MultiSelectionHelper class</title><content type='html'>When a developer is implementing some scenario which requires support of multiple record selection on the form he faces the problem that form datasource should be iterated on the client to avoid numerous calls from server to client (form resides on client). From the other point of view, the scenario itself most likely requires numerous database operations, so it probably should be run on server. There is a solution to this problem – datasource should be iterated on the client, fetched records serialized and passed to the server, where the main job will be executed.&lt;br /&gt;In AX 2009 a new class MultiSelectionHelper was introduced to simplify the described scenario. This class can be constructed on the server and the reference to form data source can be passed into it. The MultiSelectionHelper has API to iterate records on the form datasource – getFirst() and getNext(), just like datasource itself has. But the difference is that MultiSelectionHelper will do pre-fetch of the records from the datasource first time it will be accessed, so any further calls to its methods will not cause any client\server calls.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-9168311785783322331?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/9168311785783322331/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/04/multiselectionhelper-class.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/9168311785783322331'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/9168311785783322331'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/04/multiselectionhelper-class.html' title='MultiSelectionHelper class'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-1839244539788922841</id><published>2010-04-19T23:30:00.000+02:00</published><updated>2010-04-20T00:20:18.608+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='compiler'/><title type='text'>Compiler special cases</title><content type='html'>There are several code examples which are compiled in AX not in the way one can expect. For example, call to any method on the Object class or Common class will be successfully compiled despite the fact that such method does not exist on the mentioned class. There is also special case in the other way around. It is regarding "element" object in the forms and reports. Element object is of type SysSetupFormRun (for forms) and SysReportRun (for reports), but they will contain all the methods created on the form or report and will allow to compile calls to them (not any method will be allowed in this case).&lt;br /&gt;&lt;br /&gt;Do you know any other examples of such compiler special cases?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-1839244539788922841?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/1839244539788922841/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/04/compiler-special-cases.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/1839244539788922841'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/1839244539788922841'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/04/compiler-special-cases.html' title='Compiler special cases'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-6907727379363962519</id><published>2010-04-16T23:59:00.001+02:00</published><updated>2010-04-17T00:01:14.464+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Global class'/><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><title type='text'>Global::formControlValue</title><content type='html'>There is quite frustrating fact about different AX form edit control classes, like FormStringControl, FormIntControl, etc. They are inherited directly from FormControl class which of course has no method to get the value in the control (because buttons or tabs are inherited from FormControl too and they don't have value). So, each form edit control class has its own method to get the value from it, for example FormIntControl has method value(), but FormRealControl has method realValue() for the same purpose. It makes some problems in the case you want to work with form which is generated dynamically and has controls of unknown type in compile time. For resolving this problem you can use formControlValue() method which allows to get the value from form edit control of any type.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-6907727379363962519?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/6907727379363962519/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/04/globalformcontrolvalue.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/6907727379363962519'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/6907727379363962519'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/04/globalformcontrolvalue.html' title='Global::formControlValue'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-3706406361294657316</id><published>2010-04-15T23:30:00.001+02:00</published><updated>2010-04-15T23:31:46.244+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='Label editor'/><category scheme='http://www.blogger.com/atom/ns#' term='AOT'/><category scheme='http://www.blogger.com/atom/ns#' term='RegExp'/><title type='text'>Regular expressions in AOT and label search</title><content type='html'>It is known fact that AOT search and Label editor search support regular expressions. However, I never met any document that describes the grammar of the regular expressions used there. I haven’t done the full code investigation but it was reasonable to assume that match() kernel function is used for this purpose. So I’ve looked for documentation for this function and validated that all described patterns can really be used for the AOT and label search. Here is the link to match() documentation: &lt;a href="http://msdn.microsoft.com/en-us/library/aa886279.aspx"&gt;http://msdn.microsoft.com/en-us/library/aa886279.aspx&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-3706406361294657316?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/3706406361294657316/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/04/regular-expressions-in-aot-and-label.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/3706406361294657316'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/3706406361294657316'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/04/regular-expressions-in-aot-and-label.html' title='Regular expressions in AOT and label search'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-7898632419722786540</id><published>2010-04-14T22:22:00.003+02:00</published><updated>2010-04-21T00:28:37.003+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='exception'/><title type='text'>Exceptions and tts 2</title><content type='html'>Once I wrote &lt;a href="http://axdaily.blogspot.com/2010/01/exceptions-and-tts.html"&gt;here&lt;/a&gt; that one cannot catch exception from inside transaction. This appeared to be not true. Or, well, at least partially true. There are types of exceptions that can be caught from inside transaction - Exception::DuplicateKeyException and Exception::UpdateConflict.&lt;br /&gt;Example:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ttsbegin;&lt;br /&gt;try&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;throw Exception::UpdateConflict;&lt;br /&gt;}&lt;br /&gt;catch&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;info("Here");&lt;br /&gt;}&lt;br /&gt;ttscommit; &lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-7898632419722786540?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/7898632419722786540/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/04/exceptions-and-tts-2.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/7898632419722786540'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/7898632419722786540'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/04/exceptions-and-tts-2.html' title='Exceptions and tts 2'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-1830223771629319726</id><published>2010-04-13T22:29:00.003+02:00</published><updated>2010-04-13T22:34:08.189+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='compiler'/><title type='text'>Using XppScanner for lexical code parsing</title><content type='html'>The XppScanner class allows to parse X++ code in the way compiler does it. The simplest way to use it is to traverse all symbols in the given source code using iteration methods – firstSymbol() and nextSymbol(). The integer values returned by these methods are enumerated in the TokenTypes macro. For example, to check if there is “ttsbegin” statement in the code the following job can be used:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;public static boolean checkTTSBegin(str _source)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#TokenTypes&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;XppScanner xppScanner = new XppScanner(_source);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;int symbol;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for (symbol = xppScanner.firstSymbol(); symbol; symbol = xppScanner.nextSymbol())&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (symbol == #TTSBEGIN_SYM)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return true;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return false;&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;PS. For this particular task you can, of course, use XppScanner.find() method.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-1830223771629319726?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/1830223771629319726/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/04/using-xppscanner-for-code-parsing.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/1830223771629319726'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/1830223771629319726'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/04/using-xppscanner-for-code-parsing.html' title='Using XppScanner for lexical code parsing'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-8916029180664424051</id><published>2010-04-12T21:25:00.002+02:00</published><updated>2010-04-12T21:34:57.761+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='WinAPI'/><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='debug'/><title type='text'>Performance measurement</title><content type='html'>My favorite approach to measure performance of my code in AX is WinAPI::getTickCount() method. I find it as the most precise and simple way to do a quick measurement. Code profiler measures performance quite well, however it takes much more time to get the results.&lt;br /&gt;How do you measure performance of your code in AX?&lt;br /&gt;&lt;br /&gt;Example:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;int timeInterval;&lt;br /&gt;;&lt;br /&gt;&lt;br /&gt;timeInterval = WinAPI::getTickCount();&lt;br /&gt;doSomething();&lt;br /&gt;timeInterval = WinAPI::getTickCount() - timeInterval; &lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-8916029180664424051?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/8916029180664424051/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/04/performance-measurement.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/8916029180664424051'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/8916029180664424051'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/04/performance-measurement.html' title='Performance measurement'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-8596434320929625016</id><published>2010-04-09T21:02:00.004+02:00</published><updated>2010-04-09T21:13:59.034+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='bug'/><category scheme='http://www.blogger.com/atom/ns#' term='table'/><title type='text'>FormRef and Go to the main table form</title><content type='html'>It is known fact that "go to the main table form" functionality uses FormRef property on the table to determine which form should be opened (a menu item can be specified there pointing the required form). The interesting fact is that even if FormRef is not specified on the table AX will still try to open some form. Actually AX will look for display menu item which has the name equals to the table name.&lt;br /&gt;Frustrating thing is that if such menu item does not exist the warning will be shown on clicking "go to the main table form":&lt;br /&gt;No object specified on menu item %TableName%.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-8596434320929625016?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/8596434320929625016/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/04/formref-and-go-to-main-table-form.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/8596434320929625016'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/8596434320929625016'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/04/formref-and-go-to-main-table-form.html' title='FormRef and Go to the main table form'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-3677599469000529493</id><published>2010-04-08T22:50:00.002+02:00</published><updated>2010-04-08T22:55:25.229+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='WinAPI'/><category scheme='http://www.blogger.com/atom/ns#' term='Global class'/><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><title type='text'>Simple cryptography in AX</title><content type='html'>There are methods in AX which allow to encrypt and decrypt data easily. Those methods are WinAPIServer::cryptProtectData() for encryption and WinAPIServer::cryptUnProtectData() for decryption. As input and output parameters these methods use CryptoBlob extended data type, which is a container. However, this is not an arbitrary container. It should contain only bytes (integers in the range 0-255). There are methods on the Global class which allow to convert from and to CryptoBlob type, for example, Global::binary2cryptoblob() and Global::cryptoblob2binary().&lt;br /&gt;&lt;br /&gt;Sample usage:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;public static void cryptoTest()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;str text = "Here goes some text";&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;CryptoBlob encryptedCryptoBlob;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;str decryptedText;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;encryptedCryptoBlob = WinAPIServer::cryptProtectData(str2cryptoblob(text));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;conview(encryptedCryptoBlob);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;decryptedText = cryptoblob2str(WinAPIServer::cryptUnProtectData(encryptedCryptoBlob));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;info(decryptedText);&lt;br /&gt;} &lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-3677599469000529493?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/3677599469000529493/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/04/simple-cryptography-in-ax.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/3677599469000529493'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/3677599469000529493'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/04/simple-cryptography-in-ax.html' title='Simple cryptography in AX'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-2336069806883700533</id><published>2010-04-07T22:25:00.003+02:00</published><updated>2010-04-07T22:29:17.436+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Global class'/><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='labels'/><title type='text'>Labels with line breaks</title><content type='html'>Labels can contain line breaks. For example, “Text1\nText2” (let it has ID @LBL1).&lt;br /&gt;&lt;br /&gt;However, if you’ll try to display this label “as is”, the result will be not expected:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Box::info("@LBL1");&lt;/span&gt;&lt;br /&gt;Gives&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_M4Xc6T_bNcg/S7zqyKG67jI/AAAAAAAAE0c/B-f4IHiZDgA/s1600/Box1.png"&gt;&lt;img style="WIDTH: 155px; HEIGHT: 123px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5457494995893939762" border="0" alt="" src="http://1.bp.blogspot.com/_M4Xc6T_bNcg/S7zqyKG67jI/AAAAAAAAE0c/B-f4IHiZDgA/s400/Box1.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;To get the expected message with line break strFmtLB() method should be used:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Box::info(strFmtLB("@LBL1"));&lt;/span&gt;&lt;br /&gt;Gives &lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_M4Xc6T_bNcg/S7zqyH6gyZI/AAAAAAAAE0k/_8peIRfJado/s1600/Box2.png"&gt;&lt;img style="WIDTH: 153px; HEIGHT: 120px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5457494995305023890" border="0" alt="" src="http://3.bp.blogspot.com/_M4Xc6T_bNcg/S7zqyH6gyZI/AAAAAAAAE0k/_8peIRfJado/s400/Box2.png" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-2336069806883700533?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/2336069806883700533/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/04/labels-with-line-breaks.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/2336069806883700533'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/2336069806883700533'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/04/labels-with-line-breaks.html' title='Labels with line breaks'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_M4Xc6T_bNcg/S7zqyKG67jI/AAAAAAAAE0c/B-f4IHiZDgA/s72-c/Box1.png' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-8008649069162913301</id><published>2010-04-06T23:42:00.002+02:00</published><updated>2010-04-06T23:46:00.316+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='test'/><title type='text'>Deadlocks with number sequences</title><content type='html'>Number sequence cannot be set up and used in the same transaction. If you’ll try to do so you’ll face a deadlock. This happens because of the fact that AX uses separate connection to get next number from a number sequence.&lt;br /&gt;&lt;br /&gt;For example, the following code will cause deadlock:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;public static void testNumberSequences()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;NumberSequenceTable numberSequenceTable;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;NumberSequenceReference numberSequenceReference;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ttsbegin;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;numberSequenceTable.NumberSequence = 'A';&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;numberSequenceTable.Lowest = 1;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;numberSequenceTable.Highest = 99999;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;numberSequenceTable.NextRec = 1;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;numberSequenceTable.Format = '#####';&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;numberSequenceTable.Continuous = NoYes::No;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;numberSequenceTable.insert();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;numberSequenceReference.DataTypeId = typeId2ExtendedTypeId(typeid(ItemGroupId));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;numberSequenceReference.NumberSequence = numberSequenceTable.NumberSequence;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;numberSequenceReference.insert();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;NumberSeq::newGetNum(NumberSeqReference::findReference(typeId2ExtendedTypeId(typeid(ItemGroupId)))).num();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ttscommit;&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;By moving the line with num() call out of tts scope the deadlock will be eliminated.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-8008649069162913301?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/8008649069162913301/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/04/deadlocks-with-number-sequences.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/8008649069162913301'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/8008649069162913301'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/04/deadlocks-with-number-sequences.html' title='Deadlocks with number sequences'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-3766521483831588331</id><published>2010-04-05T23:41:00.001+02:00</published><updated>2010-04-05T23:43:38.083+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='bug'/><category scheme='http://www.blogger.com/atom/ns#' term='compiler'/><category scheme='http://www.blogger.com/atom/ns#' term='best practice'/><title type='text'>Implicit casting from super-class to sub-class</title><content type='html'>X++ compiler allows casting from the super-class object to the sub-class. For example, UserConnection class extends Connection class. And you are allowed to write the following code:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;UserConnection con = new Connection(); &lt;/span&gt;&lt;br /&gt;The only consequence of doing such thing is a run-time error thrown if a method that exists only on sub-class will be called for the instantiated object.&lt;br /&gt;In the modern managed languages such implicit casting is not allowed and generates compilation error. So, it is best practice not to use it in AX too.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-3766521483831588331?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/3766521483831588331/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/04/implicit-casting-from-super-class-to.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/3766521483831588331'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/3766521483831588331'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/04/implicit-casting-from-super-class-to.html' title='Implicit casting from super-class to sub-class'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-1390948462349222298</id><published>2010-04-02T22:53:00.001+02:00</published><updated>2010-04-02T22:53:51.306+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='forms'/><category scheme='http://www.blogger.com/atom/ns#' term='bug'/><title type='text'>Breakpoint in clicked method</title><content type='html'>There is quite well known bug in AX that breakpoint placed in the clicked() method of a button will not be triggered. It is quite unpleasant one since when one faces it first time he gets totally confused.&lt;br /&gt;However, there are easy workarounds for this bug. First one – put breakpoint into the method that is called from clicked (in most cases it is possible). But if not, keyword breakpoint can be used – it will be triggered in clicked() method.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-1390948462349222298?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/1390948462349222298/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/04/breakpoint-in-clicked-method.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/1390948462349222298'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/1390948462349222298'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/04/breakpoint-in-clicked-method.html' title='Breakpoint in clicked method'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-5822899001694014774</id><published>2010-04-01T23:06:00.003+02:00</published><updated>2010-04-01T23:19:42.945+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='kernel'/><title type='text'>FormattedStr2Num kernel function</title><content type='html'>Once I've read &lt;a href="http://axatluegisdorf.blogspot.com/2010/03/simple-x-calculator.html"&gt;here&lt;/a&gt; that arithmetic expressions get evaluated in real edit form controls. It was an interesting fact that I didn't know. As an alternative way to evaluate arithmetic expressions runBuf and evalBuf kernel functions can be used, however they require code access permission validation.&lt;br /&gt;Today I found yet another way to do the same thing - formattedStr2Num kernel function, which is designed to convert strings to reals but it accepts arithmetic expressions too. Probably it is the function invoked by form real edit control to evaluate user input.&lt;br /&gt;&lt;br /&gt;Example:&lt;br /&gt;formattedStr2Num('0.23 + 1 * (2 - 0,5)');&lt;br /&gt;gives 1.73 as the result.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-5822899001694014774?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/5822899001694014774/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/04/formattedstr2num-kernel-function.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/5822899001694014774'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/5822899001694014774'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/04/formattedstr2num-kernel-function.html' title='FormattedStr2Num kernel function'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-1898004893981926254</id><published>2010-03-31T23:22:00.003+02:00</published><updated>2010-03-31T23:25:56.577+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='app'/><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='Inventory dimensions'/><category scheme='http://www.blogger.com/atom/ns#' term='Macro'/><title type='text'>InventDimDevelop macro</title><content type='html'>InventDimDevelop macro is used to mark places in the application where specific inventory dimension(s) are referred from the code explicitly. The idea behind it is to help developers to find all the places that potentially have to be updated if a new inventory dimension is added.&lt;br /&gt;&lt;br /&gt;For example, the following code should be marked with InventDimDevelop since size, color and configuration are referred explicitly:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;#InventDimDevelop&lt;br /&gt;&lt;br /&gt;this.ConfigId = inventDimCombination.ConfigId;&lt;br /&gt;this.InventSizeId = inventDimCombination.InventSizeId;&lt;br /&gt;this.InventColorId = inventDimCombination.InventColorId;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;However, the following code processes all dimensions in a loop, so newly added dimension will be handled automatically. No need for InventDimDevelop.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;container dimFields = InventDim::dimFieldList();&lt;br /&gt;int h, y;&lt;br /&gt;;&lt;br /&gt;&lt;br /&gt;for (h = 1; h &lt;= conlen(dimFields); h++)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;y = conpeek(dimFields, h);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;this.(y) = _inventDim.(y);&lt;br /&gt;}&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-1898004893981926254?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/1898004893981926254/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/03/inventdimdevelop-macro.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/1898004893981926254'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/1898004893981926254'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/03/inventdimdevelop-macro.html' title='InventDimDevelop macro'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-2604635649713656199</id><published>2010-03-30T19:19:00.004+02:00</published><updated>2010-03-31T09:17:39.149+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tool'/><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><title type='text'>SysSpellChecker</title><content type='html'>There is a class in AX that allows to perform spell checking. This class uses Microsoft Word spell checker to do the validation. So, in order to use it, Microsoft Word should be installed together with proofing language pack. Because of this requirement it is also important to consider where to run spell checking - on the server or on the client.&lt;br /&gt;&lt;br /&gt;Example:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;public static server void spellCheckerTest()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;SysSpellChecker sp = SysSpellChecker::newLanguageId('en-us');&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;info(strfmt('%1', sp.checkSpelling("behavior")));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;info(strfmt('%1', sp.checkSpelling("behaviour")));&lt;br /&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The output in infolog will be:&lt;br /&gt;1&lt;br /&gt;0&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Upd:&lt;/b&gt; I've received a link to the interesting post where there is more information about AX spell checker - &lt;a href="http://sangi1983.spaces.live.com/blog/cns!264A0056CBCBB1D3!404.entry?wa=wsignin1.0&amp;sa=93421708"&gt;http://sangi1983.spaces.live.com/blog/cns!264A0056CBCBB1D3!404.entry?wa=wsignin1.0&amp;sa=93421708&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-2604635649713656199?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/2604635649713656199/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/03/sysspellchecker.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/2604635649713656199'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/2604635649713656199'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/03/sysspellchecker.html' title='SysSpellChecker'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-4775799302396398318</id><published>2010-03-29T23:27:00.000+02:00</published><updated>2010-03-29T23:28:15.168+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='app'/><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='compiler'/><category scheme='http://www.blogger.com/atom/ns#' term='AOT'/><title type='text'>Exporting and importing compiler output</title><content type='html'>I am probably not the only person who had faced the following problem – if you are doing some major change, like renaming of a table or a class you are compiling the AOT to get all the places where references to renamed object should be changed. The problem is that the resulting error log can be easily lost, for example, by pressing reset or closing AX by accident. Unfortunately in this case it cannot be restored easily, only with yet another AOT compilation. To avoid recompilation I found out for myself great functionality that allows to export and import compiler error logs. It is accessible from the Compiler output window-&gt;Import/Export.&lt;br /&gt;It is also interesting fact that AX uses html format to store error logs.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-4775799302396398318?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/4775799302396398318/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/03/exporting-and-importing-compiler-output.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/4775799302396398318'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/4775799302396398318'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/03/exporting-and-importing-compiler-output.html' title='Exporting and importing compiler output'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-1628729363092794252</id><published>2010-03-26T19:48:00.002+01:00</published><updated>2010-03-26T20:03:04.809+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='documentation'/><category scheme='http://www.blogger.com/atom/ns#' term='QnA'/><category scheme='http://www.blogger.com/atom/ns#' term='X++ editor'/><title type='text'>Editor scripts</title><content type='html'>I’ve noticed that there are only two editor scripts that I am using during development. First one is XML documentation template (Scripts\Documentation\Header Template) – very nice script for documenting classes\methods. It automatically generates documentation sections for description, input and output parameters and exceptions. The second one is parm method template (Scripts\Template\Method\Parm) – creates a standard AX getter\setter. The rest of the scripts are either to specific and need for them doesn’t appear in my daily work or they are doing too simple things and it is faster for me just type them.&lt;br /&gt;What editor scripts are you using from standard AX?&lt;br /&gt;What known editor scripts extensions are you using?&lt;br /&gt;What kind of custom editor scripts are you implementing for yourself?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-1628729363092794252?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/1628729363092794252/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/03/editor-scripts.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/1628729363092794252'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/1628729363092794252'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/03/editor-scripts.html' title='Editor scripts'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-1043869359591319551</id><published>2010-03-25T22:19:00.001+01:00</published><updated>2010-03-25T22:21:10.557+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Global class'/><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><title type='text'>Global::isType</title><content type='html'>The easiest way to determine if an EDT extends another EDT (not necessarily directly) is to use Global::isType() method.&lt;br /&gt;For example:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;isType(extendedtypenum(PurchUnit), extendedtypenum(UnitIDBase));&lt;/span&gt;&lt;br /&gt;give true, since PurchUnit extends UnitID, which extends UnitIDBase.&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;isType(extendedtypenum(ABCModelType), extendedtypenum(NoYesId));&lt;/span&gt;&lt;br /&gt;gives false, since ABCModelType and NoYesId are in different hierarchies.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-1043869359591319551?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/1043869359591319551/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/03/globalistype.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/1043869359591319551'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/1043869359591319551'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/03/globalistype.html' title='Global::isType'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-2311490554640621262</id><published>2010-03-24T19:17:00.002+01:00</published><updated>2010-03-24T19:21:56.801+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='forms'/><category scheme='http://www.blogger.com/atom/ns#' term='AX 2009'/><category scheme='http://www.blogger.com/atom/ns#' term='grid'/><title type='text'>DefaultAction property on grids</title><content type='html'>DefaultAction property on the form grid control was added in AX 2009. It allows to specify a menu item from the form which will be executed on the double click event on the grid. Originally this feature targets list pages – it allows to open details forms for the selected record on the list page. However, it can be used for any grid on any form. The only limitation is that grid should not be editable.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-2311490554640621262?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/2311490554640621262/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/03/defaultaction-property-on-grids.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/2311490554640621262'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/2311490554640621262'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/03/defaultaction-property-on-grids.html' title='DefaultAction property on grids'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-9025529880565569402</id><published>2010-03-23T23:42:00.003+01:00</published><updated>2010-03-23T23:47:17.854+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='union'/><category scheme='http://www.blogger.com/atom/ns#' term='query'/><category scheme='http://www.blogger.com/atom/ns#' term='AX 2009'/><title type='text'>Union queries</title><content type='html'>In AX 2009 a great enhancement was introduced to the queries – support for union operation was added. A new property was added to the AOT queries – QueryType. It has two values:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Join – regular query&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Union – union query&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;In the case of union query several datasources of the same type (the same table) can be placed on the query datasource root node. Note, that all datasources except the first one will have a property called UnionType, which specifies what should be done with duplicated records that may appear because of union:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Union – remove duplicated records&lt;/li&gt;&lt;br /&gt;&lt;li&gt;UnionAll – keep duplicated records&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Additional datasources can be added to the deeper levels of the query under any datasource that participates in union. Those will be translated into joins. The only allowed join types for the union query are exists and notexists join.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_M4Xc6T_bNcg/S6lERN8BHSI/AAAAAAAAEz8/P0sR1n5h1Gk/s1600-h/UnionQuery.png"&gt;&lt;img border="0" alt="" src="http://1.bp.blogspot.com/_M4Xc6T_bNcg/S6lERN8BHSI/AAAAAAAAEz8/P0sR1n5h1Gk/s1600/UnionQuery.png" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-9025529880565569402?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/9025529880565569402/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/03/union-queries.html#comment-form' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/9025529880565569402'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/9025529880565569402'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/03/union-queries.html' title='Union queries'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_M4Xc6T_bNcg/S6lERN8BHSI/AAAAAAAAEz8/P0sR1n5h1Gk/s72-c/UnionQuery.png' height='72' width='72'/><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-3968748430276683172</id><published>2010-03-22T20:03:00.003+01:00</published><updated>2010-03-22T20:29:14.949+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='app'/><category scheme='http://www.blogger.com/atom/ns#' term='tool'/><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='wizard'/><title type='text'>Wizard wizard</title><content type='html'>There is a tool in AX that allows automatically generate code for new AX wizards. This tool is accessible from the Main menu\Tools\Development tools\Wizards\Wizard Wizard. By using this tool a new project with a wizard form, controlling class and a menu item will be generated. There will be also several methods created on the controlling class and on the form. Actually, the code generated by the tool is a good start for implementing a new wizard.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-3968748430276683172?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/3968748430276683172/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/03/wizard-wizard.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/3968748430276683172'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/3968748430276683172'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/03/wizard-wizard.html' title='Wizard wizard'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-9222982218304289907</id><published>2010-03-19T16:27:00.004+01:00</published><updated>2010-03-19T16:45:21.933+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='query'/><category scheme='http://www.blogger.com/atom/ns#' term='QnA'/><title type='text'>Query.pack method parameter</title><content type='html'>The comment from &lt;a href="http://axdaily.blogspot.com/2010/03/instantiating-query-object.html#comments"&gt;here&lt;/a&gt; forced me to pay attention to the Boolean parameter on the Query.pack() method which I didn't mention before. It is not obvious what it does by looking at its name - _doCheck. I tried to figure out what it does and I've got the following:&lt;br /&gt;If a query contains DynaLink then calling Query.pack(true) will throw the error: Attempting to pack a query that contains one or more dynamic links.&lt;br /&gt;If a query contains DynaLink then calling Query.pack(false) will succeed and DynaLink will not be stored in the package - it will not appear on a new query created from the package.&lt;br /&gt;&lt;br /&gt;Does anybody have more information on this parameter?&lt;br /&gt;&lt;br /&gt;Example:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;public static void testQueryPack()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;InventItemGroup itemGroup;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Query q1 = new Query();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Query q2;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;QueryBuildDataSource qbds;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;qbds = q1.addDataSource(tablenum(InventTable));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;qbds.addDynalink(fieldnum(InventTable, ItemGroupId), itemGroup, fieldnum(InventItemGroup, ItemGroupId));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;info(qbds.toString());&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;q2 = new Query(q1.pack(false));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;qbds = q2.dataSourceTable(tablenum(InventTable));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;info(qbds.toString());&lt;br /&gt;}&lt;/span&gt;&lt;br /&gt;Result:&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_M4Xc6T_bNcg/S6ObKjLRzdI/AAAAAAAAEz0/kQShsIA-Ogw/s1600-h/DynaLink.png"&gt;&lt;img src="http://1.bp.blogspot.com/_M4Xc6T_bNcg/S6ObKjLRzdI/AAAAAAAAEz0/kQShsIA-Ogw/s1600/DynaLink.png" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-9222982218304289907?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/9222982218304289907/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/03/querypack-method-parameter.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/9222982218304289907'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/9222982218304289907'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/03/querypack-method-parameter.html' title='Query.pack method parameter'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_M4Xc6T_bNcg/S6ObKjLRzdI/AAAAAAAAEz0/kQShsIA-Ogw/s72-c/DynaLink.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-7495616500167955299</id><published>2010-03-18T20:36:00.004+01:00</published><updated>2010-03-18T20:48:52.823+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='debug'/><category scheme='http://www.blogger.com/atom/ns#' term='best practice'/><title type='text'>Debug::assert</title><content type='html'>This method allows to check if some Boolean condition evaluates to true and if it doesn't - stop further execution and show stack trace. Debug::assert() should be used to validate some assumptions made in the code which should never happen if nothing is broken in the application. It means that wrong user input should not be asserted but rather validated by normal if statement and exception should be thrown if the input is wrong. However, if the code relies, for example, on query data source name, which can be broken only in development time - that is a good place to add assert to.&lt;br /&gt;&lt;br /&gt;Example:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Query query = new Query(querystr(Alertsetup));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;QueryBuildDataSource qbds;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;qbds = query.dataSourceName(identifierstr(EventRule));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Debug::assert(qbds != null); &lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-7495616500167955299?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/7495616500167955299/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/03/debugassert.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/7495616500167955299'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/7495616500167955299'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/03/debugassert.html' title='Debug::assert'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-5475442218580602193</id><published>2010-03-17T19:35:00.003+01:00</published><updated>2010-03-17T19:53:01.024+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='query'/><title type='text'>Instantiating query object</title><content type='html'>Constructor of the Query class has default anytype parameter named _source. To my knowledge there are four different ways to use it:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Instantiating an empty query – no parameter value should be specified:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Query q = new Query();&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Instantiating a query based on the AOT query:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Query q = new Query(querystr(Alertsetup));&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Instantiating a query as the copy of another query:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Query q1 = new Query();&lt;br /&gt;Query q2 = new Query(q1);&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Instantiating a query from the container with the packed query&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Query q1 = new Query();&lt;br /&gt;Query q2 = new Query(q1.pack());&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;Is there anything else that can be used as a source for constructing a query?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-5475442218580602193?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/5475442218580602193/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/03/instantiating-query-object.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/5475442218580602193'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/5475442218580602193'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/03/instantiating-query-object.html' title='Instantiating query object'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-1041105815258268565</id><published>2010-03-16T16:38:00.004+01:00</published><updated>2010-03-16T16:52:37.912+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Global class'/><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='virtual companies'/><title type='text'>Global::curExt2dataareaId</title><content type='html'>While working with virtual companies it is needed sometimes to determine what is the actual DataAreaId that will be assigned to the table record if it will be inserted in the current company context. To do that there is the method curExt2dataareaid() on the Global class.&lt;br /&gt;Example:&lt;br /&gt;Let there are 2 companies A and B and the virtual company V that includes both A and B.&lt;br /&gt;If table Unit is shared in the virtual company V and current company is A then&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;curExt2dataareaid(tablenum(Unit)) == 'V'.&lt;/span&gt;&lt;br /&gt;If table Unit is not shared in the virtual company V and current company is A then&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;curExt2dataareaid(tablenum(Unit)) == 'A'.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-1041105815258268565?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/1041105815258268565/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/03/globalcurext2dataareaid.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/1041105815258268565'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/1041105815258268565'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/03/globalcurext2dataareaid.html' title='Global::curExt2dataareaId'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-9045609537563113963</id><published>2010-03-15T20:26:00.005+01:00</published><updated>2010-03-15T20:33:30.256+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='app'/><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='navigation pane'/><category scheme='http://www.blogger.com/atom/ns#' term='QnA'/><category scheme='http://www.blogger.com/atom/ns#' term='MenuItem'/><category scheme='http://www.blogger.com/atom/ns#' term='AOT'/><title type='text'>MenuItem types</title><content type='html'>What is the difference between MenuItem types - Display, Action and Output, except that they reside under different AOT nodes and that different intrinsic functions should be used to access them via reflection?&lt;br /&gt;&lt;br /&gt;I know one - they are displayed with different images in the navigation pane:&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_M4Xc6T_bNcg/S56K4e6tb_I/AAAAAAAAEzU/l9ss_U0zotM/s1600-h/menuitem.png"&gt;&lt;img style="WIDTH: 163px; HEIGHT: 56px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5448945302141497330" border="0" alt="" src="http://3.bp.blogspot.com/_M4Xc6T_bNcg/S56K4e6tb_I/AAAAAAAAEzU/l9ss_U0zotM/s320/menuitem.png" /&gt;&lt;/a&gt;&lt;br /&gt;Are there any other differences?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-9045609537563113963?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/9045609537563113963/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/03/menuitem-types.html#comment-form' title='20 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/9045609537563113963'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/9045609537563113963'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/03/menuitem-types.html' title='MenuItem types'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_M4Xc6T_bNcg/S56K4e6tb_I/AAAAAAAAEzU/l9ss_U0zotM/s72-c/menuitem.png' height='72' width='72'/><thr:total>20</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-3359430657013106760</id><published>2010-03-12T23:30:00.000+01:00</published><updated>2010-03-13T00:12:07.108+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='xRefs'/><category scheme='http://www.blogger.com/atom/ns#' term='kernel'/><title type='text'>Cross-references for kernel classes</title><content type='html'>It is good to know that it is possible to view cross-references for kernel classes, tables, enums, etc. This can be done by using "System Documentation" node in AOT.&lt;br /&gt;For example, to view cross-references for lookupField method of the Args class you can do the following:&lt;br /&gt;1) Navigate to the "System Documentation\Classes\Args\lookupField" AOT node&lt;br /&gt;2) Open context menu&lt;br /&gt;3) Navigate Add-Ins\Cross-reference\Used by&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-3359430657013106760?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/3359430657013106760/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/03/cross-references-for-kernel-classes.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/3359430657013106760'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/3359430657013106760'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/03/cross-references-for-kernel-classes.html' title='Cross-references for kernel classes'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-7889792875947239638</id><published>2010-03-11T23:29:00.002+01:00</published><updated>2010-03-11T23:37:31.803+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='table'/><title type='text'>SaveContents property on the table fields</title><content type='html'>I've opened for myself the new great property of the table fields - SaveContents. This property defines whether field will be physically created in the database (Yes) or will it just be present on the table buffer (No). It can be quite useful to have such kind of fields if you want to avoid redundancies in the database but you need to perform some complex calculations/queries and use their results on the table buffer. To get these fields filled with values you have to override the postLoad() method on the table.&lt;br /&gt;For example, let you have the table:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Table1&lt;br /&gt;IntField1 : Int, SaveContents = Yes&lt;br /&gt;IntField2 : Int, SaveContents = Yes&lt;br /&gt;IntField3 : Int, SaveContents = No&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;If you'll override postLoad() method on the Table1 like:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;public void postLoad()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;this.IntField3 = this.IntField1 + this.IntField2;&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;then you'll get the IntField3 field filled with the sum of the other two field values. The postLoad() method will be executed on each query on Table1 table. That is huge drawback because of serious performance degradation, however it still can be useful sometimes.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-7889792875947239638?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/7889792875947239638/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/03/savecontents-property-on-table-fields.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/7889792875947239638'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/7889792875947239638'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/03/savecontents-property-on-table-fields.html' title='SaveContents property on the table fields'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-4705421589797333331</id><published>2010-03-10T20:16:00.002+01:00</published><updated>2010-03-10T20:19:31.439+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='bug'/><category scheme='http://www.blogger.com/atom/ns#' term='compiler'/><category scheme='http://www.blogger.com/atom/ns#' term='best practice'/><title type='text'>Define overwrites</title><content type='html'>It is a little bit weird how X++ compiler handles the case when macros with the same name are defined in the class declaration of a class and in the one of its methods. The expected behavior for me is to either not allow to do that or to have a macro from class declaration to be applicable everywhere except for the method where it is redefined. But in AX the value defined in the method will overwrite the value defined in the class declaration and will be the same in all methods.&lt;br /&gt;Example:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;class TestDefine&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#define.A(‘A’)&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public void method1()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;info(#A);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public void method2()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#define.A(‘B’)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;info(#A);&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;If method1 or method2 will be called the ‘B’ will be received in the infolog and not ‘A’.&lt;br /&gt;&lt;br /&gt;The next question will be what if define is overwritten in several methods. The answer is that the result is undetermined. It depends on X++ compiler internal flow and cannot be predicted. So, just avoid such constructions and even better avoid defines at all.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-4705421589797333331?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/4705421589797333331/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/03/define-overwrites.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/4705421589797333331'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/4705421589797333331'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/03/define-overwrites.html' title='Define overwrites'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-2354171327633718875</id><published>2010-03-09T23:19:00.002+01:00</published><updated>2010-03-09T23:23:27.423+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='table'/><title type='text'>TableGroup property</title><content type='html'>The TableGroup property on tables not just categorizes them. I know two cases where this property has influence on the functionality:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Forceliterals keyword is added to the queries which contain two or more joined tables of group Miscellaneous, Transaction, WorksheetHeader or WorksheetLine.&lt;/li&gt;&lt;li&gt;Record templates can be created only for the tables of Main or Group groups.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;Are there any other cases where this property affects functionality?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-2354171327633718875?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/2354171327633718875/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/03/tablegroup-property.html#comment-form' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/2354171327633718875'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/2354171327633718875'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/03/tablegroup-property.html' title='TableGroup property'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-6496695048418493308</id><published>2010-03-08T20:14:00.000+01:00</published><updated>2010-03-08T20:15:47.879+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='labels'/><title type='text'>Getting label text in different languages</title><content type='html'>Sometimes it is needed to get a label text in a language that is different from the current one. To do that the labelId2String method of the SysLabel class can be used.&lt;br /&gt;Example:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;SysLabel::labelId2String(literalstr('@SYS1'), 'en-us'); &lt;/span&gt;&lt;br /&gt;Gives: Time transactions&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;SysLabel::labelId2String(literalstr('@SYS1'), 'de'); &lt;/span&gt;&lt;br /&gt;Gives: Zeit Transaktionen&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-6496695048418493308?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/6496695048418493308/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/03/getting-label-text-in-different.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/6496695048418493308'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/6496695048418493308'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/03/getting-label-text-in-different.html' title='Getting label text in different languages'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-2806227325009125981</id><published>2010-03-05T18:56:00.004+01:00</published><updated>2010-03-05T19:15:23.820+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='debug'/><title type='text'>xSession::xppCallStack method</title><content type='html'>This method allows to get the current call stack - all caller method names and line numbers. For example, calling xSession::xppCallStack() from the line 13 at the Tutorial_RunbaseBatch.dialog() method will give the following call stack:&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_M4Xc6T_bNcg/S5FJqMIP7MI/AAAAAAAAEzE/gwid8_yzevk/s1600-h/xppCallStack.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 236px; height: 320px;" src="http://3.bp.blogspot.com/_M4Xc6T_bNcg/S5FJqMIP7MI/AAAAAAAAEzE/gwid8_yzevk/s320/xppCallStack.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5445214413626797250" /&gt;&lt;/a&gt;&lt;br /&gt;Actually I even found one nice practical application for it - SysTestAssert class can be modified so that it will display the line number where assertion has failed. It becomes much easier to debug unit tests with such modification.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-2806227325009125981?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/2806227325009125981/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/03/xsessionxppcallstack-method.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/2806227325009125981'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/2806227325009125981'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/03/xsessionxppcallstack-method.html' title='xSession::xppCallStack method'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_M4Xc6T_bNcg/S5FJqMIP7MI/AAAAAAAAEzE/gwid8_yzevk/s72-c/xppCallStack.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-5536479928053680992</id><published>2010-03-04T23:52:00.004+01:00</published><updated>2010-03-05T00:02:07.726+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='query'/><category scheme='http://www.blogger.com/atom/ns#' term='best practice'/><title type='text'>Global::queryValue method</title><content type='html'>This method translates anything into the correct query range value, so you don't have to care about how UTCDateTime value should be converted into a string or which symbols require slash before them. It is the best practice to always use this method when query range is assigned a value, even if the value is string.&lt;br /&gt;&lt;br /&gt;Note, that queryValue('') will return the following string '""' (two double quotes) which will give empty string range value. If you want to clear the range you'll have to assign it's value with empty string directly.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-5536479928053680992?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/5536479928053680992/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/03/globalqueryvalue-method.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/5536479928053680992'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/5536479928053680992'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/03/globalqueryvalue-method.html' title='Global::queryValue method'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-402825174841507586</id><published>2010-03-03T19:41:00.003+01:00</published><updated>2010-03-03T22:10:18.914+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='documentation'/><category scheme='http://www.blogger.com/atom/ns#' term='kernel'/><category scheme='http://www.blogger.com/atom/ns#' term='AOT'/><title type='text'>System Documentation</title><content type='html'>It is known fact that in AX there are quite a lot of kernel classes, tables, data types, functions, etc. that are not visible in the AOT but can be used from the code. For example, class Args. There is a nice way to get an overview of all this stuff - in the System Documentation node in the AOT. The full list of all kernel objects and functions can be found there. And actually some of them have nice documentation - the one that can be found on MSDN.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-402825174841507586?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/402825174841507586/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/03/system-documentation.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/402825174841507586'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/402825174841507586'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/03/system-documentation.html' title='System Documentation'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-1729413702427907547</id><published>2010-03-02T17:09:00.002+01:00</published><updated>2010-03-02T17:13:23.025+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='DateTimeUtil'/><category scheme='http://www.blogger.com/atom/ns#' term='UTCDateTime'/><title type='text'>Defining UTCDateTime constants</title><content type='html'>I was always using DateTimeUtil class to set a specific UTCDateTime value:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;dateTime = DateTimeUtil::newDateTime(02\03\2010, 17*3600+30*60);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;But it appeared that there is an easier way to define UTCDateTime constant:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;dateTime = 2010-03-02T17:30:00;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-1729413702427907547?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/1729413702427907547/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/03/defining-utcdatetime-constants.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/1729413702427907547'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/1729413702427907547'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/03/defining-utcdatetime-constants.html' title='Defining UTCDateTime constants'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-2237773430163275983</id><published>2010-03-01T20:26:00.003+01:00</published><updated>2010-03-01T20:33:38.057+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Global class'/><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><title type='text'>Global::exceptionTextFallThrough</title><content type='html'>This method looks really strange since it does nothing! However, this one is still quite useful. Sometimes there is a need to display text of the error that was thrown in the infolog but without preventing further code execution. For this purpose the following code can be written:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;try&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;throw error("Error");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;catch&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;br /&gt;The problem with this code is that compiler will generate a warning regarding empty compound statement (the one after catch). To avoid this warning exceptionTextFallThrough() method should be used.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-2237773430163275983?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/2237773430163275983/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/03/globalexceptiontextfallthrough.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/2237773430163275983'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/2237773430163275983'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/03/globalexceptiontextfallthrough.html' title='Global::exceptionTextFallThrough'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-7815410961232729923</id><published>2010-02-26T18:26:00.003+01:00</published><updated>2010-02-26T18:39:09.368+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='query'/><title type='text'>, and ,! operators in query ranges</title><content type='html'>&lt;a href="http://2.bp.blogspot.com/_M4Xc6T_bNcg/S4gEWLurkUI/AAAAAAAAEyg/3459t3ezFxU/s1600-h/QueryRange.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 130px;" src="http://2.bp.blogspot.com/_M4Xc6T_bNcg/S4gEWLurkUI/AAAAAAAAEyg/3459t3ezFxU/s320/QueryRange.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5442604928829460802" /&gt;&lt;/a&gt;&lt;br /&gt;If a query range value is "A,B" it will be translated into the SQL expression (ItemId='A') OR (ItemId='B'), so both items with ID A and B will be selected. If a query range is "!A" than it will be translated into SQL expression NOT (ItemId='A'), so items with ID not equal to A will be selected. But, if a query range is "A,!B" it will be translated not into (ItemId='A') OR NOT (ItemId='B') as it seems to be correct. It will be translated into (ItemId='A') AND NOT (ItemId='B'). Despite that such behavior looks strange it seems to be a feature, not a bug. So it is just better to understand "," and ",!" as different operators - OR and AND NOT.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-7815410961232729923?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/7815410961232729923/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/02/and-operators-in-query-ranges.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/7815410961232729923'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/7815410961232729923'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/02/and-operators-in-query-ranges.html' title=', and ,! operators in query ranges'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_M4Xc6T_bNcg/S4gEWLurkUI/AAAAAAAAEyg/3459t3ezFxU/s72-c/QueryRange.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-4996412024207319405</id><published>2010-02-25T17:05:00.003+01:00</published><updated>2010-02-26T00:15:22.462+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RunBase'/><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><title type='text'>Handling events of the RunBase dialog controls</title><content type='html'>It is required sometimes to handle events of the controls on the RunBase dialog, like modified or lookup. Since these controls are added to the dialog in runtime there seems to be no place where event handlers can be added. However there is a possibility to do that. To do that dialogPostRun method should be overridden and contain the following code:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;public void dialogPostRun(DialogRunbase _dialog)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;super(_dialog);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_dialog.dialogForm().formRun().controlMethodOverload(true);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_dialog.dialogForm().formRun().controlMethodOverloadObject(this);&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Note, that in the code above the RunBase class itself is used as event handler (by passing this to the controlMethodOverloadObject() method), but it is possible to create a separate class for handling events.&lt;br /&gt;&lt;br /&gt;Afterwards event handlers can be created as method with specific name: &lt;control&gt;_&lt;event&gt;. Control name can be found in the dialog user setup. For example, the following method will handle modify event of the first field control on the dialog:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;public void fld1_1_modified()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Object control;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;control = dialog.formRun().controlCallingMethod();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(control.modified())&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;info(“Modified triggered!”);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-4996412024207319405?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/4996412024207319405/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/02/handling-events-of-runbase-dialog.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/4996412024207319405'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/4996412024207319405'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/02/handling-events-of-runbase-dialog.html' title='Handling events of the RunBase dialog controls'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-1950128672167971043</id><published>2010-02-24T17:10:00.004+01:00</published><updated>2010-02-25T09:10:29.734+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='forms'/><category scheme='http://www.blogger.com/atom/ns#' term='AOT'/><title type='text'>Synchronizing form data source with table changes</title><content type='html'>After a new field of a field group was added to a table, all forms that contain this table as a data source are not automatically updated with this new field or field group. Because of that one cannot use drag and drop to place the field on the form design which makes form development more complex. But there is an easy way to synchronize form data sources with the latest changes to the table. To do that one should right click on the form node in AOT and pick "Restore" command which will do the synchronization.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-1950128672167971043?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/1950128672167971043/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/02/synchronizing-form-data-source-wit.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/1950128672167971043'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/1950128672167971043'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/02/synchronizing-form-data-source-wit.html' title='Synchronizing form data source with table changes'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-3584235895559956434</id><published>2010-02-23T19:32:00.005+01:00</published><updated>2010-02-23T19:39:32.980+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='forms'/><category scheme='http://www.blogger.com/atom/ns#' term='AX 2009'/><category scheme='http://www.blogger.com/atom/ns#' term='best practice'/><title type='text'>Caching edit methods</title><content type='html'>There was a great improvement done to the form datasource caching in AX 2009 - it is possible now to cache not only display methods but edit methods too. The caching of the edit methods can be performed in the same way as caching of display methods - by using FormDataSource.cacheAddMethod() method.&lt;br /&gt;Despite that great improvement a lot of forms in AX 2009 haven't consumed it. So if you are looking for a solution to speed up existing AX 2009 form, edit methods that are not cached is a good place to look at.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-3584235895559956434?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/3584235895559956434/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/02/caching-edit-methods.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/3584235895559956434'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/3584235895559956434'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/02/caching-edit-methods.html' title='Caching edit methods'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-4933398666414553231</id><published>2010-02-22T19:04:00.004+01:00</published><updated>2010-02-22T19:33:08.947+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='bug'/><title type='text'>X++ real vs numeric(32,16)</title><content type='html'>It is an interesting fact that X++ real type is not fully compatible with the table field real type. The problem is that in the database numeric(32,16) data type is used to store fields of the real type. Numeric(32,16) data type stores numbers with no more than 32 digits total and no more than 16 digits after the decimal point, so value 10&lt;sup&gt;33&lt;/sup&gt; cannot be stored with this data type. X++ real type is floating-point type and can store values in the range from -10&lt;sup&gt;127&lt;/sup&gt; to 10&lt;sup&gt;127&lt;/sup&gt;.&lt;br /&gt;The following code execution will fail:&lt;br /&gt;public static void testReal()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbspInventTrans inventTrans;&lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbspreal realValue = 1.0e33;&lt;br /&gt;&lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbspinventTrans.Qty = realValue;&lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbspinventTrans.doInsert();&lt;br /&gt;}&lt;br /&gt;With the following exception:&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_M4Xc6T_bNcg/S4LLJ7v173I/AAAAAAAAEx4/SVDLof2yyO8/s1600-h/RealNumeric3216.png"&gt;&lt;img style="WIDTH: 320px; HEIGHT: 26px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5441134671334600562" border="0" alt="" src="http://1.bp.blogspot.com/_M4Xc6T_bNcg/S4LLJ7v173I/AAAAAAAAEx4/SVDLof2yyO8/s320/RealNumeric3216.png" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-4933398666414553231?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/4933398666414553231/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/02/x-real-vs-numeric3216.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/4933398666414553231'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/4933398666414553231'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/02/x-real-vs-numeric3216.html' title='X++ real vs numeric(32,16)'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_M4Xc6T_bNcg/S4LLJ7v173I/AAAAAAAAEx4/SVDLof2yyO8/s72-c/RealNumeric3216.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-2985618673765268317</id><published>2010-02-19T14:00:00.000+01:00</published><updated>2010-02-19T14:00:00.346+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='AOT'/><title type='text'>Getting project TreeNode iterator</title><content type='html'>It is extremely not obvious how to get TreeNode iterator pointing to a project node. Projects cannot be accessed from the AOT root node which is retrieved by TreeNode::rootNode() method. To get to projects root node the following method should be used: infolog.projectRootNode(). Afterwards projects can be traversed from there.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-2985618673765268317?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/2985618673765268317/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/02/getting-project-treenode-iterator.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/2985618673765268317'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/2985618673765268317'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/02/getting-project-treenode-iterator.html' title='Getting project TreeNode iterator'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-8330548225082900802</id><published>2010-02-18T15:00:00.001+01:00</published><updated>2010-02-18T15:00:05.335+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='query'/><category scheme='http://www.blogger.com/atom/ns#' term='AX 2009'/><title type='text'>SysQueryRangeUtil class</title><content type='html'>The SysQueryRangeUtil class is just the great enhancement to the AOT queries made in AX 2009. It is possible now to specify a range on the AOT query with the value taken from a method's return. The requirements for such range method are quite simple: the method should be static, return string, be a member of the SysQueryRangeUtil class and not be related on the data fetched by the query.&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_M4Xc6T_bNcg/S3vEAAfNvtI/AAAAAAAAExg/4o4aVnjVyrE/s1600-h/SysQueryRangeUtil.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 170px;" src="http://3.bp.blogspot.com/_M4Xc6T_bNcg/S3vEAAfNvtI/AAAAAAAAExg/4o4aVnjVyrE/s320/SysQueryRangeUtil.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5439156479389974226" /&gt;&lt;/a&gt;&lt;br /&gt;There are quite a lot of useful methods on the SysQueryRangeUtil class available out of the box, like currentEmployeeId() - returns current employee ID, dayRange() - allows to specify date interval around current date, etc. And it is possible to add a new custom method to this class as well.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-8330548225082900802?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/8330548225082900802/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/02/sysqueryrangeutil-class.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/8330548225082900802'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/8330548225082900802'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/02/sysqueryrangeutil-class.html' title='SysQueryRangeUtil class'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_M4Xc6T_bNcg/S3vEAAfNvtI/AAAAAAAAExg/4o4aVnjVyrE/s72-c/SysQueryRangeUtil.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-1939796227945097488</id><published>2010-02-17T13:07:00.004+01:00</published><updated>2010-02-17T13:32:33.342+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='temporary table'/><category scheme='http://www.blogger.com/atom/ns#' term='client server'/><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='best practice'/><category scheme='http://www.blogger.com/atom/ns#' term='table'/><title type='text'>Temporary table residing tier</title><content type='html'>Temporary table resides on the tier where the first insert happened into it. Since temporary table data generation usually requires quite a lot of database transactions it makes sense to instantiate it on the server. However, if a temporary table is displayed on a form it makes sense to instantiate it on the client to avoid chattiness during displaying of the form. But anyway with such approach there will be a lot of client-server calls either during data generation or during displaying. To avoid that the following approach can be used:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Create a temporary table instance on the server and fill it with data.&lt;/li&gt;&lt;li&gt;Place all records from the table to a container and pass it to the client.&lt;/li&gt;&lt;li&gt;Create a new temporary table instance on the client and fill it with data from the container.&lt;/li&gt;&lt;li&gt;Use the client temporary table instance to display on a form.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt; &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-1939796227945097488?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/1939796227945097488/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/02/temporary-table-residing-tier.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/1939796227945097488'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/1939796227945097488'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/02/temporary-table-residing-tier.html' title='Temporary table residing tier'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-3830938852424523213</id><published>2010-02-16T18:42:00.001+01:00</published><updated>2010-02-16T18:43:30.952+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='bug'/><category scheme='http://www.blogger.com/atom/ns#' term='best practice'/><title type='text'>Priority of Boolean operations</title><content type='html'>In X++ Boolean &amp;&amp; and || operations have the same priority. That is not the case in other languages where &amp;&amp; has higher priority than ||. So adding additional parenthesis to make sure that code works as expected is a good idea.&lt;br /&gt;Example: (true || false &amp;&amp; false) will be evaluated to false in X++, but in C# it will be evaluated to true.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-3830938852424523213?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/3830938852424523213/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/02/priority-of-boolean-operations.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/3830938852424523213'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/3830938852424523213'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/02/priority-of-boolean-operations.html' title='Priority of Boolean operations'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-5261614379481831631</id><published>2010-02-15T18:21:00.002+01:00</published><updated>2010-02-15T18:42:22.212+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='intrinsic functions'/><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='best practice'/><title type='text'>Messages mentioning table or field</title><content type='html'>It is the best practice to use both table or field UI name and system name in error messages. For example, the standard “The record already exists” message looks like:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Cannot create a record in Inventory model groups (InventModelGroup). Inventory model group: Std, Standard. The record already exists.&lt;br /&gt;&lt;/span&gt;So both UI name (Inventory model groups) and system name (InventModelGroup) appear in the message.&lt;br /&gt;To retrieve those names tablepname() and tablestr() functions can be used correspondingly. For the fields there are similar functions: fieldpname() and fieldstr().&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-5261614379481831631?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/5261614379481831631/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/02/messages-mentioning-table-or-field.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/5261614379481831631'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/5261614379481831631'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/02/messages-mentioning-table-or-field.html' title='Messages mentioning table or field'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-1317052365673126288</id><published>2010-02-12T19:33:00.002+01:00</published><updated>2010-02-12T19:36:50.055+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><title type='text'>Call stack size</title><content type='html'>Dynamics AX call stack size is equal to 401 function call. It looks like it is idependent from function input and output parameters.&lt;br /&gt;Actually 401 is quite a small number, so be careful with implementing recursive algorithms.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-1317052365673126288?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/1317052365673126288/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/02/call-stack-size.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/1317052365673126288'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/1317052365673126288'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/02/call-stack-size.html' title='Call stack size'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-7502848333625086126</id><published>2010-02-11T17:31:00.004+01:00</published><updated>2010-02-11T17:53:54.939+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='bug'/><category scheme='http://www.blogger.com/atom/ns#' term='table'/><title type='text'>Delete actions and multiple relations</title><content type='html'>If one table has several relations to another table delete action will not work properly. In such case delete action will be triggered for only one of the relations. So, in the case of multiple relations one should write his own cascading or restricting logic in the delete method.&lt;br /&gt;An example can be found in Unit and UnitConvert tables. UnitConvert table has two relations to the Unit table – from unit and to unit. Table Unit has cascading delete action for the UnitConvert table. However, if a unit will be deleted, only unit conversions with from unit equal to the deleted one will be deleted. Conversions with to unit equal to the deleted one will survive.&lt;br /&gt;Example of correct implementation can be found in InventTestEmplResponsible and EmplTable. EmplTable has delete method overridden to perform manual delete in the InventTestEmplResponsible table.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-7502848333625086126?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/7502848333625086126/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/02/delete-actions-and-multiple-relations.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/7502848333625086126'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/7502848333625086126'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/02/delete-actions-and-multiple-relations.html' title='Delete actions and multiple relations'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-7338309774565824382</id><published>2010-02-10T20:13:00.005+01:00</published><updated>2010-02-10T20:47:34.646+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='query'/><category scheme='http://www.blogger.com/atom/ns#' term='index'/><category scheme='http://www.blogger.com/atom/ns#' term='table'/><title type='text'>Indexes and data fetching</title><content type='html'>Indexes can speed up not only record lookup but data fetching too. If all fields that participate in a query are present in the index, database will not start retrieving actual table data but will use index values only. It is quite important factor to consider during table’s indexes tuning.&lt;br /&gt;Example:&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_M4Xc6T_bNcg/S3MLy9oAtlI/AAAAAAAAExA/xtrbKglLE58/s1600-h/table1.png"&gt;&lt;img style="WIDTH: 202px; HEIGHT: 205px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5436702145330067026" border="0" alt="" src="http://1.bp.blogspot.com/_M4Xc6T_bNcg/S3MLy9oAtlI/AAAAAAAAExA/xtrbKglLE58/s320/table1.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;select maxof(Quantity) from table1&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;where&amp;nbsp;&amp;nbsp;table1.Key &gt;= 100000&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;amp;&amp;amp;&amp;nbsp;table1.Key &lt;= 300000;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;The query above runs around 320 ms on my machine with 1M records in Table1 when index on the Table1 contains only Key field. If Quantity field is added to the index execution time drops to 70 ms.&lt;br /&gt;&lt;br /&gt;Note: It is important to mention that the difference appears only if lookup happens using non-cluster index. Otherwise query execution time will be almost the same because cluster index is stored together with table data and it is cheap to retrieve it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-7338309774565824382?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/7338309774565824382/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/02/indexes-and-data-fetching.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/7338309774565824382'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/7338309774565824382'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/02/indexes-and-data-fetching.html' title='Indexes and data fetching'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_M4Xc6T_bNcg/S3MLy9oAtlI/AAAAAAAAExA/xtrbKglLE58/s72-c/table1.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-6185098388605664429</id><published>2010-02-09T18:34:00.005+01:00</published><updated>2010-02-10T20:46:45.768+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='query'/><category scheme='http://www.blogger.com/atom/ns#' term='bug'/><title type='text'>Intrinsic functions in queries</title><content type='html'>The following code won't compile in AX.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;select extCodeTable&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;where extCodeTable.ExtCodeTableId == tablenum(CompanyInfo)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;join extCodeValueTable&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;where extCodeValueTable.ExtCodeId == extCodeTable.ExtCodeId;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The reason for that is the call to tablenum(CompanyInfo) - compiler doesn't not allow it inside queries. The simplest workaround is to define a variable, assign it with tablenum(CompanyInfo) value and use it in the query.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-6185098388605664429?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/6185098388605664429/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/02/intrinsic-functions-in-queries.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/6185098388605664429'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/6185098388605664429'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/02/intrinsic-functions-in-queries.html' title='Intrinsic functions in queries'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-858343511776993650</id><published>2010-02-08T17:03:00.005+01:00</published><updated>2010-02-09T09:27:41.787+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='DateTimeUtil'/><category scheme='http://www.blogger.com/atom/ns#' term='AX 2009'/><category scheme='http://www.blogger.com/atom/ns#' term='UTCDateTime'/><title type='text'>Conversion from UTCDateTime to Date or Time</title><content type='html'>One should be very careful with converting an UTCDateTime value to a Date and/or Time value or vice versa. &lt;br /&gt;The problem is that values of type UTCDateTime are stored in the database in UTC time zone and in code they are accessible in UTC time zone too. But in the UI UTCDateTime values are displayed in user preferred time zone in most cases. Date and Time values are not related to any time zone, so in fact both stored and displayed values are equal. &lt;br /&gt;Because of that each field or variable of type Date or Time should be strictly associated with some fixed time zone (in most cases it makes sense to associate it with user preferred time zone because it’s what user see in the UI) and explicit conversion should always be performed during assignments or comparisons. There are special methods in DateTimeUtil class to switch time zones. &lt;br /&gt;Here is an example of correct conversion between UTCDateTime value and Date and Time value which is associated with user preferred time zone:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;public static void testDateTimeConversion()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;utcDateTime dateTime;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;date dateInUserTimeZone;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;TimeOfDay timeInUserTimeZone;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;dateTime = DateTimeUtil::utcNow();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;dateInUserTimeZone = DateTimeUtil::date(DateTimeUtil::applyTimeZoneOffset(dateTime, DateTimeUtil::getUserPreferredTimeZone()));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;timeInUserTimeZone = DateTimeUtil::time(DateTimeUtil::applyTimeZoneOffset(dateTime, DateTimeUtil::getUserPreferredTimeZone()));&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;dateTime = DateTimeUtil::newDateTime(dateInUserTimeZone, timeInUserTimeZone, DateTimeUtil::getUserPreferredTimeZone());&lt;br /&gt;} &lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-858343511776993650?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/858343511776993650/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/02/conversion-from-utcdatetime-to-date-or.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/858343511776993650'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/858343511776993650'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/02/conversion-from-utcdatetime-to-date-or.html' title='Conversion from UTCDateTime to Date or Time'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-1593830622698359338</id><published>2010-02-05T18:05:00.002+01:00</published><updated>2010-02-05T19:05:50.467+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='QnA'/><title type='text'>Moving code execution from client to server</title><content type='html'>This post replies to &lt;a href="http://axdaily.blogspot.com/2010/01/globalisrunningonserver.html?showComment=1265341924353#c2136368069072815907"&gt;this&lt;/a&gt; question from the comments.&lt;br /&gt;&lt;br /&gt;There are two ways to move the execution of some code from client to server. Choosing one way or another depends on the purpose and complexity of the code to be moved.&lt;br /&gt;&lt;br /&gt;Simple way - static server method.&lt;br /&gt;This one is applicable when the code to be executed on server does not affect owning object's state. For example, if MyClass class has the following method run() :&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;public void run()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;while select forupdate table1&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;table1.Field1 = instanceMember1;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;table1.Field2 = instanceMember2;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;table1.update();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;The code depends on the object state – instanceMember1 and instanceMember2, but does not modify it. In this case code can be rewritten in the following way.&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;public void run()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MyClass::runOnServer(instanceMember1, instanceMember2);&lt;br /&gt;}&lt;br /&gt;private static server void runOnServer(SomeType1 _arg1, SomeType2 _arg2)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;while select forupdate table1&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;table1.Field1 = _arg1;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;table1.Field2 = _arg2;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;table1.update();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Complex way – serialization.&lt;br /&gt;This one should be used when the job to be moved on server modifies object state. In this case the client-side object should be serialized to some data structure -package (for example, container in the standard pack\unpack serialization approach). Then a new instance of the same class as client-side object should be created on the server and de-serialized from the package – so we get exactly the same objects on client and server. After that the job should be executed on the server-side object. Then server-side object is serialized to a package and client-side object (the initial one) is de-serialized from the package. So, the client-side and server-side objects are the same again with the state as it should be after job execution.&lt;br /&gt;Example:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;public void run()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;while select forupdate table1&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;table1.Field1 = instanceMember1;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;table1.Field2 = instanceMember2;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;instanceMember1 += 1;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;instanceMember2 += 2;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;table1.update();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;Will be rewritten as:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;public void run()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MyClass myClassOnServer;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (!isRunningOnServer())&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;myClassOnServer = MyClass::constructOnServer();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;myClassOnServer.unpack(this.pack());&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;myClassOnServer.run();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;this.unpack(myClassOnServer.pack());&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;while select forupdate table1&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;table1.Field1 = instanceMember1;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;table1.Field2 = instanceMember2;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;instanceMember1 += 1;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;instanceMember2 += 2;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;table1.update();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;public static server MyClass constructOnServer()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return new MyClass();&lt;br /&gt;}&lt;br /&gt;public container pack()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return [instanceMember1, instanceMember2];&lt;br /&gt;}&lt;br /&gt;public void unpack(container _packedClass)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;instanceMember1 = conpeek(_packedClass, 1);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;instanceMember2 = conpeek(_packedClass, 2);&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;Note, that in this example there will be 4 client-server RPC calls: call of constructOnServer(), unpack(), run() and pack() methods. This number can be reduced to only one call by wrapping all the calls by server static method but in the example it wasn’t done for better readability.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-1593830622698359338?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/1593830622698359338/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/02/moving-code-execution-from-client-to.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/1593830622698359338'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/1593830622698359338'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/02/moving-code-execution-from-client-to.html' title='Moving code execution from client to server'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-7136507333075348586</id><published>2010-02-04T16:57:00.003+01:00</published><updated>2010-02-04T17:08:16.090+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='forms'/><category scheme='http://www.blogger.com/atom/ns#' term='best practice'/><title type='text'>FormDataSource.object method</title><content type='html'>There is a nice way to change a property for all controls on a form that are bound to the same field, for example, hide\unhide or enable\disable. FormDataSource has method object() which accepts field number as parameter and returns an object of type FormDataObject which has several properties to change controls' behavior, like visible(), enabled(), allowEdit() and others.&lt;br /&gt;Example:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;inventBatch_ds.object(fieldnum(InventBatch, ItemId)).visible(false);&lt;/span&gt;&lt;br /&gt;This way to change controls' properties is more preferable than working with individual controls, since it's possible that user will add new controls for the same field using user setup.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-7136507333075348586?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/7136507333075348586/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/02/formdatasourceobject-method.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/7136507333075348586'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/7136507333075348586'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/02/formdatasourceobject-method.html' title='FormDataSource.object method'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-7488763212003580721</id><published>2010-02-03T18:36:00.005+01:00</published><updated>2010-02-03T18:49:02.395+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='useless'/><title type='text'>Weird keywords</title><content type='html'>I've found that I didn't know all the keywords that X++ language has. For example, keywords "window" and "at". And it is probably not so strange, because they are doing the following: position and resize output window. For example, the following code:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;static void weirdKeywordsTest()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;window 20, 6 at 20, 20;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print "Weird keywords";&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pause;&lt;br /&gt;}&lt;/span&gt;&lt;br /&gt;Will position output window somewhere in the center and will make it quite small. Furthermore, the maximal window size that can be achieved by using these keywords is 78x22, which is just slightly bigger than default one and only by number of lines. I have no idea why one might need those. Any suggestions?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-7488763212003580721?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/7488763212003580721/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/02/weird-keywords.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/7488763212003580721'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/7488763212003580721'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/02/weird-keywords.html' title='Weird keywords'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-284545106018228834</id><published>2010-02-02T19:56:00.003+01:00</published><updated>2010-02-02T20:09:58.596+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='forms'/><category scheme='http://www.blogger.com/atom/ns#' term='AX 2009'/><category scheme='http://www.blogger.com/atom/ns#' term='best practice'/><title type='text'>FormButtonManager</title><content type='html'>In AX 2009 a new nice framework was introduced to simplify form buttons enabling\disabling. This framework is primarily used for list pages, however it can be used for regular forms too. Usage of this framework is quite simple. A new class should be created for a form which implements ButtonStateProvider interface. This class will contain methods which define buttons enable\disable rules. After that form buttons should be mapped to the rules using FormButtonManager class. That's pretty much it. The only thing left is to call FormButtonManager.refresh() method on selection changed event to get buttons enabled or disabled according to specified rules.&lt;br /&gt;For more details you can look at SMAAgreementTableListPage and SMAAgreementTableButtonStateProvider class.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-284545106018228834?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/284545106018228834/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/02/formbuttonmanager.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/284545106018228834'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/284545106018228834'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/02/formbuttonmanager.html' title='FormButtonManager'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-552889711024165578</id><published>2010-02-01T17:57:00.006+01:00</published><updated>2010-02-05T09:05:47.441+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Global class'/><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='debug'/><title type='text'>Global::conView</title><content type='html'>It is nice sometimes for debugging purpose to see what is inside a container without starting debugger. There is a method conView on the Global class which allows to do that easily.&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_M4Xc6T_bNcg/S2cMIbt7wbI/AAAAAAAAEw4/ADgUElz43H4/s1600-h/conView.png"&gt;&lt;img style="WIDTH: 231px; HEIGHT: 313px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5433324814464696754" border="0" alt="" src="http://2.bp.blogspot.com/_M4Xc6T_bNcg/S2cMIbt7wbI/AAAAAAAAEw4/ADgUElz43H4/s320/conView.png" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-552889711024165578?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/552889711024165578/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/02/globalconview.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/552889711024165578'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/552889711024165578'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/02/globalconview.html' title='Global::conView'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_M4Xc6T_bNcg/S2cMIbt7wbI/AAAAAAAAEw4/ADgUElz43H4/s72-c/conView.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-7801262085811685787</id><published>2010-01-29T12:57:00.004+01:00</published><updated>2010-02-02T20:09:17.983+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='forms'/><category scheme='http://www.blogger.com/atom/ns#' term='AX 2009'/><category scheme='http://www.blogger.com/atom/ns#' term='best practice'/><title type='text'>FormDataSource.markChanged method</title><content type='html'>In AX 2009 a new method was added to the FormDataSource – markChanged() which is dedicated specifically to handle selection change event. Before that active() method was commonly used for this purpose, however it is not precise and there are cases when selection is changed but active() method is not triggered. It is the most important to use markChanged() instead of active() when multiple records selection needs to be handled.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-7801262085811685787?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/7801262085811685787/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/01/formdatasourcemarkchanged-method.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/7801262085811685787'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/7801262085811685787'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/01/formdatasourcemarkchanged-method.html' title='FormDataSource.markChanged method'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-4070975413066425354</id><published>2010-01-28T15:44:00.004+01:00</published><updated>2010-02-02T20:09:44.765+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='forms'/><category scheme='http://www.blogger.com/atom/ns#' term='best practice'/><title type='text'>PageActivated metod</title><content type='html'>Overriding of tabChanged method on the form Tab control leads to locking of user setup for this tab and all it child controls.&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_M4Xc6T_bNcg/S2GjGdI7JxI/AAAAAAAAEr4/eoS-CPkMbo8/s1600-h/PageActivated.jpg"&gt;&lt;img style="WIDTH: 174px; HEIGHT: 147px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5431801956882130706" border="0" alt="" src="http://4.bp.blogspot.com/_M4Xc6T_bNcg/S2GjGdI7JxI/AAAAAAAAEr4/eoS-CPkMbo8/s320/PageActivated.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;The best practice is to override pageActivated method on the TabPage control which in most cases allows to achieve the same behavior as tabChanged method but does not lock user setup.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-4070975413066425354?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/4070975413066425354/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/01/overriding-of-tabchanged-method-on-form.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/4070975413066425354'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/4070975413066425354'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/01/overriding-of-tabchanged-method-on-form.html' title='PageActivated metod'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_M4Xc6T_bNcg/S2GjGdI7JxI/AAAAAAAAEr4/eoS-CPkMbo8/s72-c/PageActivated.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-4719016223200231402</id><published>2010-01-27T14:40:00.004+01:00</published><updated>2010-01-27T14:58:50.366+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='bug'/><title type='text'>Insert_recordset and EntireCache</title><content type='html'>It is known fact that set-based operations, like insert_recordset, update_recodset and delete_from are falling into row-by-row operations under certain circumstances. For example, if table has insert (update or delete) methods overridden or table has delete actions or aosValidate methods are overridden. To avoid such fallback (of course, if it is acceptable that mentioned logic won't be executed) several methods should be called to disable each of the mentioned cases, for example:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;inventItemGroup.skipDataMethods(true);&lt;br /&gt;inventItemGroup.skipDeleteActions(true);&lt;br /&gt;inventItemGroup.skipAosValidation(true);&lt;br /&gt;&lt;/span&gt;However, if a table’s CacheLookup property is EntireTable and insert method is overridden, insert_recordset operation (and only it) will fall into row-by-row operations despite the mentioned calls. To avoid that cache should be disable too, like:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;inventItemGroup.disableCache(true);&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-4719016223200231402?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/4719016223200231402/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/01/insertrecordset-and-entirecache.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/4719016223200231402'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/4719016223200231402'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/01/insertrecordset-and-entirecache.html' title='Insert_recordset and EntireCache'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-4170799577499164896</id><published>2010-01-26T17:04:00.005+01:00</published><updated>2010-01-26T20:38:17.413+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><title type='text'>Generating a random number</title><content type='html'>It is not so obvious thing - generating random numbers in AX. I found 3 different ways to do that:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Kernel class Random (not visible in AOT). Generates a value in the range [0..32767] by calling nextInt() instance method. &lt;/li&gt;&lt;li&gt;Class RandomGenerate (which extends Random class). Generates a value in the specified range by calling randomInt() instance method.&lt;/li&gt;&lt;li&gt;xGlobal::randomPositiveInt32() method. Generates a value in the range [0..2147483647].&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;Actually, the third way seems to be the most preferable because there is some trick with first two ones. If the new Random class instance will be created each time before calling nextInt(), the output values will be very far from random. For example, the following code:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;static void testRandom(Args _args)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Random  random;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;int     i;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for (i = 0; i &amp;lt; 3; i++)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;random  = new Random();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;info(int2str(random.nextInt()));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;/span&gt;&lt;br /&gt;On the first run will give the following output:&lt;br /&gt;30800&lt;br /&gt;30800&lt;br /&gt;30800&lt;br /&gt;And on the second run:&lt;br /&gt;30810&lt;br /&gt;30810&lt;br /&gt;30810&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-4170799577499164896?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/4170799577499164896/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/01/generating-random-number.html#comment-form' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/4170799577499164896'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/4170799577499164896'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/01/generating-random-number.html' title='Generating a random number'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-6371875322009740984</id><published>2010-01-25T16:28:00.004+01:00</published><updated>2010-01-25T16:38:45.560+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='best practice'/><title type='text'>Client server method keywords</title><content type='html'>There is a difference between declaring a static method with both client and server keywords and without any:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;public static client server void method1()&lt;br /&gt;{&lt;br /&gt;}&lt;/span&gt;&lt;br /&gt;and&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;public static void method2()&lt;br /&gt;{&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;If a method is declared without these keywords the tier to execute the method will be determined based on RunOn property of the class. So if a class has RunOn property equals to "Client", then method2() will always be called on the client tier but method1() will be called on the tier where it was called from.&lt;br /&gt;Considering that it is a best practice to explicitly mark methods with both client and server keywords if it is designed to be executed on both tiers.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-6371875322009740984?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/6371875322009740984/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/01/client-server-method-keywords.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/6371875322009740984'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/6371875322009740984'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/01/client-server-method-keywords.html' title='Client server method keywords'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-6030184771201625853</id><published>2010-01-22T15:40:00.004+01:00</published><updated>2010-01-22T15:55:12.462+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='reports'/><title type='text'>Validate method on reports</title><content type='html'>Be careful with naming report method validate(). It does not appear in override list for the report methods but still will be called by the framework if you are running report from the output menu item. Just try to add the following lines to any report that has no such method:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;private boolean validate(Object _calledFrom)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;throw error("Unexpected call.");&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Moreover, if your method has different signature from above you will get another exception regarding incorrect method signature.&lt;br /&gt;The root cause of this call is located deep inside ReportRun framework - some of the methods are being called via reflection from SysReportRun class (see SysReportRun._validate() method for exmaple).&lt;br /&gt;&lt;br /&gt;The full list of such dangerous names can be found in SysReportRun::reportFindMethodsMap() method.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-6030184771201625853?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/6030184771201625853/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/01/validate-method-on-reports.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/6030184771201625853'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/6030184771201625853'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/01/validate-method-on-reports.html' title='Validate method on reports'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-4371352932736156595</id><published>2010-01-21T17:05:00.003+01:00</published><updated>2010-01-21T18:28:04.800+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='best practice'/><title type='text'>Global::isRunningOnServer</title><content type='html'>This method allows to determine if the code is being executed on server (or client). It can be useful if there is a class which is explicitly designed to be executed on "called from" tier but which has a method that performs a lot of database calls. Execution of the "heavy" method on the object which resides on the client can result in a large numer of RPC calls which seriously reduces performance. To avoid that, object on the client can be serialized, instantiated on the server, deserialized and then execution of the desired method can be performed. To determine whether object is on the client (or server) just call Global::isRunningOnServer() method.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-4371352932736156595?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/4371352932736156595/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/01/globalisrunningonserver.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/4371352932736156595'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/4371352932736156595'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/01/globalisrunningonserver.html' title='Global::isRunningOnServer'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-70446916513492509</id><published>2010-01-20T14:28:00.003+01:00</published><updated>2010-01-20T14:33:18.518+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='best practice'/><title type='text'>Intrinsic functions for Maps and Views</title><content type='html'>It appears that the same intrinsic functions that work for tables can be used on AOT Maps and Views. Among them tableStr, fieldStr, tableMethodStr, etc.&lt;br /&gt;So, if a map or a view is needed to be referenced via reflection, those functions should be used.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-70446916513492509?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/70446916513492509/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/01/intrinsic-functions-for-maps-and-views.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/70446916513492509'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/70446916513492509'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/01/intrinsic-functions-for-maps-and-views.html' title='Intrinsic functions for Maps and Views'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-607753851944905512</id><published>2010-01-19T16:16:00.005+01:00</published><updated>2010-01-19T20:16:14.902+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Global class'/><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><title type='text'>Global::getPrimaryKey</title><content type='html'>This method retrieves a string representation of a candidate key value of a record.&lt;br /&gt;If candidade key consists of more than one field, all candidate key fields' values will be added to the result string separated by commas. If table has property CreateRecIdIndex = Yes then string representation of the RecId field value will be returned by the getPrimaryKey method.&lt;br /&gt;This method should be used if you need to get unique identifier of a record of unknown type.&lt;br /&gt;&lt;br /&gt;Here are some examples:&lt;br /&gt;1) For InventTable table a string representation of the value of RecId field will be returned, like "5637144662"&lt;br /&gt;2) For InventItemGroup table the value of ItemGroupId field will be returned, like "Bulbs")&lt;br /&gt;3) For InventSize table the value of ItemId + InventSizeId fields will be returned, like "PB-Frame,10"&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-607753851944905512?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/607753851944905512/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/01/globalgetprimarykey.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/607753851944905512'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/607753851944905512'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/01/globalgetprimarykey.html' title='Global::getPrimaryKey'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-1316181237933330165</id><published>2010-01-18T13:25:00.005+01:00</published><updated>2010-01-18T15:17:58.936+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='bug'/><title type='text'>ChangeCompany and table buffers</title><content type='html'>There is a bug with changeCompany keyword which prevents usage of the same initialized table buffer in different companies. For example, in the following code:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;InventItemGroup inventItemGroup;&lt;br /&gt;&lt;br /&gt;changeCompany ('A')&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;inventItemGroup.ItemGroupId = 'IA';&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;inventItemGroup.insert();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;changeCompany ('B')&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;inventItemGroup = null;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;inventItemGroup.ItemGroupId = 'IB';&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;inventItemGroup.insert();&lt;br /&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Without &lt;span style="font-family:courier new;"&gt;inventItemGroup = null;&lt;/span&gt; line the second insert will throw an error:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Cannot create a record in Item groups (InventItemGroup).&lt;br /&gt;Insert operations are not allowed across companies. Please use changecompany keyword to change the current company before inserting the record.&lt;/span&gt;&lt;br /&gt;Because buffer still has dataAreaId value equals to 'A' and neither changeCompany nor insert does the substitution automatically.&lt;br /&gt;&lt;br /&gt;So you need to either avoid using the same buffer in different companies or do not forget to reset it via assigning null value.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-1316181237933330165?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/1316181237933330165/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/01/changecompany-and-table-buffers.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/1316181237933330165'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/1316181237933330165'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/01/changecompany-and-table-buffers.html' title='ChangeCompany and table buffers'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-6978450147777897176</id><published>2010-01-15T16:42:00.005+01:00</published><updated>2010-01-19T16:17:30.563+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Global class'/><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><category scheme='http://www.blogger.com/atom/ns#' term='best practice'/><title type='text'>Global::formHasMethod</title><content type='html'>This method determines if a form has the specified method. It is a best practice to call this method before executing the desired method on the form itself.&lt;br /&gt;&lt;br /&gt;For example:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Object formRunObject;&lt;br /&gt;&lt;br /&gt;if (formHasMethod(formRun, identifierstr(refreshForm)))&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;formRunObject = formRun;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;formRunObject.refreshForm();&lt;br /&gt;}&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-6978450147777897176?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/6978450147777897176/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/01/globalformhasmethod.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/6978450147777897176'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/6978450147777897176'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/01/globalformhasmethod.html' title='Global::formHasMethod'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-3706189718561261208</id><published>2010-01-14T14:33:00.002+01:00</published><updated>2010-01-14T14:40:25.197+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><title type='text'>ConIns function performance</title><content type='html'>ConIns function for adding elements to containers is quite slow because its complexity linearly depends on the number of elements that are already in the container. If you need just to add elements to the end of the container it is better to use += operator.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-3706189718561261208?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/3706189718561261208/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/01/conins-function-performance.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/3706189718561261208'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/3706189718561261208'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/01/conins-function-performance.html' title='ConIns function performance'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-2824060454413880992</id><published>2010-01-13T16:19:00.004+01:00</published><updated>2010-01-13T16:48:44.721+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='hotkey'/><category scheme='http://www.blogger.com/atom/ns#' term='Label editor'/><category scheme='http://www.blogger.com/atom/ns#' term='X++ editor'/><title type='text'>An easy way to find an exact label</title><content type='html'>If you need to find the label "Item" you will probably find out that it's not so easy from the Label Editor, since all the labels that contain word "item" will be found. For example, "According to item group". And thousands of others. To find an exact label quickly just open the code editor, write the desired label, select it and press Ctrl+Alt+Space.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-2824060454413880992?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/2824060454413880992/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/01/easy-way-to-find-exact-label.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/2824060454413880992'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/2824060454413880992'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/01/easy-way-to-find-exact-label.html' title='An easy way to find an exact label'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-3359447591827485746</id><published>2010-01-12T16:46:00.009+01:00</published><updated>2010-01-14T19:11:54.032+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><title type='text'>Exceptions and chatiness</title><content type='html'>Each exception thrown on client causes RPC call to the server.&lt;br /&gt;&lt;br /&gt;Execution of the following method:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;public static client void testExceptionChatiness()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;throw Exception::Error;&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Results in a call:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Call Server: ttsabort&lt;/span&gt;&lt;br /&gt;Even though tts level is zero.&lt;br /&gt;&lt;br /&gt;So, one should consider that while implementing throw\catch statements on client tier.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-3359447591827485746?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/3359447591827485746/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/01/exceptions-and-chatiness.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/3359447591827485746'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/3359447591827485746'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/01/exceptions-and-chatiness.html' title='Exceptions and chatiness'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-6005323934415582982</id><published>2010-01-11T18:40:00.003+01:00</published><updated>2010-01-11T19:31:51.161+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='hotkey'/><category scheme='http://www.blogger.com/atom/ns#' term='AX 2009'/><title type='text'>Hiding content pane in AX 2009</title><content type='html'>A small trick can be done to hide content pane in AX 2009. Any list page should be opened and then content page can be hidden by pressing Ctrl-Q.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-6005323934415582982?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/6005323934415582982/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/01/hiding-content-pane-in-ax-2009.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/6005323934415582982'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/6005323934415582982'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/01/hiding-content-pane-in-ax-2009.html' title='Hiding content pane in AX 2009'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-651020261938802031</id><published>2010-01-08T13:14:00.003+01:00</published><updated>2010-01-08T13:20:31.021+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='hotkey'/><category scheme='http://www.blogger.com/atom/ns#' term='X++ editor'/><title type='text'>Selecting vertical text blocks</title><content type='html'>To select vertical text block in X++ code editor press Alt+O and then start selecting as usual using keyboard or mouse. Vertical text block will be selected. Vertical text block can be copied, pasted, cut and deleted.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-651020261938802031?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/651020261938802031/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/01/selecting-vertical-text-blocks.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/651020261938802031'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/651020261938802031'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/01/selecting-vertical-text-blocks.html' title='Selecting vertical text blocks'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-8754657758051302677</id><published>2010-01-07T15:11:00.004+01:00</published><updated>2010-01-07T15:24:36.407+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='X++'/><title type='text'>Exceptions and tts</title><content type='html'>You are not able to catch exception inside tts scope:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ttsbegin;&lt;br /&gt;try&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;throw error("Exception");&lt;br /&gt;}&lt;br /&gt;catch&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;info("Exception is caught"); // We won't get here&lt;br /&gt;}&lt;br /&gt;ttscommit;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;However you can catch exception that was thrown inside tts scope from outside:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;try&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ttsbegin;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;throw error("Exception");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ttscommit;&lt;br /&gt;}&lt;br /&gt;catch&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;info("Exception is caught"); // We will get here&lt;br /&gt;}&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-8754657758051302677?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/8754657758051302677/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/01/exceptions-and-tts.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/8754657758051302677'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/8754657758051302677'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/01/exceptions-and-tts.html' title='Exceptions and tts'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1201535659745738271.post-2808070409737183572</id><published>2010-01-06T18:32:00.000+01:00</published><updated>2010-01-06T18:50:39.100+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='hotkey'/><category scheme='http://www.blogger.com/atom/ns#' term='X++ editor'/><title type='text'>Navigating methods in X++ code editor</title><content type='html'>To move to the next\previous method in X++ code editor use Ctrl+Tab and Ctrl+Shift+Tab correspondingly.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1201535659745738271-2808070409737183572?l=axdaily.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://axdaily.blogspot.com/feeds/2808070409737183572/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://axdaily.blogspot.com/2010/01/navigating-methods-in-x-code-editor.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/2808070409737183572'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1201535659745738271/posts/default/2808070409737183572'/><link rel='alternate' type='text/html' href='http://axdaily.blogspot.com/2010/01/navigating-methods-in-x-code-editor.html' title='Navigating methods in X++ code editor'/><author><name>Gigz</name><uri>http://www.blogger.com/profile/01478817669521729380</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
