<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Gatsby RSS Feed]]></title><description><![CDATA[Blog about Microsoft Dynamics 365 for Finance and Operations X++ programming, tools, hints and more.]]></description><link>https://denistrunin.com</link><generator>GatsbyJS</generator><lastBuildDate>Mon, 20 Apr 2026 13:37:33 GMT</lastBuildDate><item><title><![CDATA[X++ Show Cross-Reference With Read/Write field reference]]></title><description><![CDATA[New release of TRUDUtilsD365 Developer Add-in that includes an advanced Cross-references form, allowing you to see the actual X++ code and determine the access type (Read or Write) for table field references.]]></description><link>https://denistrunin.com/d365utils-showcrossreference/</link><guid isPermaLink="false">https://denistrunin.com/d365utils-showcrossreference/</guid><pubDate>Tue, 24 Mar 2026 22:12:03 GMT</pubDate><content:encoded>&lt;p&gt;From the first release of Visual Studio for X++ development, one of the top &lt;a href=&quot;https://experience.dynamics.com/ideas/idea/?ideaid=acff0162-ef3e-e711-80c0-00155d7cb38d&quot;&gt;ideas&lt;/a&gt; was to improve cross-references - specifically, to add a &lt;strong&gt;Read/Write&lt;/strong&gt; modifier in the &lt;strong&gt;Cross-Reference form&lt;/strong&gt;:&lt;/p&gt;
&lt;p&gt;​          &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/b6698e263cf262807f1f01791eb3cc5f/e751c/CrossRefIdea.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 89.14285714285714%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAYAAABb0P4QAAAACXBIWXMAAAsTAAALEwEAmpwYAAACD0lEQVR42p1U2Y7bMBDz//9U+56iKAoUXRToZpPYTuL7kOXb7HB8bDZA9zJAjJxI9JCi5BhjYW2NpumQZTniKEEYRjj7Z61hQIQ6DqTGcYI8L5AkKcrSKNI0Q98PwtHCMabE4XCA73oK93TC9XqFMWZDURSKSsZVVSnyPMMw9Lh/HGstAiH4+uMbHr2TEuR5roumacJHHycIAux2O3x/+IW95yLNMpGTiPRo6aoSWSX44aamNc0LtG2r4JgNOCvzSA/ES3bGxbUsZiXYddd14lOPvuvnumIYRPqgY+1wJeQfZvGokS+O46gTWdfxeyzYCNl2GHIXY5XLGkm9RSHe0t9MbKEdq4JVDetGSElcpP4JGWuapvNYkSjZhiKHrYSQFtVWlZHjWbJ4YJdIzNKXiBj+ZjUyNJ7zqIYWvCqZLZdC0nayW+LZs/GdfpkgESuJ3ySk/kpad7MST3GJTkg/87wgbJoaP70YX/74sN3cwfRZQnqUykYYOVJVkemYO9kuAa63ULfbe3sT7jXoDrPFnE3TKJMaPRUkWjPJyfRy9fEtOCTIJB58GW+CvG0KT8g9+v6/cKI0wd73UJBY81UoWi7kkbrFOzp10rLA/ukvwrOPi1wOgTsjuV5QSqA3JDGMfLyW6657hdgZxwmVTD4+/Ia7f8RF7sbU8xDJvRgcjwhPM/heXC6wokIJl0zeE/4DPFl2Ae8bUc8AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Article content&quot;
        title=&quot;&quot;
        src=&quot;/static/b6698e263cf262807f1f01791eb3cc5f/8c557/CrossRefIdea.png&quot;
        srcset=&quot;/static/b6698e263cf262807f1f01791eb3cc5f/4edbd/CrossRefIdea.png 175w,
/static/b6698e263cf262807f1f01791eb3cc5f/13ae7/CrossRefIdea.png 350w,
/static/b6698e263cf262807f1f01791eb3cc5f/8c557/CrossRefIdea.png 700w,
/static/b6698e263cf262807f1f01791eb3cc5f/e996b/CrossRefIdea.png 1050w,
/static/b6698e263cf262807f1f01791eb3cc5f/e751c/CrossRefIdea.png 1123w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;​&lt;/p&gt;
&lt;p&gt;I don&apos;t know why Microsoft has not been fixing this for so long.  In the latest release 10.0.47 they introduced a new Cross-reference form (with &lt;strong&gt;Model&lt;/strong&gt; and &lt;strong&gt;Type&lt;/strong&gt; grouping), but still don&apos;t address the main issue: &lt;strong&gt;Read&lt;/strong&gt; vs &lt;strong&gt;Write&lt;/strong&gt; references for table fields.&lt;/p&gt;
&lt;p&gt;​          &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/78144ffa9f66113c2ec5ad9f54c4c7bf/5b4a1/CrossRefNew.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 33.142857142857146%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAAAsTAAALEwEAmpwYAAAA0ElEQVR42q1PyQ6CMBTs//+H+8GzF1cORo3BLcEtsglGjCB4sKIdH6AmRi4uk0xm+tpO3jCpkkG/UYTcIjYLpAUMpCIm7TJkqYRONYtePY9uLUd89YnmnrNImaYbME0TtrUmWjB1LfaBf8De3cP1SCO6Xuw9z4d794+zHxzj+4MfUOBKxXKxhGXZcJwdTieOMLyA8zNpiI8gAKarKubTWbwd5xxCiPd34u1falg0ZzNFwXg4gkHVA1r9KgR+Ads5W2yo7pHC/gGWVBKpVb8JvAGvXBU7Z3f7zwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Article content&quot;
        title=&quot;&quot;
        src=&quot;/static/78144ffa9f66113c2ec5ad9f54c4c7bf/8c557/CrossRefNew.png&quot;
        srcset=&quot;/static/78144ffa9f66113c2ec5ad9f54c4c7bf/4edbd/CrossRefNew.png 175w,
/static/78144ffa9f66113c2ec5ad9f54c4c7bf/13ae7/CrossRefNew.png 350w,
/static/78144ffa9f66113c2ec5ad9f54c4c7bf/8c557/CrossRefNew.png 700w,
/static/78144ffa9f66113c2ec5ad9f54c4c7bf/5b4a1/CrossRefNew.png 831w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;​&lt;/p&gt;
&lt;p&gt;​      This is quite a typical task in X++ development: you have a table field and want to know which code updates this field.&lt;/p&gt;
&lt;p&gt;​      Recently, I managed to connect &lt;strong&gt;Claude Code&lt;/strong&gt; to the &lt;a href=&quot;https://github.com/TrudAX/TRUDUtilsD365&quot;&gt;TRUDUtilsD365&lt;/a&gt; DevTools project, and it was able to implement this feature(The main challenge was &lt;a href=&quot;https://github.com/TrudAX/TRUDUtilsD365/blob/master/CLAUDE.md&quot;&gt;teaching&lt;/a&gt; Claude how to work with standard D365 DLLs - once that was sorted, it handled the rest).&lt;/p&gt;
&lt;p&gt;So a new &lt;a href=&quot;https://github.com/TrudAX/TRUDUtilsD365/releases&quot;&gt;release&lt;/a&gt; of &lt;strong&gt;TRUDUtilsD365&lt;/strong&gt; DevTools includes a &quot;&lt;strong&gt;Show Cross-Reference&lt;/strong&gt;&quot; Add-in that displays &lt;strong&gt;Read&lt;/strong&gt;/&lt;strong&gt;Write&lt;/strong&gt; access type for field references.&lt;/p&gt;
&lt;p&gt;​          &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/2e09091edbf1fce7a696556e8f4a18d9/3cb0f/CrossRefAddin.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 90.85714285714286%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAYAAABb0P4QAAAACXBIWXMAAAsTAAALEwEAmpwYAAACqklEQVR42p1U2W7TUBTM/38FEg8IXpAQSKiilK0ttE2TJo4TN7Ed7/G+xetNPBzfVlAemoo+jOJY1mhmzpwz0A0bwvUZdGMD2zRh2R6CMENV71E33X9j0LQdDMuFfCtBHn+ErpsoSoamxfMIyxrQ1grmF28hr1TEyfZZRH8I6/aOcPLjNdkNyOqOq3suBmm+gzQXcXn8AprmIN8yZPfgz/kD8P8toXkUg/6jFeU3PHkJ0/IQpQxrYwthbmOxdLEJK7hRzeH4O/hRT1g/Tlg1gGXoEM/fIIpzFBVFYBWQ1zHckMFPWgKD7RXYBHvEWXfYcj8UXdMhnL6CJl2SgoYU5lipMbwIRNrxX1XPYDgVJ6ybxys1qOoO6trEfKHg5ucRVvMxTJdBt7acyIs6+DFg2AVMp0aSP0FYk2VVUTH+9QnCRIAsW9zydGZSZoyyu1NpbmqebZhQCw7VJslqKKqB29kIhiLC9WvopKYfiOU28MI9V6jqKSQlvLd8gDAlQodkLBdTOKYB6jXWZo4JKbTcGmEKBAkgazFEySXCwys52BY7eH4I8fqECNcIvIDsNTSUELdKAEVLeV0Mu+SKnxxKXjA4mxCL+YL2eQHbdijDEks1gkI2ZS3h+VluS2AIYsYJ++PBD8hD9IT9ISioOrOLd5DGX5GWgOP1qjKkxR4JOYip/D38pCOFNBTWod2Bo1/dHg3re3iv0HXJ3vgYsjQnRRkuhS1OhyHGUvsPrma0VTpDFGxhaz4sjU7dJkPsF/Su5PlyhUFA1uZD6LJIvWOQ1AyjmQPVbqFtGDSno3clplJKWTI6JCN8e/8Z50enuDy5wPDLFYSzCQmj1XO9HMuVievhDYbfP0AYnSOISr6vCflP0uovsopnKMsBxOka0sLC9IZOn2jANDJesd+OF1MX66u6wwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Article content&quot;
        title=&quot;&quot;
        src=&quot;/static/2e09091edbf1fce7a696556e8f4a18d9/8c557/CrossRefAddin.png&quot;
        srcset=&quot;/static/2e09091edbf1fce7a696556e8f4a18d9/4edbd/CrossRefAddin.png 175w,
/static/2e09091edbf1fce7a696556e8f4a18d9/13ae7/CrossRefAddin.png 350w,
/static/2e09091edbf1fce7a696556e8f4a18d9/8c557/CrossRefAddin.png 700w,
/static/2e09091edbf1fce7a696556e8f4a18d9/3cb0f/CrossRefAddin.png 708w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;​&lt;/p&gt;
&lt;p&gt;The idea is simple: find all code references to a field, extract the code line, and analyse whether it&apos;s a &lt;strong&gt;Read&lt;/strong&gt; or &lt;strong&gt;Write&lt;/strong&gt;. Currently, the detection looks for the &quot;=&quot; symbol - if the field is on  the left side, it&apos;s a Write; everything else is Read. It also handles  patterns like setField(fieldNum(...)).&lt;/p&gt;
&lt;p&gt;I tested it on several popular fields, such as &lt;strong&gt;SalesLine.SalesPrice&lt;/strong&gt; and it works great. The tool also displays the actual code line  (configurable - one or several lines of context), so you can visually  confirm what the code does.&lt;/p&gt;
&lt;p&gt;View for 1 line:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/069806ee60e1f73be6daf3397b6eedbd/d30ee/CrossRef1Line.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 59.42857142857143%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAAsTAAALEwEAmpwYAAACXklEQVR42k1T2W7UQBD0//8F4glICG+RkMhBQEiIK97N+pqx5/CxPuO1N5vsBqnonhDEQ6k9XT19TJc9qxVym6PIC1RVhWEYsNvtcDgcsN/vsX94cJbPzvc/mP8LvsPwgiDAwl9AZRlZHz4hDEOkaQZrLbTWMMY4vmsb3FJBxtB3VLx3DTxjHEd4Ugi6nEIp5RKUZQkukudPXRfUvVQWX/0YQVpC5C2EbZFVI7KiRVPXWK/X6LoOkvJ4SSwoyRphEFEXGnXdIkkkBdXo+gHzvEXdtAgjQZAIQoFEKBRlg7xYox9uaQpLUyW4vvbh6VRgc9shTULoNME4dFAiwm474X63pXeZie/JFyJXAlqGaEqDsaNkTYV5GlHlCkrGbjLv9LPE8VWBo/MUb85SHF9qvP5AvguN448WJ59KnFzlODqTeHdl8erc4MVpgpfvKf7CEF/g7eVT7JdvN/D8lUSsGvzwBX4uU6ySAotQQ5oOUVYjMS1isswxvi9S/FopXK80buICgvhFoImjpS6pQ5bNZhygUomyyN23URmNu8MdjX03z26s3BpakEFPmz7s7/H7ce/802ZEXZUwpIZgRQkzkgevXCS0bZm6zQohMU2zk8Fms3G8yhRdMrDGgu/kFMf65RhLlv1xHMMTcYKOthiFEW6WK6e7MAix3W7RkxRGSti1rePYH0cxIkJCDWilXUIulFCeiPTrZdRV23auKju5Kot6plHbpkHf95Swo66Fi5FSuu6465qlRUVZu6zl5XIJjw9r+uUYTPKIz+Dqz2NPjGlyT8GWC7L9x9N30zT4AxiobbemvQr2AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Article content&quot;
        title=&quot;&quot;
        src=&quot;/static/069806ee60e1f73be6daf3397b6eedbd/8c557/CrossRef1Line.png&quot;
        srcset=&quot;/static/069806ee60e1f73be6daf3397b6eedbd/4edbd/CrossRef1Line.png 175w,
/static/069806ee60e1f73be6daf3397b6eedbd/13ae7/CrossRef1Line.png 350w,
/static/069806ee60e1f73be6daf3397b6eedbd/8c557/CrossRef1Line.png 700w,
/static/069806ee60e1f73be6daf3397b6eedbd/d30ee/CrossRef1Line.png 980w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;View for 3 lines:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/3ec82728a74436d24a2550ab46bf4999/52ab5/CrossRef3Lines.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 48.57142857142858%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAAsTAAALEwEAmpwYAAACCUlEQVR42m1S227TQBD1/z+RoCBe4A+4tBWXVwSlNEklEsCN4yS241vWXl9ie31NOcwupfCApaPZ0ZwZz8wZzdrtYNs2PNdDmqYoikKhLAs0TY22bdA2zW/7B80/ljhCCJxOJ+i6Dm21WmG73cIwDJimCc/z6AcOFrqJtR3A9mNYfgTLu4cfPfg7iu2DGGEYIstyzOc30GT1sqyomwZ1XaPve1RVBdf1YTsegjACTzJEPEHMUwXlxwmSNEfdtCiLUnX55foaWlmWyNJMFZGjtm2rim/MDfaOg478YRjQdZ2K9X2HE/lDP+COxhxkA9SQzJ/N5tC6tkZdHtGIEl0j0HcNoQULAyQxQ57G4CxU8Z64d6cBf7+ftLue9kg77FvM5lTQcFLoG4Yf2wjrfQYrrGB6R3yc6ri6MTD9usV0YeG7ySC5JnEkb01vKxTYBZXyTTfHp89TaKNXe0zOCRcuHp85GL8mnO3x/L2LZ+8citl49HKHEWFy4eEJ8Sb3GJ97GBF3THlP34Z48eYDtOKY0w457aFQVlQ0Oo1s0Al8WyzAI0bjkmi1wP++YZAikiiUf3l5BY1L9WJOimWEVCkuRI3VrYFbfQXfD5DlR3UWSZIiIZVTyaX3kdStiCtVLghKZd/zVVLEGNiBqePOsgyccwXGIhwOh4d4RL58x2RFJdRFSIXlFSyXS/wC243kCiGlUg0AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Article content&quot;
        title=&quot;&quot;
        src=&quot;/static/3ec82728a74436d24a2550ab46bf4999/8c557/CrossRef3Lines.png&quot;
        srcset=&quot;/static/3ec82728a74436d24a2550ab46bf4999/4edbd/CrossRef3Lines.png 175w,
/static/3ec82728a74436d24a2550ab46bf4999/13ae7/CrossRef3Lines.png 350w,
/static/3ec82728a74436d24a2550ab46bf4999/8c557/CrossRef3Lines.png 700w,
/static/3ec82728a74436d24a2550ab46bf4999/e996b/CrossRef3Lines.png 1050w,
/static/3ec82728a74436d24a2550ab46bf4999/2cefc/CrossRef3Lines.png 1400w,
/static/3ec82728a74436d24a2550ab46bf4999/52ab5/CrossRef3Lines.png 1420w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Other features:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Supports tables, classes, forms, views, data entities, enums, methods, and extensions&lt;/li&gt;
&lt;li&gt;Filter by module and access type&lt;/li&gt;
&lt;li&gt;Go to source navigation (opens the X++ file at the exact line)&lt;/li&gt;
&lt;li&gt;Copy to clipboard (paste-friendly for Excel)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The tool is open-source and 100% AI-written, so if you&apos;re missing something, you can ask Claude to add it.&lt;/p&gt;
&lt;p&gt;I hope you find this tool useful. Install it from &lt;a href=&quot;https://github.com/TrudAX/TRUDUtilsD365?tab=readme-ov-file#using-power-shell&quot;&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Feel free to ask questions!    (The original post for this tool is here:  &lt;a href=&quot;https://www.linkedin.com/pulse/x-show-cross-reference-readwrite-field-reference-denis-trunin-0p8ec&quot;&gt;https://www.linkedin.com/pulse/x-show-cross-reference-readwrite-field-reference-denis-trunin-0p8ec&lt;/a&gt;  ).&lt;/p&gt;</content:encoded></item><item><title><![CDATA[D365FO License usage log utility]]></title><description><![CDATA[Learn how the new D365FO licensing model works and discover an open-source X++ utility to monitor actual user activity and optimize your license costs.]]></description><link>https://denistrunin.com/xpptools-licenseusagelog/</link><guid isPermaLink="false">https://denistrunin.com/xpptools-licenseusagelog/</guid><pubDate>Sun, 08 Mar 2026 22:12:03 GMT</pubDate><content:encoded>&lt;p&gt;In this blog post, I will describe how the current licensing works in D365FO and introduce an open-source X++ utility that allows you to track the actual usage of elements and compare it with the elements assigned to users via user roles.&lt;/p&gt;
&lt;h2 id=&quot;understanding-the-current-licensing-model&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#understanding-the-current-licensing-model&quot; aria-label=&quot;understanding the current licensing model permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Understanding the current licensing model&lt;/h2&gt;
&lt;p&gt;At first, the new licensing model may seem confusing. For example, what does &quot;Entitled&quot; or &quot;not Entitled&quot; mean? Here, I will describe my journey to understanding it.&lt;/p&gt;
&lt;p&gt;The legacy model relied on AOT properties for MenuItems. For example, opening the &lt;strong&gt;WHSLoadTable&lt;/strong&gt; MenuItem in Visual Studio shows two properties: one for the read-only license, and another for the write license.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 435px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/60600ea3c1d6c31d8ee82ee645fb455b/330eb/VSMenuItemProperties.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 90.28571428571429%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAYAAABb0P4QAAAACXBIWXMAAA7EAAAOxAGVKw4bAAADcUlEQVR42oWUa4/bRBSG/XtB/VBUFSRE+YCgVbsCwZeKthIgVWqRCup2ge6dVau95uJcnJud2EnsOMnGiXNdJ9kkD8dZWrXdFkZ6lMlM5j3nPXMmivb8FubON9gvbnOW+oFAGKjfMUp8f0Hy/+nFv6UfvUl6fQUlEtOIJ7KowklURU0bFEs2eb1KtlDGKDr0hnO6g6lw/l78/jnBBJLZGsqL7Sf8/TLG3kGGg4M9do919lN1jhIOsUwbNdcjWeiTyPc+iJrrkimO2N6voOQTafRYmuRhHENN4td9PNvDc338wRyn3qPidOgOF7S7Uzz/Mi1/IvszDiJFlMwf20R+e8rx72vE1zbIbe2S3tihIp+zqYh0elKStFi38HsjzmcwnsyZyN4rwu/zBSRSJkoukiK7f4SVyHBqlKllDEGnoVuMp9DyukSjCbSsgZrKUmt4y/VRMONsPF8SzsNASc1CqdTa5PQSdr3FaDJD1peMZwumMmk2O5wcx9DNKvGkRtVpMjlnKRRMFkvC+WwuGaZF0Ko0yWQKaFqBrGThuh6nre4yanjQa/eXe27doyXzVwJvEv42DL4ULIugXjBJJnNSpyo1t0Xz1F8eDK0NRpPlmlNr4jbar7N6k0sZFsRyaCU8HBY3jHb2r6DnD2hKZkM51B9N6fSCS7S7Af3hWEoit2yVGxQMC9NyxFaLSrVObzC5yFAs1+0atlEg6HdhIdE+OOZEVf1CMJvVyeWKxKUfbbEX1mQUzFmIja2ky7VHaa4/SnH9qcWnz6pC5TWfCddWK3y9brGxG0ExQ8F8CUOem1FyMCVDw6zhNHzmIrgac7nyq85XW6d88qzO1XcI166s1rnxl83axgFK1WlRM0v0Ox2mwxGT4YBZEIi7C3vdThvXNBmfnfFfYzGfsbMXRTnaibBy9zl37m+x8mCHO/c2ufXTS358fMK9dZMnsbq0VZ5M3qLhDej0x7TDi3gHx22yuXuCsvvnIZ/fP+bLhwm++DnOjV/ifHT3mI9vb3L1QYyHqo9rSynKNXl6gTwzCMaLtwjbpuN32T/UULRUAUeTy0incbIZ7IzGvCc3OhqymF280XOpZdhnYTu9rw9HIhiOQqmJoqZ01GyRVM5Ek//AlFgzwt6Ui8kXw8xcbOnRil2nXHGl36bL/nxLdCyRJHDRavIP640aNdZLsTIAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Menu item properties&quot;
        title=&quot;&quot;
        src=&quot;/static/60600ea3c1d6c31d8ee82ee645fb455b/330eb/VSMenuItemProperties.png&quot;
        srcset=&quot;/static/60600ea3c1d6c31d8ee82ee645fb455b/4edbd/VSMenuItemProperties.png 175w,
/static/60600ea3c1d6c31d8ee82ee645fb455b/13ae7/VSMenuItemProperties.png 350w,
/static/60600ea3c1d6c31d8ee82ee645fb455b/330eb/VSMenuItemProperties.png 435w&quot;
        sizes=&quot;(max-width: 435px) 100vw, 435px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;This model obviously couldn&apos;t cover all the complexities of the current license model (e.g., whether you have Finance, SCM, or both). As a result, Microsoft released a new model where they store all the license information on their servers and provide it to users in &lt;code class=&quot;language-text&quot;&gt;Licensing*&lt;/code&gt; tables. The data for these tables is calculated internally by Microsoft services and periodically (e.g., every 8 hours) synchronized with the Tier 2 or PROD environments. In this model, all custom menu items are treated as Teams licenses.&lt;/p&gt;
&lt;p&gt;Here are the license properties for the same menu item under the new model.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 655px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/9d628fd17574712f8c3a8b67348e51cc/ae6b7/LicensingTablesView.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 93.14285714285714%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAACXBIWXMAAA7EAAAOxAGVKw4bAAADFklEQVR42pVUaXeaWhT1//+dfnttX1Zek9gYY5yiAiKgCCjjZVJw2N33pv3YJM+1zlpygX32cA6drRegaQ5ojwKGkWE+d7FauSjLA+TvesX/+nWCfYRTe2TlSNMIg2cN376OMHiZwnFMRGn6G/j6ScBdiFYCNgJJkkHXIwyHFn72J7i/GyPSF7i07ecZ+gSUDFsCCpHB91M893NowxDTwRab7j1cw4DIK8Rxi33YIGbj0+n0F8BgT7ADzpScJCkmE58MbdhzC8ZCw9rdIs9zFEXNhmcFmqbiHUApmYCnJie7jN6N0H24h2ZoCqiua1RlibIo+L/E5Xr5QPJvhjJl0wwxGk5xc3ODu7s7BjTAaDxmOA58z0cQBPT7fT87HgGbY61C0TRBuWs8PHTR6z3hqfeIx6cnhFGMz07PG2BTK8m7vSCYwGBg4vb2O34+9uC5LtZMWpZrW5zP8n3Arb8jw0qFEgQC/X6AF87gvzff8c/Xbxj2epjddmF2n5HYDtrz6aPBfpvDtNhh7RzgB6XyyrIsVcE+gOPWsLcNju35Y8m2s0FOGVEUoLBMiMhCVVWoDwcmesX5dMbl0qpqW4I2so5oGE7T/LluVFjyrKMbJpnYWCx0WKal0hRCrmGGYLfnIEcMJSHzHTw/wJ6rGicJ7+2wjyJEcaKuPd9nBiE6uzDmuJh4GY7g8SXBeSvIOOEOr9goJKCuGbCdNbZbTzUwjCUs+hkx/cVc41ht1D3ZtOOyq64bGI8neH2dsVuKisMsAX16eTjU/AIt1PnheKQVNRaaxo2JKbHBkIsgAeW5fE+l7HK9VisLLrtkQnDNCgUoZeVlodiElCbZZ9ye9dpFlMRKiSltIobguShyCRhgSQnG0uQD1duq1RXSLFNpV1UJZ2UiFwm3qVK1XC7pZaienc/mipAkIUsB6rqO8WiCyfSVbGwaHSuz5YNpXuDLfy/4MfPQtzI8WwlG0xn9i5TMEb3fbLaKrayOx4+DT1B5aNtrlfh64zKxPQMJaUGO1+UG5jaCvcvgBCmt8ZUCCeAzXRlOTnayfgEfbZnoO3pVDgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;LicensingTablesView&quot;
        title=&quot;&quot;
        src=&quot;/static/9d628fd17574712f8c3a8b67348e51cc/ae6b7/LicensingTablesView.png&quot;
        srcset=&quot;/static/9d628fd17574712f8c3a8b67348e51cc/4edbd/LicensingTablesView.png 175w,
/static/9d628fd17574712f8c3a8b67348e51cc/13ae7/LicensingTablesView.png 350w,
/static/9d628fd17574712f8c3a8b67348e51cc/ae6b7/LicensingTablesView.png 655w&quot;
        sizes=&quot;(max-width: 655px) 100vw, 655px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The logic is now different: if a user has &lt;strong&gt;Read&lt;/strong&gt; access to this &lt;strong&gt;WHSLoadTable&lt;/strong&gt; menu, they must have one of the 7 specified licenses. If they have &lt;strong&gt;Write&lt;/strong&gt; access, they must have an SCM or SCM Premium license. This is exactly what &quot;Entitled&quot; means.&lt;/p&gt;
&lt;p&gt;Microsoft provides a form &quot;&lt;strong&gt;Licenses usage summary&lt;/strong&gt;&quot; which displays the results of the above query, but in a different level of  granularity (Role - Duty - Privilege)&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/4461ab191a3ec2befcdb6160c8d0f96a/c83ae/LicenseUsageSummary.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 57.14285714285714%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB3UlEQVR42qVSTY/TMBDN//8dCHVZJLYUsVAQVw4c6YEF1G6XOM6H7diJEyeNk8fYFAHq3rA0mTcZ+/nNjJPVeovVzWus1rd4tnmL680WT19QfHOLq/UbPHm+wdXLLa5fvT/bu7/wpSXWdmiMwTiOmE4nLPOM/1lJxlLcHw7gGSPj2N0dsfua4m7PwXgFITVk3aCoFEzrkJcyxrrtUQoNXshoQjWU75Fo08DaBtM0wvsZu28cHz5+wafPD9g/5Ph+SMErA1ZoFKLFD06E2qEbAdWMELqHticYO6F1CxKlJIqcw+gafd+h7yxaI+GnE6qyRHnOVWUOJSvUSmAchljeMDg415OYCfO5VYltWzSNoT5quL4ntRacc9S1RlVVyLKMcA0pFbTWEQ/U77AceUfkk/fwRLhcENJtLcWMsUhWFEXESsqIJXkhBCn7pfBEQww4qPNE+ojCDl3XoaRSg5qokAgDDmS/FY5nhYHMORfJHi059DCUHA4HpZp6F0gM5YUUtK+JsaPe+dnHisL+QBzieZn/ELaNJm9xZBL3qYAwI/bHgmKBQtETqQfobkaa65grlaN/9IxkF7G2HjXZxVDCMNKU0a0jGA2EsYym6GPDF/pobcgvVOLyz4MOuWA/AWYXPSShyXJ1AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;License usage summary&quot;
        title=&quot;&quot;
        src=&quot;/static/4461ab191a3ec2befcdb6160c8d0f96a/8c557/LicenseUsageSummary.png&quot;
        srcset=&quot;/static/4461ab191a3ec2befcdb6160c8d0f96a/4edbd/LicenseUsageSummary.png 175w,
/static/4461ab191a3ec2befcdb6160c8d0f96a/13ae7/LicenseUsageSummary.png 350w,
/static/4461ab191a3ec2befcdb6160c8d0f96a/8c557/LicenseUsageSummary.png 700w,
/static/4461ab191a3ec2befcdb6160c8d0f96a/e996b/LicenseUsageSummary.png 1050w,
/static/4461ab191a3ec2befcdb6160c8d0f96a/c83ae/LicenseUsageSummary.png 1180w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h3 id=&quot;special-roles&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#special-roles&quot; aria-label=&quot;special roles permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Special roles&lt;/h3&gt;
&lt;p&gt;There are special roles that are exempt from the license report:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;System administrator&lt;/strong&gt; - This role has access to everything and is currently excluded from the license report.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Device based licenses&lt;/strong&gt; - This is a common scenario in warehouse environments. For example, if you have a physical computer on the warehouse floor and five warehouse workers who periodically use it to perform various activities, instead of licensing these five people individually, you license just one device. You then assign the &quot;Device-based&quot; role to these users, which excludes them from the license report. It&apos;s my understanding that this is not currently strictly controlled by Microsoft, but they plan to introduce some level of control in the future.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;After familiarizing yourself with the &quot;&lt;strong&gt;Licenses usage summary&lt;/strong&gt;&quot; form, I also recommend reading this &lt;a href=&quot;https://dynamicspedia.com/2025/11/dynamics-365-licensing-enforcement-advent-calendar/&quot;&gt;series of articles&lt;/a&gt; by &lt;a href=&quot;https://www.linkedin.com/in/andreadc/&quot;&gt;André Arnaud de Calavon&lt;/a&gt;, who has done a fantastic job of explaining various security topics. This will give you a solid foundation in the new licensing model.&lt;/p&gt;
&lt;h3 id=&quot;isv-solutions-related-to-licensing&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#isv-solutions-related-to-licensing&quot; aria-label=&quot;isv solutions related to licensing permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;ISV solutions related to licensing&lt;/h3&gt;
&lt;p&gt;There are several companies that focus on D365FO security and licensing optimization. When I originally asked a &lt;a href=&quot;https://www.linkedin.com/posts/denis-trunin-3b73a213_d365fo-licensing-question-does-anyone-in-activity-7421742261249576961-Wnkl&quot;&gt;question about user logging on LinkedIn&lt;/a&gt;, I received a lot of insightful comments. I&apos;ve saved them here for reference:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;André Arnaud de Calavon / Next365&lt;/strong&gt; — D365 expert and consultant, probably the top writer regarding security topics. Link: &lt;a href=&quot;https://dynamicspedia.com/2025/11/dynamics-365-licensing-enforcement-advent-calendar/&quot;&gt;André Arnaud de Calavon&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;D365RoleSecure / NoirSoft&lt;/strong&gt; — D365FO security and licensing-focused tool. Link: &lt;a href=&quot;https://www.noirsoft.net/&quot;&gt;NoirSoft / D365RoleSecure&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Fastpath Assure / Alex Meyer&lt;/strong&gt; — Security, audit, compliance, and D365FO licensing governance. Link: &lt;a href=&quot;https://marketplace.microsoft.com/en-us/product/fastpath.fastpath-assure-for-dynamics-365?tab=DetailsAndSupport&quot;&gt;Fastpath Assure&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Marco Romano / IT|Fandango&lt;/strong&gt; — D365 F&amp;#x26;O consultant offering licensing/right-sizing assessment services. Link: &lt;a href=&quot;https://itfandango.com/d365-fo-licence-cost-optimiser/&quot;&gt;IT|Fandango&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;XPLUS Process Discovery / Anthonio Dixon&lt;/strong&gt; — User activity and process discovery for D365, with license optimisation angle. Link: &lt;a href=&quot;https://xplusglobal.com/products/security-and-compliance/&quot;&gt;XPLUS Process Discovery&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;license-usage-log-tool&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#license-usage-log-tool&quot; aria-label=&quot;license usage log tool permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;License usage log tool&lt;/h2&gt;
&lt;p&gt;The main limitation with Microsoft&apos;s standard solution is that it doesn&apos;t provide an actual activity-based license usage report.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Consider a simple scenario: 10 users share a single role. This role contains 100 menu items that only require a Teams license, and one menu item that requires an Activity license. How can we determine which of these 10 users are actually using that specific Activity menu item?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;License usage log tool&lt;/strong&gt; was built to fill this gap and answer exactly these types of questions. It can be downloaded from &lt;a href=&quot;https://github.com/TrudAX/XppTools/tree/master/DEVTools/DEVLicenseUtils&quot;&gt;GitHub&lt;/a&gt; and deployed to your PROD environment using your standard X++ pipeline.&lt;/p&gt;
&lt;h3 id=&quot;enabling-element-usage-logs&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#enabling-element-usage-logs&quot; aria-label=&quot;enabling element usage logs permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Enabling element usage logs&lt;/h3&gt;
&lt;p&gt;After installation, you need to enable element usage logging. You have two options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Full (Debug only) mode&lt;/strong&gt; - Every single access is logged.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Summary mode&lt;/strong&gt; - The system creates an element usage log entry for a user only once per session.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You should run this for a couple of weeks in your PROD environment to collect meaningful usage data.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 602px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/95999354aa4819318b48441a4adb250e/32056/UsageLogSetup.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 42.857142857142854%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABS0lEQVR42o2R3VLCMBCF+xzqCyA6YAvj+7+CIIyiTJHK0J+kTdqmaYpz3ARwFC/g4puT5Gw2uxvvcexjFAwxHo9w17/F4L6PIPDR7/UQ+D78hyH5PoaDAW6ur87ihRHDahWB8wxZluB9tcVyuUQUfWCxeEGSMvC8QCkFpDiPxxgHY3SJMzooYEwH3Si0ukGjauw6Q3T42l2GN508YTadYD6bYf48xeYzcoZNZLUz7WVQvGk1vCSOwbIUSRIjibfIc466KlGWAhWpoiqrSjq1FVvvqEfsvqJ425UXUxLGUlRuRgXquoSUBXIaQVHk7kJBj9gZWs+u7UM2VhScyCGERLhOyFf0KWHoPkFIibZtobWm0tvD7Ixr53Tt9OTcmEPLr29rrDcZUk5tKkN04KJx5g9a/90Ttj2jf8ft155SLZrGVtZBke75n+BSvgESEYVT0Nvo7AAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Element usage monitor&quot;
        title=&quot;&quot;
        src=&quot;/static/95999354aa4819318b48441a4adb250e/32056/UsageLogSetup.png&quot;
        srcset=&quot;/static/95999354aa4819318b48441a4adb250e/4edbd/UsageLogSetup.png 175w,
/static/95999354aa4819318b48441a4adb250e/13ae7/UsageLogSetup.png 350w,
/static/95999354aa4819318b48441a4adb250e/32056/UsageLogSetup.png 602w&quot;
        sizes=&quot;(max-width: 602px) 100vw, 602px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The following events are &lt;a href=&quot;https://github.com/TrudAX/XppTools/blob/master/DEVTools/DEVLicenseUtils/AxClass/DEVLicenseElementUsageLogMonitor.xml&quot;&gt;logged&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Form openings&lt;/strong&gt; (using the same extension point as the standard Microsoft &quot;Form runs (Page views)&quot; telemetry)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SysOperation executions&lt;/strong&gt; (including reports and actions)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;FormLetter executions&lt;/strong&gt; (such as sales and purchase order postings)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;RunBase class executions&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/f619459f2816f02460aa6d8ad71e88e6/e996b/UserElementUsageLog.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 56.57142857142857%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABoElEQVR42qVS2VLDMAzM/39BD+h0ym+VgbS5mtNx7BylzaIVBBheeCAzGltaabVSHGy3D3g6HLDf77Fer7HZrHAQf7d7FH+FDWOLbf62wDsH09QY+h7AjHm+4z9fcD7HOD4/IzqFaE0Daw1sa9DJSf+n9d5hHHpp7tV+32mBaT3absQ0vcFLgeusAkvxNI56v14nXKcRnIgxmvde6iaxEc516gfDMCBJEhhjkOc5wjBE13XIsgyXywW3201x3pnTNA3u91kaXBFFEcqy1HglJ8kDdk7TVIG6rjWJnegzTkKSM97LnnvdNTQex7HmUTVF6A7ZicG2bWVPRklYpF2rStTc5SxVPdWxGWtoi2KSMf5JOKEoCgVJSjVKKIkLIRtyZJ5O1IzcoYzH/KXui5AACa3tFGAh98rOJCAh8VJUkojYMjJziX0Q9t8jF/lFnolVkjjmrvxHsSid5xnu82+SpJE3q3+cqxIyvgDmfe0wb0YcTxXOmUWU1ji+JMgrj1NSI4zlD7obzkmONBOVtcVrVClW1L3cc8EqFM2ArBTSAXgHx0A4VfYoTasAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;User element usage log&quot;
        title=&quot;&quot;
        src=&quot;/static/f619459f2816f02460aa6d8ad71e88e6/8c557/UserElementUsageLog.png&quot;
        srcset=&quot;/static/f619459f2816f02460aa6d8ad71e88e6/4edbd/UserElementUsageLog.png 175w,
/static/f619459f2816f02460aa6d8ad71e88e6/13ae7/UserElementUsageLog.png 350w,
/static/f619459f2816f02460aa6d8ad71e88e6/8c557/UserElementUsageLog.png 700w,
/static/f619459f2816f02460aa6d8ad71e88e6/e996b/UserElementUsageLog.png 1050w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h3 id=&quot;calculating-data-modifications&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#calculating-data-modifications&quot; aria-label=&quot;calculating data modifications permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Calculating data modifications&lt;/h3&gt;
&lt;p&gt;One of the main challenges of license monitoring is distinguishing whether a user only viewed a form or if they actually modified data. We can gather modification events from two sources:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Table ModifiedBy and CreatedBy fields&lt;/strong&gt; - This is not always fully reliable, as it only records the last user who touched the record.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SysDatabaseLog table&lt;/strong&gt; - This provides more accurate event information, but it must be enabled in advance.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/1c3205c52e9811e70c60ac1722a0e37f/6bff2/ModifiedTablesCalc.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 54.285714285714285%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB3UlEQVR42m1T7W7iMBDM+78Ff0AiLeUJeg+Bqjupaq8opYCTkNjxdz6mu+bgDnSWVsRre3ZnZsnyPMd6vcZqtUKeP2C5XOLx4RFPqycsFgvM5/P0O5vN8Pz8A8ZatFLh1LRoKLwP4DVN58isdemCNQYx9hh6imHA/1aMEft9CXGooDsLbQOcHxDidI2sbU6oqooqNjBawzmPQFVDuATvffo2SmK/ecHh9Q3t2ztiiIjjhDj8jcz7HqZVUB8f8HRBKgPuOhC1QAWCcwnQUyEuWO/2EMUn1OFw5ni3MkfdyFMLW1bUnaOw6UBttyg3G/QEPNLDcRzhrEHx6xXl5xeiUnDHI8Z+INzpGhlrpjpF/CMM6di0bQJksauqTkCXZbsO4ucLlDhC1yVMURBgf9thAqRqmugwoJQyHfSUbwl8+oeW9w5lscPu9xa7d5Lo7jwB9glQJpct0ePvM2AkwObmQYwBp7ZDJUnb4ZxvyEw2lZth40jDSJc0JI2B6gxq0pPdspQv6wahH68OWp4A0nkcLjSnBCZEmdjwRGTa0sOGADVVlwailnBhQmcijiWZ5ce0TzntbzTl7lkuZsn5ZApvjO6Su56qaxKex4G17ejyxAB//gY8PveAQog0HZf9N49ATCRX6MObAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Modified tables calculation&quot;
        title=&quot;&quot;
        src=&quot;/static/1c3205c52e9811e70c60ac1722a0e37f/8c557/ModifiedTablesCalc.png&quot;
        srcset=&quot;/static/1c3205c52e9811e70c60ac1722a0e37f/4edbd/ModifiedTablesCalc.png 175w,
/static/1c3205c52e9811e70c60ac1722a0e37f/13ae7/ModifiedTablesCalc.png 350w,
/static/1c3205c52e9811e70c60ac1722a0e37f/8c557/ModifiedTablesCalc.png 700w,
/static/1c3205c52e9811e70c60ac1722a0e37f/6bff2/ModifiedTablesCalc.png 957w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The tool allows you to specify a period (e.g., the last 90 days) and process the modification information from the two sources mentioned above.&lt;/p&gt;
&lt;p&gt;The next challenge is linking the form to a list of tables. The License tool automatically calculates this by linking all form DataSources with the corresponding MenuItem, but you can also manually correct these links if needed.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update 20.04.2026:&lt;/strong&gt; There is also a v2 of this tool that supports update logging from the form (&lt;a href=&quot;https://www.linkedin.com/pulse/d365fo-license-log-utility-v2-improved-data-logging-denis-trunin-um6fe/&quot;&gt;https://www.linkedin.com/pulse/d365fo-license-log-utility-v2-improved-data-logging-denis-trunin-um6fe/&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;You can enable write operations logging:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/9af33fc4e4af4d4e9c3175dbf7ee3259/a8e5b/DataLogSetup.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 41.714285714285715%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAAsTAAALEwEAmpwYAAABUElEQVR42pVQa2+CQBDkZxcbAQV8/bM2tmnVGmtUrDatVUBAODgeme6drZrGLyWZzC43Ozt3im2Z6LRbaNktWKZJbMOyLMlt+tftdCA0Wr0OQ9eh6xrhyLLXtNOcgGIYDTKw5aDZbMIwmlJo0IBY0uv20DB01FQVt7XaVajqzQlKWVZgjKMqC1RVBZ6XKPIcPMtk/99PcRYzPD32MXweYPwywt73yJCTYQqeMmSElCXICJJ/+5+z7EIjoERhANfdwfdceIJ9F2EYUuqEOIA4T5JY1kl8QBjsER8i2Ys6Iq3n+sgoQM4zKO5ui/XqTQpEsqLg2EwnWI4GWE/G2Dpz7N9X8BZzcBYfk18gTVNEEZNPJA03nx9YOo5MxyiJECwf+ni9v5PGu9kUXwLjoTTMaakYvESRn2tFXEPEPr8Dk+ZbWhT6PsFDQM9xiMKrZn/xDVt5MHQwxg8SAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Data log setup&quot;
        title=&quot;&quot;
        src=&quot;/static/9af33fc4e4af4d4e9c3175dbf7ee3259/8c557/DataLogSetup.png&quot;
        srcset=&quot;/static/9af33fc4e4af4d4e9c3175dbf7ee3259/4edbd/DataLogSetup.png 175w,
/static/9af33fc4e4af4d4e9c3175dbf7ee3259/13ae7/DataLogSetup.png 350w,
/static/9af33fc4e4af4d4e9c3175dbf7ee3259/8c557/DataLogSetup.png 700w,
/static/9af33fc4e4af4d4e9c3175dbf7ee3259/a8e5b/DataLogSetup.png 711w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;​      When enabled, the system dynamically tracks user modifications using &lt;strong&gt;event handlers&lt;/strong&gt; on form data sources:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Event handlers are attached to form &lt;strong&gt;Insert, Update, and Delete&lt;/strong&gt; events&lt;/li&gt;
&lt;li&gt;A log entry is created whenever a modification occurs&lt;/li&gt;
&lt;li&gt;Only one record per &lt;em&gt;user session per table&lt;/em&gt; is logged&lt;/li&gt;
&lt;li&gt;Logging can be enabled for specific users only&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/f32757f5321da182b0b47094ed6b294c/081d5/WriteLogView.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 40.57142857142858%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAAsTAAALEwEAmpwYAAABUklEQVR42mVR2XLjMAzz/3/jTtquEx86o1uK62JJppuHVjMcygQIkfA0zx+4XN4Q7h6P0dFbpWjf+RmjN8F+xvEYv2qT9xEhJKQUkb+j5IxWC+WESrmWLMLc8F+cM3NGry8xrk0xRty9h3MOy7KglIJ1XdFah7UWnrAxhtz5KKUwaLJWG1JMgrMGn/M8MbGAMQrOW+zbRsQKrRUJVtzJBmM0juNADEGanLPy3XnSxwOZtlH7RoNkwadNRfy9asw3gz9vNyibcXlfoV3BdbH4mOmx0OVeOoTr44DxDTYMrCpgJow5qdKEIWZsu4bSFrfrQl4WLOuOlGlS47AT1schnPML2JWV70zqrT9o5SC8L8I+TzxXtsbAk4cbeVdfKzfxlrHj4Eb3Wvnzx8oxPu2QlbmgyWhHpq/kIQtukov8KK21NLL5fIw8wIJd6ikl4fEjLPgPj7xmj7scyWMAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;WriteLogView&quot;
        title=&quot;&quot;
        src=&quot;/static/f32757f5321da182b0b47094ed6b294c/8c557/WriteLogView.png&quot;
        srcset=&quot;/static/f32757f5321da182b0b47094ed6b294c/4edbd/WriteLogView.png 175w,
/static/f32757f5321da182b0b47094ed6b294c/13ae7/WriteLogView.png 350w,
/static/f32757f5321da182b0b47094ed6b294c/8c557/WriteLogView.png 700w,
/static/f32757f5321da182b0b47094ed6b294c/e996b/WriteLogView.png 1050w,
/static/f32757f5321da182b0b47094ed6b294c/081d5/WriteLogView.png 1264w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h3 id=&quot;service-functions&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#service-functions&quot; aria-label=&quot;service functions permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Service functions&lt;/h3&gt;
&lt;p&gt;The License log form includes a couple of useful service functions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Cleanup function&lt;/strong&gt;: Deletes all log records older than a specified period (e.g., 90 days) and compacts the remaining data, leaving only one record per user, per element, for the entire period.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/936e1024cdb95eb25fae28a885f574bf/e51a6/CleanupFunction.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 41.142857142857146%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABX0lEQVR42n1R207DMAzt/3/Drp32PL4EiVdekMZWWNOmzT1tkx6cTKwIJCxZzsU+PvYpdrs9DmWJw+GA7WaL/W6HzXqNcl/ieDxivVrh6XSC0gpCCHRd94jOOfy2IoQZwzAhhoApREzjiHHwCHT/tpHejNGQUsBam4G01vn9DyCrb7i8n1FVFRhjCNMdPMXkqYEnENYKnC9V/rvbTAQCboyaGIN5nrMXSmkk16KHkRKeuhtK8N7DEVCK1ih8tA4Vo8IYcmECHMaIt09LjRemhbYjBJdonl8gX18RxiGPPFFMiSGNS+MZ69EJC07+nxVCedRcgzUSvNN5tLoR4D0xp2aslagZJ9YWXa9oLS2EVI8RE9nlPCeGE1rh4MY5e5PYknNhYFwAo3PLewIxuN56uis4EjGZ/yFOjPEOmJas1dJR0i77jtNeZU5Kd9H3VKigSOUYF/WTiNfrNcemYVn9LxZmYzy1PjUbAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Cleanup function&quot;
        title=&quot;&quot;
        src=&quot;/static/936e1024cdb95eb25fae28a885f574bf/8c557/CleanupFunction.png&quot;
        srcset=&quot;/static/936e1024cdb95eb25fae28a885f574bf/4edbd/CleanupFunction.png 175w,
/static/936e1024cdb95eb25fae28a885f574bf/13ae7/CleanupFunction.png 350w,
/static/936e1024cdb95eb25fae28a885f574bf/8c557/CleanupFunction.png 700w,
/static/936e1024cdb95eb25fae28a885f574bf/e51a6/CleanupFunction.png 783w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Comments per user&lt;/strong&gt;: The reporting table is recalculated on every run, but you can add free-text comments that are preserved between sessions (for example, to note that a specific user has already been validated).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/3fea7eb3218ec4b074e5c3524ee9b041/f43e4/Comments.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 25.142857142857146%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAYAAABFA8wzAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAA6UlEQVR42q2M3U6DQBBGef8robRofx7LxDRqpaWVFnaH3YVdaGKOa+ull05y8p1vMpkknxeslksWi4I0TXksCjbrNbMsvZH95l9k2QOLPGezWjGbPzHLlySiNapt8d7zH5OIxIeqxYjCWUPvfrD00UU6zhdF1wljGJhGf89wz9H30YcbY28ZB0dSNz3aBHy40mqDEkejOtww3txYz+AnpHO0cd8PAS0W6zxhumJjv5QV59cd+uMQH6rAdlez/xTETpzOhueXHVXs+2PD9u1AWTXR2+gVx1p4L2vK2LWZMP6LOt5dDifq8sg3Nu9pMBs0tUcAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Comments&quot;
        title=&quot;&quot;
        src=&quot;/static/3fea7eb3218ec4b074e5c3524ee9b041/8c557/Comments.png&quot;
        srcset=&quot;/static/3fea7eb3218ec4b074e5c3524ee9b041/4edbd/Comments.png 175w,
/static/3fea7eb3218ec4b074e5c3524ee9b041/13ae7/Comments.png 350w,
/static/3fea7eb3218ec4b074e5c3524ee9b041/8c557/Comments.png 700w,
/static/3fea7eb3218ec4b074e5c3524ee9b041/e996b/Comments.png 1050w,
/static/3fea7eb3218ec4b074e5c3524ee9b041/f43e4/Comments.png 1120w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;It also includes a couple of custom recalculated tables, which are primarily used for tracking and debugging:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;RunBase items&lt;/strong&gt;: Links MenuItem names with their corresponding RunBase class instances. Since RunBase logging only captures the class name, this table is required to link the class back to its originating MenuItem.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Permissions&lt;/strong&gt;: A view containing MenuItems with their Read and Write license requirements.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;running-the-license-usage-report&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#running-the-license-usage-report&quot; aria-label=&quot;running the license usage report permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Running the license usage report&lt;/h2&gt;
&lt;p&gt;After collecting the element usage log and calculating the data modification information, open the &lt;strong&gt;User license report&lt;/strong&gt; tab and click &lt;strong&gt;Refresh data&lt;/strong&gt;. The report will compare each user’s currently assigned license with the highest license tier required based on their captured system usage.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/9a73db44cfe2fa17031157b02c448dbb/9239a/LicenseUsageReport.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 63.42857142857142%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACP0lEQVR42o1TyW7bMBDV/wNNkHr5kJ57y6FBitjOpUCKwrZ2SqL2zVqs1ze023MMPHM0HM68mUda2+0Gq9UKX5+esN1ssFmv8fDwBY+Pj8SDwXq9wmaz/hSs5+dnvPx4wc/XV+x3e7y/H3DY74j9Dbsddm9vn4aVRAp1VQHLFQtBw+A6X3G9zvfvz/+s7HhCX9eo6gpFURAl6rpBmlWoqhZ93xkMwwUXsbuOa4+ua9G1st8b3zgMBtbvUwQvqqDzDi+HE759P+DkprC9CLafwI8KfPxxcfYSnJwYQVwhq0azxlmHICrx6+PMvQhHW8GKE40sy9negpzsfD8gsxpxHCMMFW0ejBPGZMjzHC3ZTNOMcZx45oqmaRkXmtggCGDJX8HAZVnMAdd1TZIwDOB5HkoWCRnjODaSJLknkoSDOSPjsc9nODbhOLC01iaBVCvLElEUsWoD8ce0a85WbPEbhve5TdONoXwLQ5m/5DEMtU5NtTTl7FhJEvu+bwJrCib2LU5jnmej5jiO5owkOR6PpjPbtqlyXlC1FjMriorCSBSsKqpNdG1jrlXFIk1Tk9mIiclEdWn7culJoPgPK4hrqhPCCzP4KofSNUIqaFPVtLjQn0Nzjeg/OgoeY0T5tBxwdmMTp5LSKF80M6y27eF6Ac62w9ZCVp5RlDU82g33VMTEWWF8Eid++R7GmXsxW/V5CzSmeTGwhHLE1xJwTkopttsZ6uKTtrROOPDctKs4U6VC0768Kk3V5QbkvFL/XspfUHbAFeMxJpwAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;License usage report&quot;
        title=&quot;&quot;
        src=&quot;/static/9a73db44cfe2fa17031157b02c448dbb/8c557/LicenseUsageReport.png&quot;
        srcset=&quot;/static/9a73db44cfe2fa17031157b02c448dbb/4edbd/LicenseUsageReport.png 175w,
/static/9a73db44cfe2fa17031157b02c448dbb/13ae7/LicenseUsageReport.png 350w,
/static/9a73db44cfe2fa17031157b02c448dbb/8c557/LicenseUsageReport.png 700w,
/static/9a73db44cfe2fa17031157b02c448dbb/e996b/LicenseUsageReport.png 1050w,
/static/9a73db44cfe2fa17031157b02c448dbb/9239a/LicenseUsageReport.png 1246w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The report consists of two sections: a &lt;strong&gt;header&lt;/strong&gt; and &lt;strong&gt;lines&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;header-section&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#header-section&quot; aria-label=&quot;header section permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Header section&lt;/h3&gt;
&lt;p&gt;The header contains one row per user and provides their licensing status:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;User&lt;/strong&gt; – The user account being analyzed.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enabled&lt;/strong&gt; – Whether the user account is currently active.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Last logon date&lt;/strong&gt; – The latest detected sign-in date for the user.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;License&lt;/strong&gt; – The license currently assigned to the user.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Usage log license&lt;/strong&gt; – The highest license level required based on the Element Usage log.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Compare Status&lt;/strong&gt; – A comparison between the assigned license and the usage-based license.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;High-tier lines&lt;/strong&gt; – The number of records that contribute to the highest detected license requirement for that user.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Comment&lt;/strong&gt; – An optional, custom reviewer comment.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;High-tier objects&lt;/strong&gt; – The specific objects that drive the user into their highest detected license tier.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;lines-section&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#lines-section&quot; aria-label=&quot;lines section permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Lines section&lt;/h3&gt;
&lt;p&gt;The lines section details the individual securable objects behind a selected user&apos;s result, explaining exactly why they fall into a specific license tier:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;AOT Name, Type&lt;/strong&gt; – The AOT name and type of the MenuItem.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Read License&lt;/strong&gt; – The license tier necessary for read access.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Write Permission&lt;/strong&gt; – The license tier necessary for write access.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Access&lt;/strong&gt; – The access level currently being evaluated for the user (&lt;strong&gt;Read&lt;/strong&gt; or &lt;strong&gt;Write&lt;/strong&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Current Permission&lt;/strong&gt; – The permission currently assigned to the user via security roles.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Writes&lt;/strong&gt; – Indicates whether actual write activity was verified for this object based on the collected data modification logic.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;analyzing-the-license-report-data&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#analyzing-the-license-report-data&quot; aria-label=&quot;analyzing the license report data permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Analyzing the license report data&lt;/h2&gt;
&lt;p&gt;This report evaluates users by comparing their &lt;strong&gt;Assigned license level&lt;/strong&gt; (the &quot;License&quot; column) with their &lt;strong&gt;Actual system usage&lt;/strong&gt; (the &quot;Usage log license&quot; column), based on captured daily activity and entitlement objects.&lt;/p&gt;
&lt;p&gt;Let&apos;s review the possible analysis scenarios based on the &lt;strong&gt;Compare status&lt;/strong&gt; field:&lt;/p&gt;
&lt;h3 id=&quot;1-match&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#1-match&quot; aria-label=&quot;1 match permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;1. Match&lt;/h3&gt;
&lt;p&gt;The assigned license accurately corresponds to the user’s actual system activity.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Technical meaning:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The user is accessing allocated menu items.&lt;/li&gt;
&lt;li&gt;Logged operations confirm the required access level (including write access where applicable).&lt;/li&gt;
&lt;li&gt;The assigned SKU properly aligns with the required entitlement objects.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;Example 1&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/1993d721992e4d50e483d4d7695dfda5/19a15/MatchStatusExample1.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 45.142857142857146%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABhklEQVR42q1R2W7cMAz032edBmmw+b0CjdenJEuWD50+ppQWLYo+18B4OBRFjs3i29s7/7zf+RtxWZb8TvHHx3devryIV9IJ5W/cbuJGKP/O/YNimWfIcYRzDv/jKWatL6Xktejp2tb5MgS7rVnznl2S8ctodbllJujLzTqzt9sVnPnD0dvMBZMGVb+hlxZsXMGERs8nsKpD87MFbwWGhuPrR4WhZqi/OgyUV+MMJhfIyYBT3PQC47Si8CHChRPGH7AE43aKd2zTAs1HzEJhERMUe8Y6a0W/6HnPEyzVr8bD0t3CWg9D2KPHeR5PHDvpgD14HMTRu8xJR0I+3yMO4hif+jzPrAvvPWZaTF3XGGk5gRynw2maMAwM1rqc9yFgWRZ0XZe1njTVhqxTnagqBGtRnAd9Km24aRrUjwpCCJp05CFt21JDSxcGGLNh27Zcl6C1Jpc7+r7Ho35AkKGTdHHQK7lkjGVXqUGMkRoYKKWyi5RPA5LD5E5KCUPN0+AUp5wih6nhL2FNma2zJrlaAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Match status1&quot;
        title=&quot;&quot;
        src=&quot;/static/1993d721992e4d50e483d4d7695dfda5/8c557/MatchStatusExample1.png&quot;
        srcset=&quot;/static/1993d721992e4d50e483d4d7695dfda5/4edbd/MatchStatusExample1.png 175w,
/static/1993d721992e4d50e483d4d7695dfda5/13ae7/MatchStatusExample1.png 350w,
/static/1993d721992e4d50e483d4d7695dfda5/8c557/MatchStatusExample1.png 700w,
/static/1993d721992e4d50e483d4d7695dfda5/e996b/MatchStatusExample1.png 1050w,
/static/1993d721992e4d50e483d4d7695dfda5/19a15/MatchStatusExample1.png 1229w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;In this example, we can see that the user accesses the &lt;strong&gt;Work&lt;/strong&gt; and &lt;strong&gt;Waves&lt;/strong&gt; forms and actually writes to the relevant tables. This legitimately requires a &lt;strong&gt;Supply Chain Management&lt;/strong&gt; license; it cannot be further optimized.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Example 2&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/158c2b021c3039908aec02c05a46a93e/d56b5/MatchStatusExample2.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 43.99999999999999%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABaElEQVR42q2SS4+cMBCE+f+XZQ/7yPy1KKPMZhgDBvx+YXBt40VRcsshSJ+qq6stbEPz7f09v7y85rZt89vba75cLvm5fSLaP3j6Z5p54rDG4n89jVhmaLXAaAlnFJzVVedFgPOFXqaQokcK7jfRW8RDT448nv3m1i3gs8YkLNgoMEwKi/KkmjTUumMTZulqxhcDaWJVvtjavz94VeM3NMpt0ISLO+kKZROsz1C0SNlIQxlChy9vKAs7fCp1vkJeUn5oWOnIKa0oO1Ey6QaUjTRXar3RFPazT3U5s2OGspqfc0e/+cUkvl8feIx0RE27MRn3XuD6MWCSoerh773Ej58M3SBxZ4KuIuHWTbjeejCuwQVdj17RaEt30DH0A0dad2y0Gaks+QkhZox8htIOPiSwniOmXP2aC6ZZVo41efuicc6BsQfGccCWc/30xpjqU0q1LmVHjBFCCOS8wntPvYIQAvn812/zCXq1oJXWa1D+AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Match status example 2&quot;
        title=&quot;&quot;
        src=&quot;/static/158c2b021c3039908aec02c05a46a93e/8c557/MatchStatusExample2.png&quot;
        srcset=&quot;/static/158c2b021c3039908aec02c05a46a93e/4edbd/MatchStatusExample2.png 175w,
/static/158c2b021c3039908aec02c05a46a93e/13ae7/MatchStatusExample2.png 350w,
/static/158c2b021c3039908aec02c05a46a93e/8c557/MatchStatusExample2.png 700w,
/static/158c2b021c3039908aec02c05a46a93e/e996b/MatchStatusExample2.png 1050w,
/static/158c2b021c3039908aec02c05a46a93e/d56b5/MatchStatusExample2.png 1215w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;This example is a bit different. The user only runs the &lt;code class=&quot;language-text&quot;&gt;TMSPACKINGLIST&lt;/code&gt; report. Microsoft recently changed this report to require an Enterprise-level license (it previously only required an Activity license). Since the high license requirement is caused by this single report, it presents an opportunity to reduce costs by developing a custom report or providing the required data through a different channel.&lt;/p&gt;
&lt;p&gt;A common question here is: &lt;em&gt;Can we just duplicate the standard MenuItem and use our custom copy instead?&lt;/em&gt; According to the D365 licensing guide, this practice constitutes &quot;Multiplexing,&quot; and still requires the original underlying license to be applied.&lt;/p&gt;
&lt;h3 id=&quot;2-match--write-not-confirmed&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#2-match--write-not-confirmed&quot; aria-label=&quot;2 match  write not confirmed permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;2. Match – Write Not Confirmed&lt;/h3&gt;
&lt;p&gt;The user accesses functionality corresponding to their assigned license, but no write operations were captured for the related tables.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Technical meaning:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The user accesses the menu items.&lt;/li&gt;
&lt;li&gt;Their assigned access level matches their allocated license.&lt;/li&gt;
&lt;li&gt;However, no actual database writes were logged for those sessions.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;Example&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/42d950ecffbdcafc447bd35620bd2777/7a4b2/MatchNoWritesExample1.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 40%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABVElEQVR42q1S2U7DMBDMf9M+UFq+kQfOkjaJ7fiI4ytOGNYGxDMSkUY7u7NyvLNuDodjvj+d8uH2Lu/3+8pPx2Pe3dzk/W73ZzSTMRCcw3uP//gaozW0kpgnjdkauHmCJzg7QQgFpRSCn7FEj/SD8MtjcDVfYqh5w0aLq3AYTcAwThi4xnWQGLVDzw2k9hByRtsJCGXRkdYzXWuDoJ+q0qfRXkWtNc5HuJDh04qYKIYFs4sI39yHVHnpqzwutR5ipv4VKW9feuklrVF6Bqdbci5hJkdiOXiDNnRrSRb4RDrZQbHohZeoCdYlMLJFqgnj+QLDFXloA43n8fjSEi7omIGaIkWNl3MHSVa8vvd1NCYtnt+6On4ZV9tEPT3OLUP78ATZSzQ5LyhgbEDfXWkBjvIESwviVFuWRK+AkfmeXoKrfF1XeDdj21awoadlRKQU8bFt+AQuzUukKdFuLgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Match no writes&quot;
        title=&quot;&quot;
        src=&quot;/static/42d950ecffbdcafc447bd35620bd2777/8c557/MatchNoWritesExample1.png&quot;
        srcset=&quot;/static/42d950ecffbdcafc447bd35620bd2777/4edbd/MatchNoWritesExample1.png 175w,
/static/42d950ecffbdcafc447bd35620bd2777/13ae7/MatchNoWritesExample1.png 350w,
/static/42d950ecffbdcafc447bd35620bd2777/8c557/MatchNoWritesExample1.png 700w,
/static/42d950ecffbdcafc447bd35620bd2777/e996b/MatchNoWritesExample1.png 1050w,
/static/42d950ecffbdcafc447bd35620bd2777/7a4b2/MatchNoWritesExample1.png 1240w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The user accesses the Waves form, but there is no confirmed record of them writing to its underlying tables. While this requires further investigation, it highlights an opportunity to lower their access to this form to read-only, which could potentially reduce their required license level down to a Teams license.&lt;/p&gt;
&lt;h3 id=&quot;3-higher-than-required&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#3-higher-than-required&quot; aria-label=&quot;3 higher than required permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;3. Higher Than Required&lt;/h3&gt;
&lt;p&gt;The user’s assigned license is higher than what their actual logged system activity.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Technical meaning:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Logged operations demonstrate a lower utilization level than the allocated SKU.&lt;/li&gt;
&lt;li&gt;The required entitlement objects actually fall into a lower license tier.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;Example&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/7926dd62b18862f6dff36ab1315effb3/e9d87/HigherExample1.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 41.142857142857146%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABb0lEQVR42q1R7Y7bIBD0++viu1PuHu3a9NoqaerEYPMNBoyJpovVB+iPIo0WhtllZ+n659d6PB7ry8trPTw90f6tvr+/1f5wqM99X/sG2v8rOq0UpBCIMeJ/rM4YDa0VnFUI3mIJFnHx8M5ATAITmxCMQg4OyTvkGLDmSHFBTgvW1GJASXHnu1F4XPkCrhK4cJilxThpKIrXj0+Mlxv4ZcCv00/cPs+Yh5HuFYyNENqT3kG7iJFLMOI7GzKUW+HiBresMD5BmgBHIjEwzPcJksTTjVMxBqsclF3Q8pq+IaRt5zShc1TAugBL1hPZKKXg8XiQjQQfAuqjYvnLb7XCGINEdw1lXSlGGpclu3nnukkXsurx9fsVH6czBmZAb2CcHb58u4DLgMsw4/ddUucZ5yvHfbK4cQtB54FpnH4MYCLQCKjgtlEHSwRjJLzTfEZGP946yJjnGTmve1dSKjStlHLnWs66FnjvIYgrZSM+4w+K9015I5PwZAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Higher than required&quot;
        title=&quot;&quot;
        src=&quot;/static/7926dd62b18862f6dff36ab1315effb3/8c557/HigherExample1.png&quot;
        srcset=&quot;/static/7926dd62b18862f6dff36ab1315effb3/4edbd/HigherExample1.png 175w,
/static/7926dd62b18862f6dff36ab1315effb3/13ae7/HigherExample1.png 350w,
/static/7926dd62b18862f6dff36ab1315effb3/8c557/HigherExample1.png 700w,
/static/7926dd62b18862f6dff36ab1315effb3/e996b/HigherExample1.png 1050w,
/static/7926dd62b18862f6dff36ab1315effb3/e9d87/HigherExample1.png 1176w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;In this case, the user is assigned a full &lt;strong&gt;SCM&lt;/strong&gt; license. However, the usage log reveals they only use two forms that require an &lt;strong&gt;Activity&lt;/strong&gt; license. This makes them a strong candidate for a permissions review to right-size their licensing.&lt;/p&gt;
&lt;h3 id=&quot;4-higher-than-required-no-activity&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#4-higher-than-required-no-activity&quot; aria-label=&quot;4 higher than required no activity permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;4. Higher Than Required (No Activity)&lt;/h3&gt;
&lt;p&gt;The user has an assigned license, but zero recorded system activity.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Technical meaning:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;No logins or operational activities were captured in the system logs.&lt;/li&gt;
&lt;li&gt;No entitlement usage was detected.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/bb717609d549be35d6ad8cc78e1a2386/0f246/NoActivity.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 37.714285714285715%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABKUlEQVR42qVR2WrDMBDUN9eBJpg8pN/ZI01DkjY+dWtle7qSE2roS6GGwbszO2I1Ek+7HW23W1pvNlSWJaV+vX6konigVVHMWP0dom1bWGsRKSIOEf/9xOvLMw7ve/R9ByV7aCUzpOzQNg3qus588DbDO4PgbIa3Zu4XmpDaIUaC1oah+TCVN05oOo1eWzjvYYzJ8Lc66RQIzjloo2HY75gTh4vGqQo4fSlcGovzVePaBVQ94ePc4lwpfCa+Mjxn0KgB+2ONt2PFnM5I3hP7KvYJHyKICEMceNOIYZj/MfWcqw9+1pn/0WaEEBbamDlRtyrnF/gqw32Yh6SU82Nxn+q7OeWZr5/y8y57lJQ5quQT6WWmafr1WktuWadtUm5912EcR0w3/T7zDT3DUAHy3noEAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;No activity log&quot;
        title=&quot;&quot;
        src=&quot;/static/bb717609d549be35d6ad8cc78e1a2386/8c557/NoActivity.png&quot;
        srcset=&quot;/static/bb717609d549be35d6ad8cc78e1a2386/4edbd/NoActivity.png 175w,
/static/bb717609d549be35d6ad8cc78e1a2386/13ae7/NoActivity.png 350w,
/static/bb717609d549be35d6ad8cc78e1a2386/8c557/NoActivity.png 700w,
/static/bb717609d549be35d6ad8cc78e1a2386/e996b/NoActivity.png 1050w,
/static/bb717609d549be35d6ad8cc78e1a2386/0f246/NoActivity.png 1118w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The user is assigned an SCM license, but no logging activity was recorded. There are a few possibilities here: the user may no longer require system access and should be disabled; or, the user might be a high-level manager who only needs periodic read access, or could perhaps be assigned a different appropriate role instead of holding an unused premium license.&lt;/p&gt;
&lt;h3 id=&quot;quick-overview-with-ai&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#quick-overview-with-ai&quot; aria-label=&quot;quick overview with ai permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Quick overview with AI&lt;/h3&gt;
&lt;p&gt;For a fast executive overview, you can copy the report&apos;s header data into Excel, then pass it to ChatGPT alongside this &lt;a href=&quot;https://github.com/TrudAX/denistrunin-blog/blob/master/src/posts/xpptools-licenseusagelog/notes.txt&quot;&gt;prompt&lt;/a&gt; to generate a helpful written summary for stakeholders.&lt;/p&gt;
&lt;h2 id=&quot;summary&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#summary&quot; aria-label=&quot;summary permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Summary&lt;/h2&gt;
&lt;p&gt;A license usage log utility provides insights into how users interact with the system by producing a usage report that compares the required license usage based on actual activity against the currently allocated licenses based on user roles.&lt;/p&gt;
&lt;p&gt;The tool is open source and can be downloaded from &lt;a href=&quot;https://github.com/TrudAX/XppTools/tree/master/DEVTools/DEVLicenseUtils&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I look forward to your feedback on it. Specifically:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Do the currently logged operations provide a clear enough view of license usage, or is more data needed?&lt;/li&gt;
&lt;li&gt;Do you have any guidance or best practices you can share with the community on how to adjust security roles based on this tool&apos;s output?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For general questions, please use the original post on &lt;a href=&quot;https://www.linkedin.com/posts/denis-trunin-3b73a213_with-the-upcoming-microsoft-license-enforcement-activity-7436416828597465088-I-g-&quot;&gt;LinkedIn&lt;/a&gt;. For bug reports or feature requests, please use the &lt;a href=&quot;https://github.com/TrudAX/XppTools/issues&quot;&gt;GitHub issue tracker&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I hope you found this post helpful. As always, if you have any suggestions for improvements or questions regarding this implementation, please don&apos;t hesitate to reach out.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Implement Service-based integration in D365FO]]></title><description><![CDATA[This blog post describes how to implement a synchronous integration with D365FO by creating a service using the External Integration framework.]]></description><link>https://denistrunin.com/integration-services/</link><guid isPermaLink="false">https://denistrunin.com/integration-services/</guid><pubDate>Mon, 02 Mar 2026 22:12:03 GMT</pubDate><content:encoded>&lt;p&gt;The &lt;strong&gt;External Integration&lt;/strong&gt; framework is an open-source &lt;a href=&quot;https://github.com/TrudAX/XppTools?tab=readme-ov-file#devexternalintegration-submodel&quot;&gt;solution&lt;/a&gt; designed for inbound and outbound integrations in D365FO.&lt;/p&gt;
&lt;p&gt;In this blog post, I will describe how to implement a service endpoint using the External Integration framework.&lt;/p&gt;
&lt;h2 id=&quot;key-design-principles&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#key-design-principles&quot; aria-label=&quot;key design principles permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Key Design Principles&lt;/h2&gt;
&lt;p&gt;X++ services are created using a standard service class and the &lt;a href=&quot;https://learn.microsoft.com/en-us/dynamics365/fin-ops-core/dev-itpro/data-entities/custom-services#json-based-custom-services&quot;&gt;Service and Service group objects&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Please note that a service is a synchronous integration pattern that increases system coupling. It should only be used when an asynchronous approach is not an option.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Before starting development, I analyzed several projects to see how different developers implemented their services. My key observations were:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The input parameters vary by integration and cannot be universal.&lt;/li&gt;
&lt;li&gt;The output parameters look very similar: typically a dataset containing one or more tables, along with some error flags. Additionally, most implementations included some kind of logging table, which usually varied per implementation.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Based on these observations, the following concept was implemented:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The service input contract will be a new class for each integration, providing maximum flexibility.&lt;/li&gt;
&lt;li&gt;The output contract will be a unified class containing the following data: a .NET dataset (with 0 to n tables), an output string, an error flag, and an error message.&lt;/li&gt;
&lt;li&gt;A common logging option will be provided.&lt;/li&gt;
&lt;li&gt;It must be possible to test the class directly inside D365FO.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;implementation-details-x-code&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#implementation-details-x-code&quot; aria-label=&quot;implementation details x code permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Implementation details: X++ code&lt;/h2&gt;
&lt;p&gt;I have provided sample code in the following &lt;a href=&quot;https://github.com/TrudAX/XppTools/blob/master/DEVTutorial/DEVExternalIntegrationSamples/AxClass/DEVIntegTutorialServiceTest.xml&quot;&gt;class&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 468px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/b037c60f397b5bf88b23aee043b4289e/90372/SolutionOverview.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 49.142857142857146%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABiklEQVR42oWSyZqCMBCEef8X8zSXEQXCvojs+6IjWFOJFy/jHIokfOm/K92tBUEOywwhhA/hhDAtD/pJ4PtowDBddZY6mw6EHcD1Yxx1AdsNUdYD6nZE2YyoqLLqoXXDiiStcDzZlIlv3VLBthfCDy4K4HiRWk0msGxfSZ4NJhLcC8JlgtPZhrbcd/TDjCRmIH8GcYb1/sATwM7P9nytj53aXtr2t/VN8qxNywPzckdTNzgbQrmJkhxhdIUfpkgucp9hXncm2rHcPktb70/QEOpmgClc2E7A2nlwvZj7kLCUziPElwJRnBO8Qcb8JW2kw36Y0FYlAREs1kWCTobNQg9o+0UVvO5m5eATTAGnZcMwruiahoVOVLcNy1VPveYNirJDmtUoqg63n+f/QPmEef1BnuVqTGRnLUKTtHwBCboSeM1rul0JxT9Pnh90uKDMMgUM2Ii6nThTA7KiVbOW02XBcz/eVNDHpmRFry47bMbh8AVdtzlPHGYzYNc5Z0IOe0DwjKqeeHf8qF9wM/EENvP4gwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Solution overview&quot;
        title=&quot;&quot;
        src=&quot;/static/b037c60f397b5bf88b23aee043b4289e/90372/SolutionOverview.png&quot;
        srcset=&quot;/static/b037c60f397b5bf88b23aee043b4289e/4edbd/SolutionOverview.png 175w,
/static/b037c60f397b5bf88b23aee043b4289e/13ae7/SolutionOverview.png 350w,
/static/b037c60f397b5bf88b23aee043b4289e/90372/SolutionOverview.png 468w&quot;
        sizes=&quot;(max-width: 468px) 100vw, 468px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;To create a new service using the External Integration framework:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create a new class that extends &lt;strong&gt;DEVIntegServiceExportBase&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Create an entry point that is always a single line—just a call referencing the main method.&lt;/li&gt;
&lt;li&gt;Implement the main method to contain only the service&apos;s business logic.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;A code sample looks like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;DEVIntegTutorialServiceTest&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;extends&lt;/span&gt; DEVIntegServiceExportBase
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;/// DEMO #1 (DataTables / DataSet):&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;DEVIntegServiceExportResponseContract&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getSOInfoDataTable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;DEVIntegTutorialServiceTestContract&lt;/span&gt; _contract&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;serviceCallProcess&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;methodStr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;DEVIntegTutorialServiceTest&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; calculateGetSOInfoDataTable&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _contract&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calculateGetSOInfoDataTable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;DEVIntegTutorialServiceTestContract&lt;/span&gt; _contract&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;DEVIntegServiceExportResponseContract&lt;/span&gt; _response&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;validateAndDelay&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;_contract&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token function&quot;&gt;changecompany&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;_contract&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parmCompanyId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token class-name&quot;&gt;SalesTable&lt;/span&gt; salesTable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; SalesTable&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;_contract&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parmSalesId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;salesTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;RecId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;strFmt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Sales order %1 not found in company %2&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _contract&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parmSalesId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _contract&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parmCompanyId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

            &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;initDataTableHelper&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

            dataTableHelper&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addDataTable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&apos;SOHeader&apos;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            dataTableHelper&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addRowItem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&apos;SalesId&apos;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;     salesTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;SalesId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            dataTableHelper&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addRowItem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&apos;CustAccount&apos;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; salesTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;CustAccount&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            dataTableHelper&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addRow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

            &lt;span class=&quot;token comment&quot;&gt;// Lines table: multiple rows with sales lines&lt;/span&gt;
            dataTableHelper&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addDataTable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&apos;SOLine&apos;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

            &lt;span class=&quot;token class-name&quot;&gt;SalesLine&lt;/span&gt; salesLine&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;select&lt;/span&gt; salesLine
                &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;salesLine&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;SalesId &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; salesTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;SalesId
            &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                dataTableHelper&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addRowItem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&apos;SalesId&apos;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;  salesLine&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;SalesId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                dataTableHelper&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addRowItem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&apos;ItemId&apos;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;   salesLine&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ItemId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                dataTableHelper&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addRowItem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&apos;SalesQty&apos;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; salesLine&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;SalesQty&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                dataTableHelper&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addRow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

            &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addDataTableHelperToResponse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;_response&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;/// DEMO #2 (Temp table / DataSet):&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;DEVIntegServiceExportResponseContract&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getSOInfoTempTable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;DEVIntegTutorialServiceTestContract&lt;/span&gt; _contract&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;serviceCallProcess&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;methodStr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;DEVIntegTutorialServiceTest&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; calculateGetSOInfoTempTable&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _contract&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calculateGetSOInfoTempTable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;DEVIntegTutorialServiceTestContract&lt;/span&gt; _contract&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;DEVIntegServiceExportResponseContract&lt;/span&gt; _response&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;validateAndDelay&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;_contract&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token function&quot;&gt;changecompany&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;_contract&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parmCompanyId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token class-name&quot;&gt;SalesTable&lt;/span&gt; salesTable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; SalesTable&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;_contract&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parmSalesId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;salesTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;RecId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;strFmt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Sales order %1 not found in company %2&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _contract&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parmSalesId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _contract&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parmCompanyId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

            &lt;span class=&quot;token class-name&quot;&gt;SalesTable&lt;/span&gt; tmpSalesTable&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            tmpSalesTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setTmp&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            tmpSalesTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;SalesId     &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; salesTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;SalesId&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            tmpSalesTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;CustAccount &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; salesTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;CustAccount&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            tmpSalesTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;doinsert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

            &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;initDataTableHelper&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

            &lt;span class=&quot;token comment&quot;&gt;// Return temp table as a dataset DataTable (SOHeaderTmp)&lt;/span&gt;
            dataTableHelper&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addTmpTable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&apos;SOHeaderTmp&apos;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; tmpSalesTable&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
                    &lt;span class=&quot;token attribute&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;fieldNum&lt;/span&gt;&lt;span class=&quot;token attribute-arguments&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;SalesTable&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; SalesId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;token class-name&quot;&gt;fieldNum&lt;/span&gt;&lt;span class=&quot;token attribute-arguments&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;SalesTable&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; CustAccount&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

            &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addDataTableHelperToResponse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;_response&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In case of errors, simply throw an exception, and the framework will handle it automatically. There are also a few helper methods available that can return either a temporary table or a dataset.&lt;/p&gt;
&lt;p&gt;On the caller side, if the calling system is .NET-based, it needs to analyze the result by following these steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Check the &lt;strong&gt;IsSuccess&lt;/strong&gt; flag, and review the error details in &lt;strong&gt;ErrorMessage&lt;/strong&gt; if it failed.&lt;/li&gt;
&lt;li&gt;If successful, deserialize the &lt;strong&gt;MessageDataSet&lt;/strong&gt; parameter into a &lt;strong&gt;System.Data.DataSet&lt;/strong&gt; object and read the required data.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;implementation-details-user-configuration&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#implementation-details-user-configuration&quot; aria-label=&quot;implementation details user configuration permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Implementation details: User configuration&lt;/h2&gt;
&lt;p&gt;After creating a service class, it must be added to the &lt;strong&gt;External Integration &gt; Setup &gt; Service message type&lt;/strong&gt; form.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/7bda9f8f5b69e9ff6a755fa9135ddb74/394f7/ServiceMainForm.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 77.14285714285715%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACGUlEQVR42pVU2ZLSQBTlO322Si1lUKDG8Z/8DedlHiyIAhMyIQshkM6+L50cb0Mc0QdhuurU7XTuPTl9lwzeD8d49XqKz7e3mIzHmEymGI0+0vMUX+7u6OwT3r19g5vhEKObIdkPf0GcnWPghBxfv2XIixJ13ZCtkWYlqrJEWVUoyaZJcnzXdR0urUESB6iKmAJzIhHIUOTpEWVx2mvaBtJcgvwo40lRoKwVrGWZzjXkeY6mysmPRGUpBtqWwbQDgg9ZtcCCHFHWkS2gmS6itAZzDsdg295BVZ+wUTdwGUMUxccbKLqDMIzQ1BUGlpPAZhn2XkGkIWwvh5d0cGMORukIM34kNHQdcRTBdRkYkSVpgqIokJEq2UwQxQl4Q4Sc8//mpG1bJHEEn7mkoAZEGimXHZ23PURuBcR+0DT8t0//oo/pIZz2iwWk+3uYywViy0K43SI1TTRh2H+0ey7YRYVCiS3NsX54gDGfQ5/NoEsS2HKJyvN6pz/Vv0xIzoHnQiZ1hqpiZxiwDB2RIOuveo6rchgnMZjvoWoaVPwETsG85eBif4bLhEIhtUugG2iCEI0fnOD5aKllOuBlCimJ0L7P8GO+gnfwcbAY9jsXtqKjdJyX51CsrbLGT6qyKMZutcKepkTYPKQpq8SYFs+4rg9plh3XRUZjJlIg9DQUV9Nk1ER4jqvaJvR9eFTprm9ogZp+HELRv4S/APIBagE4sguJAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Service main form&quot;
        title=&quot;&quot;
        src=&quot;/static/7bda9f8f5b69e9ff6a755fa9135ddb74/8c557/ServiceMainForm.png&quot;
        srcset=&quot;/static/7bda9f8f5b69e9ff6a755fa9135ddb74/4edbd/ServiceMainForm.png 175w,
/static/7bda9f8f5b69e9ff6a755fa9135ddb74/13ae7/ServiceMainForm.png 350w,
/static/7bda9f8f5b69e9ff6a755fa9135ddb74/8c557/ServiceMainForm.png 700w,
/static/7bda9f8f5b69e9ff6a755fa9135ddb74/394f7/ServiceMainForm.png 707w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;From this form, we can also test the service class using the &lt;strong&gt;Test&lt;/strong&gt; button.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 612px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/aee8b9323ca1bd72f910cd3ec0be2d2c/8c76f/TestServiceInitialRun.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 72.57142857142857%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABGUlEQVR42q1Ui2qEMBDM/39iD/WOnvEdq8a8fEyzEY5StAW9wLBuNLM7s0E2DAPSNEXTNFBKYZ5nXFmsbVukz0+URYEs4+j7LrxY1/WFvfyQ0C1Ab4BBA6Pd4j9n/iYkqVEUIeMZOOf4uN2Q55m3oEZVlei6LwghEMcx2laEfSnlYadsGPoglWLrD9JzUeQvCNGg7zrUdb0R1hvhsiz7hNZa30kF59zuB3u+UU6Ee2Cjr5YkMe53QhK6ogI/Uf/Kw57vdA/MGB1kkQy6NlprGGNOg01eKk95qEryry5G3uV5HiZME5+n6RqhtQ7jqKGNhdImRGPcabBSSDyeBaSe3wKmtEXXS0hlLmNUNBTv2dElPeUh/V3eSfgNMtiTzrn3KNkAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Test service initial run&quot;
        title=&quot;&quot;
        src=&quot;/static/aee8b9323ca1bd72f910cd3ec0be2d2c/8c76f/TestServiceInitialRun.png&quot;
        srcset=&quot;/static/aee8b9323ca1bd72f910cd3ec0be2d2c/4edbd/TestServiceInitialRun.png 175w,
/static/aee8b9323ca1bd72f910cd3ec0be2d2c/13ae7/TestServiceInitialRun.png 350w,
/static/aee8b9323ca1bd72f910cd3ec0be2d2c/8c76f/TestServiceInitialRun.png 612w&quot;
        sizes=&quot;(max-width: 612px) 100vw, 612px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The system will automatically create an empty contract. We just need to specify the parameter values and press the &lt;strong&gt;Execute&lt;/strong&gt; button.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 461px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/1100269d345db37f1fb74b9ea31dd50d/f816d/TestService1.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 182.85714285714286%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAlCAYAAABCr8kFAAAACXBIWXMAAA7EAAAOxAGVKw4bAAADCElEQVR42q1WaW+jMBTk//+0rdpsP2xzEHJAQkggJNwYDLPznKaqtO22IUV6MkZ4/I55Y1tVVWG1XsP3fex2O6RpirZt0fc9hjyWALrrJbYbDxvPJagPZ26jadSni2Szzza0tO5QqB5106FUHaqmR15dxuvC9/YR8PvvVqs1okThmDbwoxKnTCE8X+YfedF1Heq6hua6T0Iu4dhTrBZz7LYe9oGPpWPz2wye5yEIdgiYW8nxMYpwPp0wn8/huS4izg+HPeLj0WxiACVXvr/FjpamiVnguR5tzdyusF6tzLhaLgnsI03O3CQw79vNxgDLhlVZSg5gSQhSWdlNqnvvY0kurq5nBE6TBFmWoeSORVH8Y2/fZXz3j3wXs3SnDWXGL38wGb9gMhmbMPf7/SW0G82SMLM8h+LYiDXNmymlbrYLIEPdsVviMMSBJjsNzafJYRLHcJ6esHj+je1iYegieR0EKJ6kpEpEWkQEi0mDmsntX0l8qxkPJXbNSdNqk0chac0eN+ONZnh4YEWPZPtPPMbD+JzjlJBTtUZRaYqDNu9l3Zn3rGy/bZaiymRlAxGJsqLbinRpWvOe54WZ667/tlkNRSNJCrjTCZZjkprk3m23CMOD6Z6cXXNTyFfA5egRzsMDFqMRYjb7Z/L0JaAiomp7lOcYObmnivy/ivwlYE1AphFFnmE9myFkxYXYG0qTNHvX6QEeck3NXAXTKSIKQ3I4IOU85HhrC1qq5ZlStSR3/TM8vAJGUUhyx6Zr7gM0RWEOWQxpN/XaQgI8pDCmKK0UheeJTcqElK6547Ao3vAqG0AePjYlLJCDh2A5RXdwyDVDrku2GWVMUWybe64iV2JLlQVIaCL5kzzelcP8fIL9+Ig9+3hm23AptHflUABnD78Q8MIkt4TrTWBAyLyr8GKkeCVp2B2KJqKLwTmkezn1UOv2ZzqlYUFEsbNTjIynX8JjdGhBXvWwN3ro/B7BeX6Gy4LIdWS4hwJID/3ZlDbDhkdplib3iUNeUBB4revJv479PLQgAvgXggtLl/U6FSEAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Test results1&quot;
        title=&quot;&quot;
        src=&quot;/static/1100269d345db37f1fb74b9ea31dd50d/f816d/TestService1.png&quot;
        srcset=&quot;/static/1100269d345db37f1fb74b9ea31dd50d/4edbd/TestService1.png 175w,
/static/1100269d345db37f1fb74b9ea31dd50d/13ae7/TestService1.png 350w,
/static/1100269d345db37f1fb74b9ea31dd50d/f816d/TestService1.png 461w&quot;
        sizes=&quot;(max-width: 461px) 100vw, 461px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;If the call is unsuccessful, an error message will be generated.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 586px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/9b92ce29288fc4dc93095de2d52a72c0/a76f4/TestServiceBadResults.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 92%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAYAAABb0P4QAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABoklEQVR42qVUa4+bMBDk//+6ql/udEpCCBDeNrbBBkyY2/UpVU/NtQ2HNNgyq2E8+4i01hjHEX3f02pxu92wbdj9REyY5xnO8RFpmiBLL7DWPgze/uNPkTEanuLcsmFeef3AboWGFLZdj0teoWpkQF40sGTDNDk4Z7EsC4wxaNsW8zyFcz4jzY8VlkUeriy6BunljLe3F8SnI5IkDudVVQbE8QnXa07WpMHzRxZEnBA3TRSgsN2+kY3fCaUUOB0PuFJyyuIK1csAre7ow3o///ztM6JhGKC0Rd3K4GUnNPQwQaphFyJtRozOoylLCNmjbloURQm/rjvrkAntjMvPH8hfX1CR6UqpbxS2GeCoAAepYejKzjqslBtPrz0ISRlGR75R29EfPGV6oUpfViZ9HoFQhSz2WFcP75df4AJ+FhH7xb3bdQJ1XUMIQfsuYJ5nIvZPIRCyyiRJcKLuyLIstNhXA+KfSbkrPMcxDocDKiqflUqG8Tcl3Ms86h4SskJWVRLZ/bpSynB9QXteuXd51HE87zmGB8efhPSRvfrq2Z6ctu/Gx3qK3MCOxAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Test service Exception&quot;
        title=&quot;&quot;
        src=&quot;/static/9b92ce29288fc4dc93095de2d52a72c0/a76f4/TestServiceBadResults.png&quot;
        srcset=&quot;/static/9b92ce29288fc4dc93095de2d52a72c0/4edbd/TestServiceBadResults.png 175w,
/static/9b92ce29288fc4dc93095de2d52a72c0/13ae7/TestServiceBadResults.png 350w,
/static/9b92ce29288fc4dc93095de2d52a72c0/a76f4/TestServiceBadResults.png 586w&quot;
        sizes=&quot;(max-width: 586px) 100vw, 586px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;logging&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#logging&quot; aria-label=&quot;logging permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Logging&lt;/h2&gt;
&lt;p&gt;The framework provides different logging options tailored to various business use cases.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/5985bbc2758890d25697e9a04e2b9760/4e814/ServiceLogging.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 44.57142857142857%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABJklEQVR42pWS226DMBBE+f/v61urJhQCAXzHNubW6a5JpOSNIh15DfKwM+vi42LhQ0QgnHWYpgnrumBZZszzTOtC+5XqhNFZaKUwjg4xBEwxYqNvrxQpRaQ0QQxDFpNS0oEx45yD1hrWWgQfUNcVyusFbdvQzzUCCXvCGk17Q7VFMegJ2i34ujTopEd5E6gaibuKkG5G3Sp8ft8wKIem7WHocPVToiyvWajv7mibhhrqsoNi33/BrOt2rNuGjXm855ots3WlJHXqEcnqE3aVY3lEU+Dkw/kIMZB9c2AMDMWR84zhgHI9L0idiqHPFtn2UyQE/8ZpwX3fUVdlHgpn5R8D4fqV04J8lXjiuRN/4ImU0hv/EFyhpICkHKUQVMu85+tyYPP6Bwvauiij3xeyAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Service logging&quot;
        title=&quot;&quot;
        src=&quot;/static/5985bbc2758890d25697e9a04e2b9760/8c557/ServiceLogging.png&quot;
        srcset=&quot;/static/5985bbc2758890d25697e9a04e2b9760/4edbd/ServiceLogging.png 175w,
/static/5985bbc2758890d25697e9a04e2b9760/13ae7/ServiceLogging.png 350w,
/static/5985bbc2758890d25697e9a04e2b9760/8c557/ServiceLogging.png 700w,
/static/5985bbc2758890d25697e9a04e2b9760/e996b/ServiceLogging.png 1050w,
/static/5985bbc2758890d25697e9a04e2b9760/4e814/ServiceLogging.png 1335w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The following logging options are available:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;None&lt;/strong&gt; – No logging.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Statistics &amp;#x26; Errors&lt;/strong&gt; – Creates one summary record per day for successful calls (showing the total number of calls and lines processed), PLUS detailed records for all calls that encounter errors during execution.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Errors only&lt;/strong&gt; – Only failed calls are logged.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Request&lt;/strong&gt; – Logs each request, including its parameters, status, and statistics (start/end date and number of lines).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Full&lt;/strong&gt; – Same as &lt;strong&gt;Request&lt;/strong&gt;, but also logs the response payload (note: this may consume significant storage space).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Recommended values for production environments are &lt;strong&gt;&quot;Request&quot;&lt;/strong&gt; or &lt;strong&gt;&quot;Statistics &amp;#x26; Errors&quot;&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&quot;notes-on-consuming-services&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#notes-on-consuming-services&quot; aria-label=&quot;notes on consuming services permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Notes on consuming services&lt;/h2&gt;
&lt;p&gt;Services can be consumed directly by connecting to the D365FO instance using an AppId. However, in recent projects, we have utilized the &lt;strong&gt;Azure API Management&lt;/strong&gt; service. Adrià has written an &lt;a href=&quot;https://ariste.info/2022/02/azure-api-management-dynamics-365-fo/&quot;&gt;excellent article&lt;/a&gt; detailing this approach.&lt;/p&gt;
&lt;p&gt;In short, you will need to create an HTTP endpoint:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;xml&quot;&gt;&lt;pre class=&quot;language-xml&quot;&gt;&lt;code class=&quot;language-xml&quot;&gt;https://testsystemlink.sandbox.operations.dynamics.com/api/services/

With a new operation:
Display name: getSOInfoDataTable
Name: getsoinfodatatable
URL:  /DEVIntegTutorialServiceTestGroup/DEVIntegTutorialServiceTest/getsoinfodatatable&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;and apply the following policy&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;xml&quot;&gt;&lt;pre class=&quot;language-xml&quot;&gt;&lt;code class=&quot;language-xml&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;policies&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;inbound&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;send-request&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;mode&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;new&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;response-variable-name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;bearerToken&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;timeout&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;20&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;ignore-error&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;false&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;set-url&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;https://login.microsoftonline.com/{{TenantId}}/oauth2/token&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;set-url&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;set-method&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;POST&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;set-method&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;set-header&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Content-Type&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;exists-action&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;override&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
                &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;application/x-www-form-urlencoded&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;set-header&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;set-body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;@{return &quot;client_ID=4989d73b-1e25&amp;amp;client_secret=jSv8Q~m~jmO0QtZFmi_h4di&amp;amp;resource=https://testsystemlink.sandbox.operations.dynamics.com/&amp;amp;grant_type=client_credentials&quot;;}&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;set-body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;send-request&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;set-backend-service&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;base-url&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://testsystemlink.sandbox.operations.dynamics.com/api/services/DEVIntegTutorialServiceTestGroup&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;set-header&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Authorization&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;exists-action&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;override&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;@(&quot;Bearer &quot; + (String)((IResponse)context.Variables[&quot;bearerToken&quot;]).Body.As&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;JObject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;()[&quot;access_token&quot;])&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;set-header&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;base&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;inbound&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;backend&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;base&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;backend&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;outbound&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;base&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;outbound&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;on-error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;base&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;on-error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;policies&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Next, test the API using the following parameters:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;_contract&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;CompanyId&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;USMF&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;DelaySeconds&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;SalesId&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;001036&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Alternatively, if you are using Postman:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;https&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;//d365apiserv.azure-api.net/mytest/DEVIntegTutorialServiceTest/getSOInfoDataTable&lt;/span&gt;

POST
subscription-key 
991874b1c..

Body raw
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;_contract&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;CompanyId&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;USMF&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;DelaySeconds&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;SalesId&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;001036&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;summary&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#summary&quot; aria-label=&quot;summary permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Summary&lt;/h2&gt;
&lt;p&gt;The External Integration framework offers the following benefits for service development:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A standard output contract that includes workload statistics and error flags.&lt;/li&gt;
&lt;li&gt;Automatic exception handling.&lt;/li&gt;
&lt;li&gt;Flexible logging options.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All the classes discussed can be found on &lt;a href=&quot;https://github.com/TrudAX/XppTools/tree/master/DEVTutorial/DEVExternalIntegrationSamples&quot;&gt;GitHub&lt;/a&gt; and serve as a great starting point for your own integrations.&lt;/p&gt;
&lt;p&gt;I hope you found this post helpful. As always, if you have any suggestions for improvements or questions regarding this implementation, please don&apos;t hesitate to reach out.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Sync data from Dynamics 365 Finance & Operations Azure SQL Database (Tier2) to local SQL Server (AxDB)]]></title><description><![CDATA[A new utility to synchronize data from D365FO cloud environments to local AxDB, featuring incremental sync and smart strategies.]]></description><link>https://denistrunin.com/d365tools-dbsync/</link><guid isPermaLink="false">https://denistrunin.com/d365tools-dbsync/</guid><pubDate>Thu, 15 Jan 2026 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;One of the frequent challenges in Dynamics 365 Finance &amp;#x26; Operations development is keeping the local development database (&lt;code class=&quot;language-text&quot;&gt;AxDB&lt;/code&gt;) synchronized with fresh data from a Tier2 (UAT/Sandbox) environment. Standard approaches often involve restoring a full BACPAC, which is time-consuming and overwrites everything, or manually copying data, which is tedious and error-prone. To address this, I created the &lt;strong&gt;D365FO-DBSync&lt;/strong&gt; utility. This tool helps developers synchronize data from D365FO cloud environments to their local development databases, making it easier to test with production-like data.&lt;/p&gt;
&lt;p&gt;The main idea is to make the last X records (ordered by &lt;code class=&quot;language-text&quot;&gt;RecId&lt;/code&gt;) the same between Tier2 and &lt;code class=&quot;language-text&quot;&gt;AxDB&lt;/code&gt;. E.g. A typical dynamics implementation has ~2000 tables with the data, around 200 tables are transactional tables that exceed 100k records, so if we sync last 100k records per table we can get a compact DB with the most of the base data and recent transactional data.&lt;/p&gt;
&lt;h2 id=&quot;usage&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#usage&quot; aria-label=&quot;usage permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Usage&lt;/h2&gt;
&lt;p&gt;For detailed technical instructions and setup steps, please refer to the &lt;a href=&quot;https://github.com/TrudAX/D365FO-DB-Sync&quot;&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The main workflow is straightforward:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Prepare your environment&lt;/strong&gt;: Whitelist your IP and get database credentials from LCS.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Configure the tool&lt;/strong&gt;: Enter the connection details for both the source (Tier2) and destination (Local AxDB).&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/fa26ad6bce05f19f82570b8a1fc51ed9/d8817/Configuration.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 63.42857142857142%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAB70lEQVR42pVTCW7bMBDU/39mF7WtOj4SwEgMHdFl3bdITWfpA4WbAC2BASXucnZ2R7LCMFxUdY28KFQ/DBjGEeM0YVIKk/4e8zwb6CdYkect27JElWWqqyoI5N0814LaoL+ha2o0ZYEmz9EzZ2waDISJty2s+HCwxyzDeEl1n8TcL+iTBH0cm31MU0xpZnbJm4IQ6W6H6PyBie+p46COIgzMV7xrZb7/SwNsddBeEMAPQyRZjojBS37dPZLIc1wUKJlTnE5oOBYZT0Ciuu/REopFrWi/tzseDkmiS9dF5ftoo9BguCntqEDUDLygYqphXhNe49LRxHPN+MwRWCFnmF9SVHmuxq6DZlXQEIESk3hWZCkyGQVnNUtM6ytueQ+IKa7rLtgxlFZq5i5Oyd52LVJWrUny+RkgYVE542gk3eSIy8/L+nh/X3ieB9/3VUl376umm3K552xedi/YH/ZYb9Y4n8+YOD9FRR3V/0X49nZcOK6DjC23tF1LK1wNlclFOVv9XMG2bSx/LHE4HB9Eo4znmbCqKtMyk5SoEUKBKMDVfTj8NEJxnybkdFuIpNiXhIQh5DzUn4H7fEThZrPBdrs1Ck/8ZKSYxEXAfxNK69KuzHG1XuH1+PpoWVT+M+F9Sfs1fyshvkMII36bX5nyG9KT6J0aY5lwAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Configuration Window&quot;
        title=&quot;&quot;
        src=&quot;/static/fa26ad6bce05f19f82570b8a1fc51ed9/8c557/Configuration.png&quot;
        srcset=&quot;/static/fa26ad6bce05f19f82570b8a1fc51ed9/4edbd/Configuration.png 175w,
/static/fa26ad6bce05f19f82570b8a1fc51ed9/13ae7/Configuration.png 350w,
/static/fa26ad6bce05f19f82570b8a1fc51ed9/8c557/Configuration.png 700w,
/static/fa26ad6bce05f19f82570b8a1fc51ed9/e996b/Configuration.png 1050w,
/static/fa26ad6bce05f19f82570b8a1fc51ed9/d8817/Configuration.png 1238w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Define strategies&lt;/strong&gt;: Choose which tables to copy and how (e.g., last 10k records).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Sync&lt;/strong&gt;: Run the discovery and process steps to synchronize the data.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/d4f57a78edc61c9cd2b5c1a8233097e7/92338/ExecutionWindow.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 64.57142857142857%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAAA7DAAAOwwHHb6hkAAACPElEQVR42mVT12ocQRDc/3/yu/UiyRb4L4xA6dXYSDK6zXObcw535a5Z74HxQDE9tR2qm15DqSOSJEHf95jnGdM0YVkXjXmZL9jfy7JgXVeN0+l0sckz1jgej4jCCOM4XtDUNZqm0Q476qbGMAyXQM3VGzcMo35TkMFAkqx2Pp91ABW3Tas5HhYJgwCe66HrOs0xOM9z9F1/KcR4g5l5+OBZRL5lmrAtWyfi4TjGacQyby3z7IoYt0Mr7MSZH8dx0kG9VCvKClGcSEuiXni2NE4zeu3Dma6YZs5ZZihd8N6wcoYKvnKlJR+xoCokUZn+vTNUeYKpa9C2LYJI+GZrGadV2voX5/MJxrenD3z67uDqwcPXRwt3Lx6uH13cPrm4e/a2W7jbZx9X9yZunhW+vPji4+D6wcYNfcX+fG/hp5vC+PV+wKvp41h0+PFu4dU+ws9a/PZCbdtRKd8VvLTBuxdBiZ+X1rCiAlZYwAwyuTM4SY2y6WFYhw+4lomxb+G7DpIoxDh0KLIEaRyha6qN6zvkaYxV5jyJ3dalRplnMpocQ9dK3ADjcDjAdhy0QtiODSUzraoKcRwjlERFWYC7yp2LWEDWhnZeFIJcr1ghNmfMbTCYgAjDUCdhgqIskUnlJBWVWfrfvWN/78m4j4ZtO3h7fYNJpbJ7lmXBdV0oXyGhSvmLfOXDkS6oJopkjvKmaqU2Hy54LT8I99RIswxBGFxU0g7kr2AwW2PlTmZGcEeHcdBtk99VEVTJf/oPKFLXSbIgK+EAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Execution Window&quot;
        title=&quot;&quot;
        src=&quot;/static/d4f57a78edc61c9cd2b5c1a8233097e7/8c557/ExecutionWindow.png&quot;
        srcset=&quot;/static/d4f57a78edc61c9cd2b5c1a8233097e7/4edbd/ExecutionWindow.png 175w,
/static/d4f57a78edc61c9cd2b5c1a8233097e7/13ae7/ExecutionWindow.png 350w,
/static/d4f57a78edc61c9cd2b5c1a8233097e7/8c557/ExecutionWindow.png 700w,
/static/d4f57a78edc61c9cd2b5c1a8233097e7/e996b/ExecutionWindow.png 1050w,
/static/d4f57a78edc61c9cd2b5c1a8233097e7/2cefc/ExecutionWindow.png 1400w,
/static/d4f57a78edc61c9cd2b5c1a8233097e7/92338/ExecutionWindow.png 1411w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;custom-copy-strategies&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#custom-copy-strategies&quot; aria-label=&quot;custom copy strategies permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Custom Copy Strategies&lt;/h2&gt;
&lt;p&gt;The default behavior of the tool is to copy the last X records (based on &lt;code class=&quot;language-text&quot;&gt;RecId&lt;/code&gt;). While this works for most transaction tables, you might need more control for some tables.&lt;/p&gt;
&lt;p&gt;You can define custom copy strategies using the following syntax:&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;TableName|RecordCount|sql:CustomQuery -truncate&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;also the CustomQuery may contains the following placeholders:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;@recordCount&lt;/code&gt;: Replaced with the record count defined in the global parameters.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;@sysRowVersionFilter&lt;/code&gt;: Used for enabling &lt;strong&gt;INCREMENTAL&lt;/strong&gt; mode in custom SQL strategies.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;examples&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#examples&quot; aria-label=&quot;examples permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Examples&lt;/h3&gt;
&lt;p&gt;Let&apos;s describe different scenarious where a custom copy strategy is required.&lt;/p&gt;
&lt;h4 id=&quot;copy-tables-where-a-row-contains-large-data&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#copy-tables-where-a-row-contains-large-data&quot; aria-label=&quot;copy tables where a row contains large data permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Copy tables where a row contains large data&lt;/h4&gt;
&lt;p&gt;Some tables may contains images or some binary info and copying a standard 100k records may take a lot of time. For such scenario one you can specify custom RecordCount to copy to limit the number of records. Usage examples:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;*   `ECORESPRODUCTIMAGE|1000`: Copies the last 1,000 product images.
*   `WHSCONTAINERTABLE|50000`: Copies the last 50,000 warehouse containers.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id=&quot;copy-inventory-dimensions-if-licence-plate-is-usedinventdim&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#copy-inventory-dimensions-if-licence-plate-is-usedinventdim&quot; aria-label=&quot;copy inventory dimensions if licence plate is usedinventdim permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Copy Inventory dimensions if Licence plate is used(InventDim)&lt;/h4&gt;
&lt;p&gt;In case you use a WHS solution, InventDim table may contains a lot of records with a LicensePlateId. During the copy you can&apos;t simply take the latest records, as you miss a lot of references to InventDimId that have a blank LicensePlateId. The solutoin for this is to take all dimensions without LicensePlateId PLUS all recent records with LicensePlateId. In this case you transfer the records that may be used in some setup and the latest transactional records. A setting for this looks the following:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;sql&quot;&gt;&lt;pre class=&quot;language-sql&quot;&gt;&lt;code class=&quot;language-sql&quot;&gt;    InventDim&lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;sql&lt;/span&gt;: &lt;span class=&quot;token keyword&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;FROM&lt;/span&gt; InventDim &lt;span class=&quot;token keyword&quot;&gt;WHERE&lt;/span&gt; RecId &lt;span class=&quot;token operator&quot;&gt;IN&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;SELECT&lt;/span&gt; RecId &lt;span class=&quot;token keyword&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;SELECT&lt;/span&gt; RecId &lt;span class=&quot;token keyword&quot;&gt;FROM&lt;/span&gt; InventDim &lt;span class=&quot;token keyword&quot;&gt;WHERE&lt;/span&gt; LICENSEPLATEID &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;AND&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;PARTITION&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5637144576&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;AND&lt;/span&gt; DATAAREAID &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;USMF&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;AND&lt;/span&gt; WMSLOCATIONID &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;UNION&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;SELECT&lt;/span&gt; RecId &lt;span class=&quot;token keyword&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;TOP&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;50000&lt;/span&gt; RecId &lt;span class=&quot;token keyword&quot;&gt;FROM&lt;/span&gt; InventDim &lt;span class=&quot;token keyword&quot;&gt;ORDER&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;BY&lt;/span&gt; RecId &lt;span class=&quot;token keyword&quot;&gt;DESC&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; t&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; u&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;AND&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;@sysRowVersionFilter&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;ORDER&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;BY&lt;/span&gt; RecId &lt;span class=&quot;token keyword&quot;&gt;DESC&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id=&quot;copy-inventory-onhand-inventsum&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#copy-inventory-onhand-inventsum&quot; aria-label=&quot;copy inventory onhand inventsum permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Copy inventory onhand (InventSum)&lt;/h4&gt;
&lt;p&gt;If InventSum is large, you may deside to copy only records that have some values. These records has the foolowing filter (&lt;code class=&quot;language-text&quot;&gt;Closed = 0&lt;/code&gt;), and it can reduce data volume. A settings for this will be the following:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;sql&quot;&gt;&lt;pre class=&quot;language-sql&quot;&gt;&lt;code class=&quot;language-sql&quot;&gt;    InventSum&lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;sql&lt;/span&gt;: &lt;span class=&quot;token keyword&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;FROM&lt;/span&gt; InventSum &lt;span class=&quot;token keyword&quot;&gt;WHERE&lt;/span&gt; Closed &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;AND&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;@sysRowVersionFilter&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;ORDER&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;BY&lt;/span&gt; RecId &lt;span class=&quot;token keyword&quot;&gt;DESC&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id=&quot;copy-inventory-reservations&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#copy-inventory-reservations&quot; aria-label=&quot;copy inventory reservations permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Copy inventory reservations&lt;/h4&gt;
&lt;p&gt;To optimize a copy of inventory reservation (WHSINVENTRESERVE) we can use a filter that includes all reservation for a level 1 PLUS any records modified in the last 93 days. This ensures you have both current availability and recent history.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;sql&quot;&gt;&lt;pre class=&quot;language-sql&quot;&gt;&lt;code class=&quot;language-sql&quot;&gt;    WHSINVENTRESERVE&lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;sql&lt;/span&gt;: &lt;span class=&quot;token keyword&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;FROM&lt;/span&gt; WHSINVENTRESERVE &lt;span class=&quot;token keyword&quot;&gt;WHERE&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HIERARCHYLEVEL &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;AND&lt;/span&gt; AVAILPHYSICAL &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;OR&lt;/span&gt; MODIFIEDDATETIME &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; DATEADD&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;DAY&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;93&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; GETUTCDATE&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;AND&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;PARTITION&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5637144576&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;AND&lt;/span&gt; DATAAREAID &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;USMF&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;AND&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;@sysRowVersionFilter&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;ORDER&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;BY&lt;/span&gt; RecId &lt;span class=&quot;token keyword&quot;&gt;DESC&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;copy-performance-optimization&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#copy-performance-optimization&quot; aria-label=&quot;copy performance optimization permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Copy Performance Optimization&lt;/h2&gt;
&lt;p&gt;Copy speed is optimized using multiple approaches.&lt;/p&gt;
&lt;h3 id=&quot;sysrowversion-optimization-incremental-sync&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#sysrowversion-optimization-incremental-sync&quot; aria-label=&quot;sysrowversion optimization incremental sync permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;SysRowVersion Optimization (Incremental Sync)&lt;/h3&gt;
&lt;p&gt;The tool saves a &lt;code class=&quot;language-text&quot;&gt;SysRowVersion&lt;/code&gt; for every table during the first run. If a saved value exists, it tries to estimate the changes first by querying only system fields before copying all data.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If changes are below a certain percentage(e.g. 40%), it deletes only changed records and re-inserts them.&lt;/li&gt;
&lt;li&gt;If changes are higher, it truncates the table (to save time on delete) and re-inserts the table.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This may give a reduction in data transfer for tables with minimal changes.&lt;/p&gt;
&lt;h3 id=&quot;smart-strategies&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#smart-strategies&quot; aria-label=&quot;smart strategies permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Smart Strategies&lt;/h3&gt;
&lt;p&gt;You are not limited to just &quot;all or nothing&quot;. You can exclude specific tables (e.g., &lt;code class=&quot;language-text&quot;&gt;Sys*&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;*Staging&lt;/code&gt;) or write custom SQL to fetch only relevant data (e.g., specific &lt;code class=&quot;language-text&quot;&gt;DataAreaId&lt;/code&gt;).&lt;/p&gt;
&lt;h3 id=&quot;execution-efficiency&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#execution-efficiency&quot; aria-label=&quot;execution efficiency permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Execution Efficiency&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Parallel Execution&lt;/strong&gt;: Uses multiple workers to process tables concurrently. Usually 10-20 workers are used.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bulk Insert&lt;/strong&gt;: Uses &lt;code class=&quot;language-text&quot;&gt;SqlBulkCopy&lt;/code&gt; for high-throughput data insertion.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With all these changes, the time for the first run (e.g. limit 100k records) may be around 2 hours, and for subsequent runs it may start from 30+ minutes.&lt;/p&gt;
&lt;h2 id=&quot;future-usage-scenarios&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#future-usage-scenarios&quot; aria-label=&quot;future usage scenarios permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Future Usage Scenarios&lt;/h2&gt;
&lt;p&gt;With the &lt;a href=&quot;https://www.linkedin.com/posts/laneswenka_onedynamicsoneplatform-odop-ppac-ugcPost-7405271671118602240-Xm_4/&quot;&gt;recent announcement from Microsoft&lt;/a&gt; stating there will be &quot;No New Cloud Implementation Projects in Dynamics Lifecycle Services&quot; (LCS), the landscape for Dynamics 365 development is  evolving. As the ecosystem moves towards the Power Platform Admin Center (PPAC), utilities like &lt;strong&gt;D365FO-DBSync&lt;/strong&gt; may become helpful.&lt;/p&gt;
&lt;p&gt;One of the limitations with the new PPAC experience is the inability to download a database backup directly(see &lt;a href=&quot;https://learn.microsoft.com/en-us/power-platform/admin/unified-experience/finance-operations-apps-overview#terminology-differences-between-lifecycle-services-and-the-power-platform-admin-center&quot;&gt;Terminology differences between Lifecycle Services and the Power Platform admin center&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/acf04a70b0af8448d8ac1780d936270c/fd28b/BackupCloudOnly.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 63.42857142857142%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAAA7DAAAOwwHHb6hkAAACF0lEQVR42p1T2Y7iQAzM///XjrQjLRBuCAwwO0AOyH1ftWVnM0L7uC1ZbXfc1a6yYzj2HfP5AqvVCqvlEj/f37FYLPH29gPT6RSr9RobmmmamEx+MdfE8XjEbGYyb4El7xRFgXEZjuNgs9ny0gaHg4Ulk9YCwjPLsvSR8/mkYJPpDLu9xbwDAWfY7/f0jzDpe95jACzLEo+HR3uoRVGEIAjUwjDUb74fIKL/9H3NkfPn8zkYYwHL83wAFMd1XR66ukuSbdvIsxxt26Kua1RVjbqp1RdrmkZNzmRv2wZ93w+A/V/u48H/rLKslFEcxzDqqlIaTdNq2eL7pCaVZFnKyj2EQajVhmGgksjjr9bwm0gnd4w8y9i5OZI0VaAF/cvlookOqUt8vV61kphgIyA5qf3LzKjrCnESa5ASNOMD45KKkyRRv2MVKfOEWsFqRpn6vkPXdei7AdwYqGXfAFJlGIWaJHFFSWS1jO+ug9+3G24cNZv+lQzEv9qO7qVQFm2kU4IuIKKHnI2xmuhEwe3tFvfdFq61h8MZtHc7JF9fKAmWUZby6cOQCqI4+q4w4IyNNANWK/rZbExxOsHj4N857FcCDfsWN/pn/mnOxweq83mgLABSkWgjOiasJuMcRqQujfHY+YKgAQFdAqSfn2g5s+XdRsXvBWVoGHecYWMcXgEcfTHxBdxnkjRCYtGx5t69dLZ/2aUpfwAHmd4gb660MgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Backup capability in LCS vs PPAC&quot;
        title=&quot;&quot;
        src=&quot;/static/acf04a70b0af8448d8ac1780d936270c/8c557/BackupCloudOnly.png&quot;
        srcset=&quot;/static/acf04a70b0af8448d8ac1780d936270c/4edbd/BackupCloudOnly.png 175w,
/static/acf04a70b0af8448d8ac1780d936270c/13ae7/BackupCloudOnly.png 350w,
/static/acf04a70b0af8448d8ac1780d936270c/8c557/BackupCloudOnly.png 700w,
/static/acf04a70b0af8448d8ac1780d936270c/fd28b/BackupCloudOnly.png 811w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;This limitation complicates the process for developers who rely on restoring UAT data to their local environments for debugging and development.&lt;/p&gt;
&lt;p&gt;Furthermore, adoption of the Unified Developer Experience (UDE) remains low. A &lt;a href=&quot;https://www.linkedin.com/feed/update/urn:li:activity:7405495534313992193/&quot;&gt;recent poll&lt;/a&gt; indicates that despite being introduced over two years ago, only about 13% of developers have switched to UDE.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 533px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/b4db909e7e53e4394bba1aeb1433e9e3/a1aa0/PollDevUsage.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 58.285714285714285%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAA7DAAAOwwHHb6hkAAABhUlEQVR42pVT2W6DMBDk//8rVR/70CpNlUQhUA4TCKdtsGG6u2kjteKhWWm0Zm3PHh4Cay0Yxhj0fQ+tNYZhuK+naZI9jrHnGO/xnZ8Ye+cclmVBcDwesd/vkaYpoihCkiTio+iMLE3Qti2UUjif6TvL5FwYhsjzHHEcS4zPcwK2gAmYlLOweX/L5OYbZlr/16RCbUdoQ+Vrg7brCdyuRlZbfF5H1NoJ6eQXeErAl/5inuf7Ong5lnjeJoKnt1iweY2wIb9NDfbljJ1y2GYTVOe/K/ldGc+5LEshDsJEYXc4I85KVJ3Bpe5RtRpVP6I1M/pxEXR2wejW2/fey6yFkIf/sXtHfb3e5/Co8Qtf6b4QHuhBTqcTqqpCURTyyrx+xLhlviMzZII8V2iaRsAbrDOpdmVea8aV3VtmrV0KRdUp0RuDiR9pn8/VdX0jrAaPnF6vN/xHaFhSfjdYJCSZop2QNROcXx7Q4ejQaCIbJ4ykdv61DGmzMx6DdeQd6W9e1d+aFr8AdRSjeQWV9HIAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Developer Usage Poll&quot;
        title=&quot;&quot;
        src=&quot;/static/b4db909e7e53e4394bba1aeb1433e9e3/a1aa0/PollDevUsage.png&quot;
        srcset=&quot;/static/b4db909e7e53e4394bba1aeb1433e9e3/4edbd/PollDevUsage.png 175w,
/static/b4db909e7e53e4394bba1aeb1433e9e3/13ae7/PollDevUsage.png 350w,
/static/b4db909e7e53e4394bba1aeb1433e9e3/a1aa0/PollDevUsage.png 533w&quot;
        sizes=&quot;(max-width: 533px) 100vw, 533px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;As a result, it is likely that many developers will migrate to a hybrid workflow combining UDE for some tasks and local VHDs for others. In this mixed environment, &lt;strong&gt;D365FO-DBSync&lt;/strong&gt; can assist with data transfer, helping developers work with relevant datasets.&lt;/p&gt;
&lt;h2 id=&quot;how-this-tool-was-built&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#how-this-tool-was-built&quot; aria-label=&quot;how this tool was built permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;How This Tool Was Built&lt;/h2&gt;
&lt;p&gt;It is an interesting time for software development. This tool contains around 3000 lines of C# code, but, I didn&apos;t write a single line manually. All of it was done using &lt;strong&gt;Claude Code&lt;/strong&gt;, leveraging &lt;strong&gt;Claude 4.5 Sonnet&lt;/strong&gt; for the actual coding and &lt;strong&gt;Claude 4.5 Opus&lt;/strong&gt; for the planning phase.&lt;/p&gt;
&lt;p&gt;In planning mode, I would provide requirements to Opus and ask it to generate questions to create a detailed specification. For a single feature, it might ask 50+ questions. Once the specification was ready, I would provide it to Claude Code for implementation.&lt;/p&gt;
&lt;p&gt;The only downside is that the standard $20 Claude subscription is not enough; the session limits are reached quite quickly. You often need to switch to API mode, which can consume $5-10 per few requests, or wait for the limits to reset.&lt;/p&gt;
&lt;h2 id=&quot;summary&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#summary&quot; aria-label=&quot;summary permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Summary&lt;/h2&gt;
&lt;p&gt;This tool helps reduce the friction of getting fresh data into your local VM.&lt;/p&gt;
&lt;p&gt;You can download the &lt;strong&gt;D365FO-DBSync&lt;/strong&gt; from the GitHub repository:&lt;br&gt;
&lt;a href=&quot;https://github.com/TrudAX/D365FO-DB-Sync&quot;&gt;https://github.com/TrudAX/D365FO-DBSync&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;It is currently a working prototype, and it definitely requires input from different projects to become mature, so feel free to share your ideas on what can be improved.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[D365FO Integration: Import Purchase Orders from PDF using Gemini AI]]></title><description><![CDATA[Learn how to use AI to import purchase orders into Dynamics 365 Finance from complex PDF files. This post covers integration design, sample prompts, and practical code examples.]]></description><link>https://denistrunin.com/integration-importpurchpdf/</link><guid isPermaLink="false">https://denistrunin.com/integration-importpurchpdf/</guid><pubDate>Wed, 10 Sep 2025 22:12:03 GMT</pubDate><content:encoded>&lt;p&gt;In this blog post, I&apos;ll guide you through the process of using AI to import purchase orders into Dynamics 365 Finance and Operations (D365FO) from complex PDF files.&lt;/p&gt;
&lt;p&gt;Although the example provided here is simplified to illustrate core integration concepts, the approach and code samples are based on real-world scenarios. This makes them highly adaptable for similar integration tasks you might encounter. We&apos;ll utilize the free and open-source External Integration &lt;a href=&quot;https://github.com/TrudAX/XppTools?tab=readme-ov-file#devexternalintegration-submodel&quot;&gt;Framework&lt;/a&gt;, which provides reusable components explicitly designed for building robust integrations in X++.&lt;/p&gt;
&lt;h2 id=&quot;integration-scenario-overview&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#integration-scenario-overview&quot; aria-label=&quot;integration scenario overview permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Integration Scenario Overview&lt;/h2&gt;
&lt;p&gt;Let&apos;s start by defining the integration scenario:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Goal: The customer receives complex invoice documents from external vendors as PDF files. We want to create Purchase orders in D365FO based on these documents.&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;current-solutions-on-the-market&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#current-solutions-on-the-market&quot; aria-label=&quot;current solutions on the market permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Current solutions on the market&lt;/h2&gt;
&lt;p&gt;Before approaching this task, I researched the available options.&lt;/p&gt;
&lt;h3 id=&quot;pdf-to-excel-converters&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#pdf-to-excel-converters&quot; aria-label=&quot;pdf to excel converters permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;PDF to Excel converters&lt;/h3&gt;
&lt;p&gt;There are numerous online services, such as &lt;a href=&quot;https://studio.convertapi.com/pdf-to-excel&quot;&gt;https://studio.convertapi.com/pdf-to-excel&lt;/a&gt; and &lt;a href=&quot;https://www.ilovepdf.com/pdf_to_excel&quot;&gt;https://www.ilovepdf.com/pdf_to_excel&lt;/a&gt;, that claim to extract tables from invoice documents. The idea was that the user converts the PDF to an Excel template and then uploads it to D365FO.&lt;/p&gt;
&lt;p&gt;However, after initial testing, they generated many errors in the line sections—for example, empty cells when a description spans two lines, or merged cells where columns should be separate, etc.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 426px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/d5c6c76da17c8560fae337cd2816086c/531e1/PFDConversionErrors.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 16%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAADCAYAAACTWi8uAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAA3klEQVR42i2PQU/CQBSEe+KP9OIf5YRnEiNcTDxzQw5q0oIioYAB1lIS6G5TWtZsquk7lMat4zs4yZfMYWaScSAlyuUCqeehFgL1ZouT+IBMEshYIsty2zS/QIPrc2k61l4wffHsPJjheNhDHiJEYYiYs+EughM9PdJsMKD34QMdx2MSoxGtfZ8WqxUF84CMKb7B+qnrdgV0LirG203XvvZvMe33sLy/w8R/hkpS5HkORwPunlEMF1z977XWrmKqqnJ574ppGSq6DZv0M7PrnUBRfuFkztiEW36j+E2GP3/5zKyjcDvmAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;PDF errors&quot;
        title=&quot;&quot;
        src=&quot;/static/d5c6c76da17c8560fae337cd2816086c/531e1/PFDConversionErrors.png&quot;
        srcset=&quot;/static/d5c6c76da17c8560fae337cd2816086c/4edbd/PFDConversionErrors.png 175w,
/static/d5c6c76da17c8560fae337cd2816086c/13ae7/PFDConversionErrors.png 350w,
/static/d5c6c76da17c8560fae337cd2816086c/531e1/PFDConversionErrors.png 426w&quot;
        sizes=&quot;(max-width: 426px) 100vw, 426px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h3 id=&quot;invoice-capture-solution&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#invoice-capture-solution&quot; aria-label=&quot;invoice capture solution permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Invoice capture solution&lt;/h3&gt;
&lt;p&gt;The invoice &lt;a href=&quot;https://learn.microsoft.com/en-us/dynamics365/finance/accounts-payable/invoice-capture-overview&quot;&gt;capture solution&lt;/a&gt; is a standard option for Microsoft Dynamics 365 for Finance and Operations (D365FO). It is based on the Power Platform and utilises Optical Character Recognition (OCR) to parse invoices.&lt;/p&gt;
&lt;p&gt;I researched it and found:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The installation document is 65 &lt;a href=&quot;https://github.com/TrudAX/denistrunin-blog/blob/master/src/posts/integration-importpurchpdf/Assets/Implementation_Guide_Invoice_Capture_GA_1.9.1.x.pdf&quot;&gt;pages&lt;/a&gt; long, and you must be an administrator of “everything” just to try it.&lt;/li&gt;
&lt;li&gt;Because it’s based on the Power Platform, extensibility is limited.&lt;/li&gt;
&lt;li&gt;The Yammer group is full of questions (for example, why something is incorrectly parsed on page 2) without clear responses.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Because invoice capture relies on Azure services, I tried Microsoft AI Foundry &lt;a href=&quot;https://azure.microsoft.com/en-us/products/ai-services/ai-document-intelligence/#Pricing-5&quot;&gt;Document Intelligence&lt;/a&gt; directly in Azure, and result&apos;s were not perfect even on the first sample (see below)&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 271px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/bc2e7ebf48d1792e13edf0adee5ab83e/5fce1/MicrosoftAIErrors.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 99.42857142857142%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAA7EAAAOxAGVKw4bAAADr0lEQVR42mVUy3ITVxCdv8k+VaycNez4AorfyJ4FValKJRuSPQuWpMzDFQLYYMC2ZOtlS6NHZD2x0GjerzujkR8n3T0aBZLFrZFu3z739OlzW4uiCFEUwjAMWJaFJEmglEIcx+BYGASwTAu+78NxHDi2I79jFSMMQznneR7tBXJeY4D5lwv88fQpGmdNZFkmh3gxsE2XvH3zGnu7eygfl7Gzs4PnL19iMv0MxZfHET7sv8OLP18RcACtuCViADrAtxTsAmLHoIr+8+/NfpizKXI5Zlm2/NY8z6dgjEQlSJMU6XIpZfMhLi0iBipRWGZLpGkqixMZjONBEFJOitUqk8s1Drqkzd+9LjqdNrqdDsbjiYAKG0oaDM5Rq9fQplhb17EwTQFmUC65TXnVWhXT6TQH9H0P49EIut5Cu61jPJluADlpMOhTQg06xXS9+R/AGJ1uF43TU2msJh2jTQZYpkXJalPSJrZcl0zfQkufussu4P2MJGFp/m2KWCQU7VjTgp0kUgXcCNaLAbiBMccZ/PJS9vy15mvbzLD79g1OKhWcVCsSLLzoeS5qtQoODg5QKpXIWmfUPIpdXUHtf0D61yscNRqUv4t+vw8tZxJgsVjAtm3Y1CCx0Nq4/HVdBybpZtkWXLpAkSNCYpbeuwfj4UOYxNSmfDE2u5yZFBolSbrxFse4/GW6lDj7NCWwmL4+sQ3u3MF5tYrs5ppy8yZKlz3XxWg8krbPZjNhyyXn5vYxHAwwHA5Jmi8YLQwYjx/j+u5d2PfvwyG5JuQKjjN70dAw5iiXS6iT106p/ecEwGwZ1HVs0e/w6BB6q4kyWav76BFw6xa827dx8f4dmr0eSocHMMxFbhtOZOD8DUffvASOXa2WWKUKKQ2RDID9bBv21hYOnzzBnM6w3RKuiHI0n0piC8ibTfIyC8uwjq4foj+zMZiTLHMHQ1eh/ekI1e1tLGIiIm9fbR6Clk8Uk6xRRbOlS1MYmA9dEavKxMXW7y388FsT3/+q47ufzvDjiwFurjO6NJKKGo06jmkSmTSZtGKesfCfL2Y051TeENpPVYShGeCX91NZP+9N8eD1BM9PDVym9GSDUADn83neFNf7v22KV5LbxpfHf5MpWgluVglAK0vIVl9Nm+Jpyvgq9LLJtGxelywks08VeoZkaJvKyZdDLPw1SG58JU/TpA4zOdFwQbb5+HEfVTJpvU5a0ogq5h7r+4lsc3xyjF6vIxaakF95sjNL7m6lciKTvKm38A/NNcbogDybmAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;OCR errors&quot;
        title=&quot;&quot;
        src=&quot;/static/bc2e7ebf48d1792e13edf0adee5ab83e/5fce1/MicrosoftAIErrors.png&quot;
        srcset=&quot;/static/bc2e7ebf48d1792e13edf0adee5ab83e/4edbd/MicrosoftAIErrors.png 175w,
/static/bc2e7ebf48d1792e13edf0adee5ab83e/5fce1/MicrosoftAIErrors.png 271w&quot;
        sizes=&quot;(max-width: 271px) 100vw, 271px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The advantage of OCR is that it provides a direct link between the image and the parsed data, and it is quite fast. However, after the initial research, I decided not to pursue this further.&lt;/p&gt;
&lt;h3 id=&quot;use-ai-models&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#use-ai-models&quot; aria-label=&quot;use ai models permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Use AI models&lt;/h3&gt;
&lt;p&gt;We currently live in an AI world, and many modern models support file inputs. The idea was to use an AI model to read the document and output it as a JSON structure. Then, use the External Integration Framework (which can work with &lt;a href=&quot;https://denistrunin.com/xpptools-integservbussalesjson/&quot;&gt;JSON data&lt;/a&gt;) to create the required D365FO documents.&lt;/p&gt;
&lt;p&gt;I tried several models and got the best results with Gemini 2.5 &lt;a href=&quot;https://deepmind.google/models/gemini/flash/&quot;&gt;Flash&lt;/a&gt;. It’s among the fastest on the market, and performance is essential. For example, an invoice with ~200 lines (4–5 pages) takes about 2 minutes to process.&lt;/p&gt;
&lt;p&gt;After some quick prototyping with Claude Code, I extended the External Integration Framework with a “Get data from AI” option. Below are the setup and usage instructions.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note: Microsoft recently released a Power App &lt;a href=&quot;https://github.com/microsoft/Dynamics-365-FastTrack-Implementation-Assets/tree/master/AI%20ERP%20Agents/Sales%20Order%20Agent#configuration-wizard&quot;&gt;Sales Order Agent&lt;/a&gt; that implements a similar concept of processing documents by defining custom prompts and then utilising virtual data entities. However, the customisation option is unclear(probably not even possible)&lt;/em&gt;.&lt;/p&gt;
&lt;h2 id=&quot;external-integration-ai-solution-setup&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#external-integration-ai-solution-setup&quot; aria-label=&quot;external integration ai solution setup permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;External integration AI solution setup&lt;/h2&gt;
&lt;p&gt;In this section, we&apos;ll discuss how to set up AI for PDF import.&lt;/p&gt;
&lt;h3 id=&quot;ai-providers&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#ai-providers&quot; aria-label=&quot;ai providers permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;AI Providers&lt;/h3&gt;
&lt;p&gt;You can have multiple AI providers. Define a provider using the &lt;strong&gt;AI Providers&lt;/strong&gt; form. A provider is a class that extends a &lt;a href=&quot;https://github.com/TrudAX/XppTools/blob/master/DEVTutorial/DEVExternalIntegration/AxClass/DEVIntegAIProviderBase.xml&quot;&gt;DEVIntegAIProviderBase&lt;/a&gt; and defines the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A set of parameters with default values that the user may override(in this case it is a model)&lt;/li&gt;
&lt;li&gt;A free‑text description of how to set up the provider&lt;/li&gt;
&lt;li&gt;A connection reference that defines the endpoint and API key&lt;/li&gt;
&lt;li&gt;A method that implements the call to the AI provider&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/dcd381b0c3df19bceab1cbb57a6b3282/33e10/AIProviderSetup.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 67.42857142857143%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABoUlEQVR42p2T246bMBCGef8n6UNUe9W7qjfVrrTbbkhIQgLGBDAHH/HfsTdBUbVstbX0yWMz/PYcnDz+OuHL1wysOOJwyLHLDsh2W2zTFJxf0DQNas5XqaoKjFU4HEu8pAWS8jKBdwa9BHp1ZZR4/f2C3TZFxRj87DA7G3HWwBq9rG/4K8nD9xzffqT4uRF4Pho87Q1OrEe2fcUpz6Mop1soOUUuNV/WWsll/0YiBjK0hTZuQSmFoReQ44hp7CFEhzHY04SK1yhKhmHoIac3UaPVQmKMwd/DUEjTOMTZOUdYWEthzzPEINGJIR6qSMzS/zENV1YEKeyCo2k7WvlIEA038N5fvWj2M/kqOsgtfu8Kam2QnQU2ew7WWtS9R3bqqIpn7PIG+3OLIxtQdRb7QqC4aLJnwq3cUGuMkvJqPZS5Z8akLOEg9Rz3KOVQd36rIYd8/c9YLcpNMOTsM6yGXNd1bJWQ8FCQf/FhlTVVMwiGvgv2W4soSCljq9zm+31r7XrIobe6to2iAU5vNsDoGYa3W1Jjl0UR7fA9zJqiCoJ/AOW38XqvD8ygAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;AIProvider setup&quot;
        title=&quot;&quot;
        src=&quot;/static/dcd381b0c3df19bceab1cbb57a6b3282/8c557/AIProviderSetup.png&quot;
        srcset=&quot;/static/dcd381b0c3df19bceab1cbb57a6b3282/4edbd/AIProviderSetup.png 175w,
/static/dcd381b0c3df19bceab1cbb57a6b3282/13ae7/AIProviderSetup.png 350w,
/static/dcd381b0c3df19bceab1cbb57a6b3282/8c557/AIProviderSetup.png 700w,
/static/dcd381b0c3df19bceab1cbb57a6b3282/33e10/AIProviderSetup.png 844w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;In the current implementation, we can use only one &lt;a href=&quot;https://github.com/TrudAX/XppTools/blob/master/DEVTutorial/DEVExternalIntegration/AxClass/DEVIntegAIProviderGemini.xml&quot;&gt;Gemini&lt;/a&gt; class, but you can extend it later.&lt;/p&gt;
&lt;h3 id=&quot;connection-type&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#connection-type&quot; aria-label=&quot;connection type permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Connection type&lt;/h3&gt;
&lt;p&gt;To store an API key, we need to create a connection type. The Google Gemini endpoint is: &lt;a href=&quot;https://generativelanguage.googleapis.com/v1beta/models/&quot;&gt;https://generativelanguage.googleapis.com/v1beta/models/&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To obtain the key, sign in to &lt;a href=&quot;https://aistudio.google.com&quot;&gt;https://aistudio.google.com&lt;/a&gt; and click the &quot;&lt;strong&gt;Get API Key&lt;/strong&gt;&quot;. The price is a fraction of a cent per 1 page.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/a04a05bc4497c6ee5f0ffccf5a72341b/98314/GoogleAIStudio.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 68%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACYElEQVR42m1TTW/aUBD0L2grpYA/sY0xYMAYbAOBGA7cUBGce6iUQw899R9U6r9IQgWqoirqIVRpmvTvTXeXGCVNDqPnt289np15Vm5ufuP6eie4vf2D+/u/uLu7x9XVT2w2W5ydnePiYo31+ptgu/0uuLz8gd3u1zMow+EQjCiKkCQJNE1FpeKh0WjIPo5jVKtVqKp6QKlUEhQKhWdQPM+DZVkwDANWuQxd12EweE91Btc0TRMwUf780l4UsgLXdWU1TVNU8GGu6PELjuOgWCweiGzbfvKO0mw2ZbwyqeNDVvaY7H8sFgusViucnp5iPp8jyzKpLZdLzGYzKKyMx2ayx6Pxnut8XqlUDqjVami320jTFEEQSA+vrVZLVsX3fWlkhbk6Rr1eR78/QK8XUzgpEfQlpE6nIxPxORMEPCGtXBNCVsC+5B6wSgGRq6r2xD/9IayXkE+n8JeYlE1mcw1Dl+d+L8JkmNKZA+9h3Dz1HNyvG/SOacF96FFC8iMPhb9kmgZevTnC18/vsfnyAcdEmk2mmE6nNH5C/oWCMOzAp1vxVitDK7fIniHG4/E+5dzQMt9HHo1GjTsBjpOI6s09qK9eb0gI1apPZL5YZeh0d9V9cKxSaQRsKjU3uyjZFRzRn/K6cITkZI5htqAQQvr6PpDBYCCh8H3ltNkOpxrAj0aHPmU0GmFEUjNK9FPUxYoal66Nd2mGdjJBRASccsy/ISGinjAM0aG15jmwoxm82UekcRfjkwmUbrdL/2sPrmOjRSb75KOvG3ANTQJi49nX3F/eW5Z5CMUS6JIB1/4BmLWvJO/A0PQAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;AI Studio&quot;
        title=&quot;&quot;
        src=&quot;/static/a04a05bc4497c6ee5f0ffccf5a72341b/8c557/GoogleAIStudio.png&quot;
        srcset=&quot;/static/a04a05bc4497c6ee5f0ffccf5a72341b/4edbd/GoogleAIStudio.png 175w,
/static/a04a05bc4497c6ee5f0ffccf5a72341b/13ae7/GoogleAIStudio.png 350w,
/static/a04a05bc4497c6ee5f0ffccf5a72341b/8c557/GoogleAIStudio.png 700w,
/static/a04a05bc4497c6ee5f0ffccf5a72341b/98314/GoogleAIStudio.png 817w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Enter these values in the &lt;strong&gt;Connections&lt;/strong&gt; form.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/ce0a8f3c9f555a7c054d6a5fc84fd037/a0209/ConnectionType.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 63.42857142857142%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB1UlEQVR42pWSy27bMBBF9Vd2gNZFAacpHPsH8xPZdZV1u+4jaVo0dezoYUkURb1MUq/bIRUVXcSNI+GCpDQ8c2cwztv5GZbLJRbvz3D67hTz+RzL8wVWqxXezGaYTCY4OZliajR9WiZm9voVzhcLOBcfGD7/ZCjzDAkXCKMUcRxhFwQQIoNSGlpr1LVG27So9XAeZb5b0V4pBScvSnuotbJq6KeRVpIuSCQsxma9hvuwRZIwG9M2Nbq2sTL7Ueae43ohIiZQyQZZXiHYxfCCEFwUkLoBI7c/br/j992dhe7LAvuqhEg5MpFC7StoubcGTDLn5lcIj9XYpS183uB2TUCm4fEWkRiAD9sN8lygKDKCcEThDr7nIcsESkpQUQKzmtIdJSX6vsf4mEzj2ZRU5rktlSUxQXP09HZ9N8SQervv0HWDHPznMVhBkDiKKLi3kOf0NPDRYUt9E9ffcO+5CHwfoSnV96j08qAJ5yCMcySXl+A312CZ6V8OKSvbL0VtOR74l9ujJRVVZUuOSGma0igpO3//9v0o4NjDoiyx3WyQkuMBpuwAv7jknpzJqyuknz4iSBJUBDYwaWaO1uMdPgaqkIb76xdwcpfQEHuua0sd23HI4R+G4McuogvrmwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Connection types&quot;
        title=&quot;&quot;
        src=&quot;/static/ce0a8f3c9f555a7c054d6a5fc84fd037/8c557/ConnectionType.png&quot;
        srcset=&quot;/static/ce0a8f3c9f555a7c054d6a5fc84fd037/4edbd/ConnectionType.png 175w,
/static/ce0a8f3c9f555a7c054d6a5fc84fd037/13ae7/ConnectionType.png 350w,
/static/ce0a8f3c9f555a7c054d6a5fc84fd037/8c557/ConnectionType.png 700w,
/static/ce0a8f3c9f555a7c054d6a5fc84fd037/a0209/ConnectionType.png 725w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Also, we need to create a &lt;strong&gt;Manual&lt;/strong&gt; connection for the inbound message.&lt;/p&gt;
&lt;h3 id=&quot;ai-prompt-definition&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#ai-prompt-definition&quot; aria-label=&quot;ai prompt definition permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;AI Prompt Definition&lt;/h3&gt;
&lt;p&gt;After setting up the connection, define a prompt. The &lt;strong&gt;AI Prompt Definition&lt;/strong&gt; form lets you define and validate the prompt.&lt;/p&gt;
&lt;p&gt;First, validate that the connection works by sending a simple “Hi” prompt. The &lt;strong&gt;Call API&lt;/strong&gt; button runs the prompt, displays the response, and shows related statistics.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/70d163d22036df6ca8ad01a7830890a0/7a3d6/AIPromptDefinition.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 73.14285714285714%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABsElEQVR42q1T207jMBTMP/PK24oqZbUCBP/FGyztcusF0bS5OL7ESZzMjt0bouwDqx5pdOJjZ3xsz0Qnpz9x+uMCVxe/EA/PMYyHuLq8xPX1DeI4DhgMBhuc/eN7jygRDoXBLtq2RSkKNE0D5xw64jsR3f5+x3gqMJpqjGYGr28ZHv88YDwe4f7+jt8j5HmKPMuwWCSQpcBqmSBZvEMUObSSMFrtEI2f5pi8rSB0SzgIqZFlK9iqQlmWqIxh1w20NsiEQW1rSMl6ZWBtFeaca3eIrDVwLAJdgF+Q5gJSc7HrA5p2nTsuaUINAc1m7iMif2cfo25aSKXZkSa5Q9/jWzgkrFvu3uF/4/iE7uiEn3Rmj03oBW2qmi/m+EDENhN2g/W4W4/rfc3nA0Ivm6xQ0NbBEMp04aeOmvGv6LP/x3X7U/haQ3X4/DUhXSGEoAVLGApbSkl3LOmMgmK2QdTz6RRpmhJrE1REEPYhod+J+uNuWx8XeY7J5BXz2QxFIaCUwgNt+fz0yM1T2k+F7r68Q//q/Way92dkLJMELy/PWLLLgl3WdU1/56FjRQP48ZbnL96qfNplb1b9AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;AI Prompt Definition&quot;
        title=&quot;&quot;
        src=&quot;/static/70d163d22036df6ca8ad01a7830890a0/8c557/AIPromptDefinition.png&quot;
        srcset=&quot;/static/70d163d22036df6ca8ad01a7830890a0/4edbd/AIPromptDefinition.png 175w,
/static/70d163d22036df6ca8ad01a7830890a0/13ae7/AIPromptDefinition.png 350w,
/static/70d163d22036df6ca8ad01a7830890a0/8c557/AIPromptDefinition.png 700w,
/static/70d163d22036df6ca8ad01a7830890a0/7a3d6/AIPromptDefinition.png 990w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Then define a prompt for invoice parsing and test it on sample invoices.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/1051eb226a615540df0c4af3305493f0/0f67e/AIPromptDefinition2.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 84%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAARCAYAAADdRIy+AAAACXBIWXMAAA7EAAAOxAGVKw4bAAACYUlEQVR42pVU2Y7TQBDMd/LGA2ITRCJ24WX5R1AEQgi02Zye+L6v8VFbPU6irNZIi6VKj+1MTVd3tSdv3s7x7sNnfLn7hPl8gfnHOe5ub/H1/h6LxRyz6RSz2RQ3N+9fhcnqWGNllegajaIkigqubcP3AjRaG7Rti9dekyJP0Hea4Ka+RdPUsPY7rB9XWD084HH1APuoUBY5sjRBnqWXdZbGKPIMVVlcMFn+Vvi78XEMGwM30jiQ0HNduB7hOiTgnwll+3C8GGWew3FshGFgDqirkkpqg8nyj0vCADtHY2trKL9GEkco0pRZd0Zu0zRoue5OkGcS+76/POu64dlEfq4veRFFIULPQxpFyJmNZh3rWlBDC/SwPqMsS1RVZdYjhB0CSt2xdrvtFvv9njW0iSNCHpRnGeIoRhzHSJKYh1MNy1GwfjVJXxC2zFAyszYbKEvhyIYoyxoikbAZWjcmS3GAxGddHpMsNVwzwy0z3G432O2GTOVeMtUnIkPanOXrcclt25iuusoaMlRHE5VShkxiEPiUHBm5YRiaKHUvaKdRwoxWsGlu2axIfGB21uFgCKV2ZyIhjaPoRDg08B+SY5OlFFk6WLLgEuX+Wu6A+lLPZkyyTEyalyiqFlXdIStaszY+pO/6Kz/2XT/sET/2gz9fEvKF4zhswgG+79MaKYk1ApkKShK/yUaRKrbyaDFPpokqxD6jkkVCy+mQCZEDJAPvPIaULrZxOXrL79/w6+cP2KxzzpkezbDjw7GvizRhs1kbQpEnUZqSJon5UFSc5/8ilO6KDxMSyHvJ+nmpeqPoCejKBDxyOw0cAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;AI Prompt for Invoice&quot;
        title=&quot;&quot;
        src=&quot;/static/1051eb226a615540df0c4af3305493f0/8c557/AIPromptDefinition2.png&quot;
        srcset=&quot;/static/1051eb226a615540df0c4af3305493f0/4edbd/AIPromptDefinition2.png 175w,
/static/1051eb226a615540df0c4af3305493f0/13ae7/AIPromptDefinition2.png 350w,
/static/1051eb226a615540df0c4af3305493f0/8c557/AIPromptDefinition2.png 700w,
/static/1051eb226a615540df0c4af3305493f0/0f67e/AIPromptDefinition2.png 921w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;A sample prompt used here:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;You are an expert at extracting structured data from multi-page PDF invoices. Your task is to process the entire document and produce a single&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; valid JSON object.
The JSON object must have two top-level keys&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; HEADER and LINES.
    HEADER&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; A single JSON object containing summary information from the invoice.
    LINES&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; A JSON array of objects&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; where each object represents a single purchased item.
Extraction Rules for HEADER&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
    VendorName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; This is printed on the first page header before or after the &lt;span class=&quot;token string&quot;&gt;&quot;Tax Invoice&quot;&lt;/span&gt; label after &lt;span class=&quot;token string&quot;&gt;&quot;Vendor:&quot;&lt;/span&gt; label. 
    ReceiptDate&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Find the &lt;span class=&quot;token string&quot;&gt;&quot;Delivery date&quot;&lt;/span&gt; date on the first page. Convert this to a &lt;span class=&quot;token string&quot;&gt;&quot;yyyy-MM-DD&quot;&lt;/span&gt; format.
    PurchPoolId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Extract the value located directly below the &lt;span class=&quot;token string&quot;&gt;&quot;Delivery date&quot;&lt;/span&gt; date on the first page. 
    ChargeValue&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; At the end of the document&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; there is a line that states &lt;span class=&quot;token string&quot;&gt;&quot;Handling fee&quot;&lt;/span&gt;. Get the value from it&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; the data type should be real&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; if not found &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;.
    InvoiceTotalAmount&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; On the final page&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; find the line &lt;span class=&quot;token string&quot;&gt;&quot;Grand Total&quot;&lt;/span&gt;. Extract the final numeric total. The data type must be a number.
    InvoiceTotalQty&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; On the final page&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; find the line &lt;span class=&quot;token string&quot;&gt;&quot;Total Quantity&quot;&lt;/span&gt;. The data type must be a number.

Extraction Rules for LINES&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
Each object in the LINES array represents a single invoice item and must contain the following fields. IMPORTANT&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Do not include summary or Total by lines as items in this array.
    InvoiceItem&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Take from the &lt;span class=&quot;token string&quot;&gt;&quot;Description&quot;&lt;/span&gt; column.
    ItemId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Check the &lt;span class=&quot;token string&quot;&gt;&quot;Description&quot;&lt;/span&gt; column. If this is &lt;span class=&quot;token number&quot;&gt;37&lt;/span&gt;&apos; TV&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; then use &lt;span class=&quot;token string&quot;&gt;&quot;T0004&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; if &lt;span class=&quot;token number&quot;&gt;52&lt;/span&gt;&apos;TV&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; use &lt;span class=&quot;token string&quot;&gt;&quot;T0005&quot;&lt;/span&gt;
    Quantity&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Take the numeric value from the &lt;span class=&quot;token string&quot;&gt;&quot;Qty&quot;&lt;/span&gt; column.
    Price&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Take the numeric value from the &lt;span class=&quot;token string&quot;&gt;&quot;Unit Price&quot;&lt;/span&gt; column.
    GST&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Take the numeric value from the &lt;span class=&quot;token string&quot;&gt;&quot;Tax Amount&quot;&lt;/span&gt; column.
    TotalValue&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Take the numeric value from the &lt;span class=&quot;token string&quot;&gt;&quot;Amount&quot;&lt;/span&gt; column.
    Color&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; This value is determined by grouping. The invoice items are separated into sections by summary lines like &lt;span class=&quot;token string&quot;&gt;&quot;Total by color Black&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Total by color Silver&quot;&lt;/span&gt;.
        First&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; identify these summary lines throughout the document.
        All regular item lines that appear before a specific summary line (e.g.&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Total by color Black&quot;&lt;/span&gt;) belong to that group.
        The Color for all items in that group should be the code from the description (e.g.&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; for &lt;span class=&quot;token string&quot;&gt;&quot;Total by color Black&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; the Color is &lt;span class=&quot;token string&quot;&gt;&quot;Black&quot;&lt;/span&gt;; for &lt;span class=&quot;token string&quot;&gt;&quot;Total by color Silver&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; the Color is &lt;span class=&quot;token string&quot;&gt;&quot;Silver&quot;&lt;/span&gt;). Apply this logic consistently across all pages.

Output ONLY the raw JSON. DO NOT INCLUDE any other text&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; explanations&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; or markdown formatting.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If you notice that the abilities are quite powerful, we can utilise AI to implement simple mappings. For example, to convert from &lt;strong&gt;InvoiceItem&lt;/strong&gt; to &lt;strong&gt;ItemId&lt;/strong&gt;, I defined a couple of rules. To derive the &lt;strong&gt;Color&lt;/strong&gt; for each line, we used quite a complex logic based on the “Total by color” group.&lt;/p&gt;
&lt;p&gt;However, if the mapping requires numeric comparisons (e.g., greater/less), Flash 2.5 can struggle; in that case, include all the necessary data in the output and implement the logic in X++.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 506px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/bef16060b018e59dff5e5697df3671b9/29f4e/SampleInvoice1.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 91.42857142857143%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAYAAABb0P4QAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABw0lEQVR42qVU2XKDMAzM/39ip9NpGzCHD2xuMKBKIiYm7UPbaIZAjLxa7cpcAGOcPGjbgaoaGOcFnokL/ThXw8vrB7y9p5CkGdR18xxg13YgyxK00qDwKksJztb/B+z7AYZxhGVZYF3X4x7Htm37PXoO6/H/CzwkPBt7y10HWZZzuzG4cw7m2UNVVSiDggm7MMZAnufQokwhR8r7PgYc+h6EyOH6mUCH7YcgKShRSolAFUtRFCWCteAXzzmkd1HIM8MRK5MhaZJC07SHNt7vm4q85EmgtRwBwzqF1oY7OAFSxSQRXP16TTHBwl5oYhPIoNDSo1nUskjFUWRveRiYOr1o6hZBNqKI+s2cZLRm5gRaYvve34e/QimI5XeGCEZiCxxsax2/nKbpYLWuPzMkqUqpHjW8MwzubRFDYtA0zc0gdWJIZpmbRCdTlKJxKE6AflnuLeM6rSkED+sU1lqwzn1vWYiMAYmlMcGUke/xyaHneFYJkPaGIpd4RMKxOxj84gRxPu4NqXvL6LLGE0D6kJvOWdbUsIMa3B++PgxIgn+8f+IsppBh2z2enGma2WWPxizRIP8SsOaBFoKGuzg0/M/H4Qt8PYFQLCZnbgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Sample invoice&quot;
        title=&quot;&quot;
        src=&quot;/static/bef16060b018e59dff5e5697df3671b9/29f4e/SampleInvoice1.png&quot;
        srcset=&quot;/static/bef16060b018e59dff5e5697df3671b9/4edbd/SampleInvoice1.png 175w,
/static/bef16060b018e59dff5e5697df3671b9/13ae7/SampleInvoice1.png 350w,
/static/bef16060b018e59dff5e5697df3671b9/29f4e/SampleInvoice1.png 506w&quot;
        sizes=&quot;(max-width: 506px) 100vw, 506px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Output for the &lt;a href=&quot;https://github.com/TrudAX/denistrunin-blog/blob/master/src/posts/integration-importpurchpdf/Assets/SampleInvoice1.pdf&quot;&gt;invoice&lt;/a&gt; above looks like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;HEADER&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;VendorName&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Contoso Asia&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;ReceiptDate&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2025-09-07&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;PurchPoolId&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;01&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;ChargeValue&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;50.00&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;InvoiceTotalAmount&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3751.50&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;InvoiceTotalQty&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;8&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;LINES&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;InvoiceItem&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;37&apos; TV Model A&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;ItemId&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;T0004&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;Quantity&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;Price&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;400.00&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;GST&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;80.00&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;TotalValue&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;880.00&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;Color&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Black&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;InvoiceItem&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;52&apos; TV Model B&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;ItemId&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;T0005&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;Quantity&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;Price&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;450.00&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;GST&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;45.00&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;TotalValue&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;495.00&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;Color&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Black&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;InvoiceItem&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;37&apos; TV Model A&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;ItemId&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;T0004&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;Quantity&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;Price&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;420.00&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;GST&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;84.00&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;TotalValue&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;924.00&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;Color&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Silver&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This output will be used as initial data for the processing class.&lt;/p&gt;
&lt;h3 id=&quot;inbound-message-type&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#inbound-message-type&quot; aria-label=&quot;inbound message type permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Inbound message type&lt;/h3&gt;
&lt;p&gt;To setup processing, we need to create a new Inbound message type with a processing class  &lt;a href=&quot;https://github.com/TrudAX/XppTools/blob/master/DEVTutorial/DEVExternalIntegrationSamples/AxClass/DEVIntegTutorialPurchOrderOCRProcess.xml&quot;&gt;DEVIntegTutorialPurchOrderOCRProcess&lt;/a&gt; which reads the JSON from the AI call and creates a purchase order based on it.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/85306943508f5154922b529e0c7cd331/5a190/InboundMessageType.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 68.57142857142857%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABwklEQVR42qVT2W7bMBDU3/a16EttK0+J0dQx0G8rmgZw6kSRLEPyIUqxDoqXNFlSQRGgRu0gCwy4osjh7CzpffoyxefJDD/m17iaTnF5eYXZzQzz+Q2+X3/DeDzCaPQVvj/GZDLk41e4nP77vo+LCwKN3mJtsEwMAAOtDYQykFI6KKXQdR0E56irCpw3bk4bDamG/1prvA2vLhkkLyFajqap0NQVlCVUwuWWhO13+H37Cw+PDwgIy/t7PAWPiOPY7eN1iZbWWXh3ywQ/71ZY71ssgh1uFzGCuECSCQTrA+JNg7x4xvLPAmH4hBUhDENsNima6oBVeqB9eyjBSYiAJ6lEZXpIUm5HpXsISWWqnkqzc0Bd18hIpWhbZ4UQwuVaK0hnkYExiqDhWY9ORUsepmniPHsbRVFgu92iM8Z9931/HiFvONYpw6EsSQ2pE4M6SxZFEfI8B2MZGjr4JKE91ZbZ0WjXGmP+dna32w5+kvo0SVAQ8dmEx8JawElVS35aW+y6DxEei/MIqat2Xf9a9v9wuin90GXGGLIsowYw56H18hjOI6TXEEUrJMm/V+fdJQ/XpqFrk6N4rtzztI2wKo/hBaiHKF4lyt3YAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Inbound message type&quot;
        title=&quot;&quot;
        src=&quot;/static/85306943508f5154922b529e0c7cd331/8c557/InboundMessageType.png&quot;
        srcset=&quot;/static/85306943508f5154922b529e0c7cd331/4edbd/InboundMessageType.png 175w,
/static/85306943508f5154922b529e0c7cd331/13ae7/InboundMessageType.png 350w,
/static/85306943508f5154922b529e0c7cd331/8c557/InboundMessageType.png 700w,
/static/85306943508f5154922b529e0c7cd331/5a190/InboundMessageType.png 800w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;As a custom parameter, this class requires a link to the previously defined prompt.&lt;/p&gt;
&lt;h3 id=&quot;operation-parameters&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#operation-parameters&quot; aria-label=&quot;operation parameters permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Operation parameters&lt;/h3&gt;
&lt;p&gt;We also need some custom parameters. When importing documents, you’ll likely define rules for tax calculation. There are usually two options: either take the value from the document (and then use the line &lt;strong&gt;Tax adjustment&lt;/strong&gt;) or calculate it directly in D365FO. The latter requires defining a &lt;strong&gt;Zero tax&lt;/strong&gt; group.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 606px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/dcd31585584fea203c4bf047ee2281e0/4d4a2/OperationParameters.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 61.71428571428571%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB70lEQVR42oWTWXObMBSF+XWu+xovsSf9t627+C0TZwpujN14QSwSSALMZk4veItnmlYz31wJwdHRvRej3+/hfjTEp4cxer07DGjdxsEAD+MxxqN7jIZDfOx++CvdbhedToe+66N/14ORFUAQpkgTjSDwkRcFqhrXUddH/jPq9p0axq+5hbllYWnb8H2fRIM2ui6DEAGSWB3R7xDfYqyWCzzPnmFZJn6vVrBME4vFCx1igjkOqrJoKYviMn/7rMjzE1mL4fgxYiVPlq/jUFWt24DcbjYbcu3BZQy+10QX2+0WnPabdNSHwwXD90X7sghDhESaphd4qBCICAGX4EJCRBqRSlqaPalT7PPqBiMSHB6d2pzc5E5KSUTQOiYxCcclRz6nGCArKpRUsTMFkZeHGwxN1421vtCslSSnsQbnIdabHRzmUfUrZHmJPbXFOZ7nbzEUOVIk0gopdRFMSDCJY0hKgyLHUSiQZ9kpwYe2RY7cttdJUF0Fm+uSmFq/wv7+DT+/fIb5dQJrMsFi+gP2dIrAnIPNZtg8PmL39ASH5oK6o6Qbviso7ReqLsMro56kasb7PXSSUOJzMlJh5ymsGOWbelFSASVVvhLiH4LUi+HaQcQ4Ms6xJ9GMPgCJNnhLGy79DNLZkRhDul6jiiL8Adjdb0UzUdOuAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Operation parameters&quot;
        title=&quot;&quot;
        src=&quot;/static/dcd31585584fea203c4bf047ee2281e0/4d4a2/OperationParameters.png&quot;
        srcset=&quot;/static/dcd31585584fea203c4bf047ee2281e0/4edbd/OperationParameters.png 175w,
/static/dcd31585584fea203c4bf047ee2281e0/13ae7/OperationParameters.png 350w,
/static/dcd31585584fea203c4bf047ee2281e0/4d4a2/OperationParameters.png 606w&quot;
        sizes=&quot;(max-width: 606px) 100vw, 606px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;main-modification-description&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#main-modification-description&quot; aria-label=&quot;main modification description permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Main modification description&lt;/h2&gt;
&lt;p&gt;After specifying all settings, we can test the import. Open &lt;strong&gt;Tutorial Purchase orders OCR Staging&lt;/strong&gt; and select &lt;strong&gt;New order import&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/41530f9314e251192a232a59924b8892/d3f96/NewFileImport.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 39.42857142857142%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABBklEQVR42q1Py07DMBDM/38GBZIoh+bKCXHuP3BqmkdD07z8todd03AsqsRII9vr2dnZpCgKlGWJ/X6P4jXH0/MHdvkB+dsn8vId6csOaZYhTVNkxOp4hBAC43jFPM+Ypgnee2xI+HNdVxJJqHmB7BpiDacECR288wghRDE3LssSGf+IxhhYaxD8jy7pujPatsNX30NICU9FHzyssUTzS0fUSuEyDKhONZ1XTItCfxlRNX0MxabJugqaYukRaJKF0RrOOmg6tVbRmFPyJlIKTLTFqR3QnEfU/YxhnCmIgiJ9TKho6j2wiNfiBNzE93v403AzZcQNboZcupUfN9zgnPufhI8YfgPnkGpIn/8zJwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;New order import&quot;
        title=&quot;&quot;
        src=&quot;/static/41530f9314e251192a232a59924b8892/8c557/NewFileImport.png&quot;
        srcset=&quot;/static/41530f9314e251192a232a59924b8892/4edbd/NewFileImport.png 175w,
/static/41530f9314e251192a232a59924b8892/13ae7/NewFileImport.png 350w,
/static/41530f9314e251192a232a59924b8892/8c557/NewFileImport.png 700w,
/static/41530f9314e251192a232a59924b8892/e996b/NewFileImport.png 1050w,
/static/41530f9314e251192a232a59924b8892/d3f96/NewFileImport.png 1093w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The system analyses the provided PDF and creates staging data.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/3a11d055a35f4ddf2a7e768ec00cd938/416ee/FileLoaded.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 53.14285714285714%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB0UlEQVR42lVSiXKbMBDlnw12p0070yaZHH/Y2G581ME2txAgCeTX3QVnXM089nq7Ek8KXl6f8fz0hLvvP3D37Sse7n8RfuLx8YHsPaIwRBjOCCHmUYQoCgXzeSQIZzPhLBYLfCEERZ5DqQppksFZg6HvCQ7D0I/ww6d/Yd+TvVxwXSN3+IyD1XKJ9/UKcXyAM4bQ0eBOhlvyrWnHnPgdTMdop9rIHfOtIEizEh2Raq1R1zWapkHTttAUc74lv67HGvucY+iJf81LX6PphNsEm48S+6PCNq7wkXSIU4Pf7yfsYoVT3mO9S/H254i/J404czgSuLak3v1RC38TNzRHIWBtegHr4+H9ZYInbbxYf5Pv+4HAOgKePqynv0GQ5YqO2sEPDr2z6OViyDqybrQCO9przUlsxYo/2eCcaRyTCnlRoqxqaBqeF+MmVcUaNYIx1lSrJG86i4J4XDPGka5WEJxLSxo0eCPN1ruENDJY70tkyuNwbkTbzaFAnDSkW4Xl5ozV9oxCA/uTIl1r5DWEzwjkLZF+aZogyzLazaAsC3lT1lq5zaIoptum5jwTLi/mcv52yUC+EG6qKiVDuFHyJL48KYqvzUop4cqGjn/V/DfwHwzJNbTfjowIAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;File loaded&quot;
        title=&quot;&quot;
        src=&quot;/static/3a11d055a35f4ddf2a7e768ec00cd938/8c557/FileLoaded.png&quot;
        srcset=&quot;/static/3a11d055a35f4ddf2a7e768ec00cd938/4edbd/FileLoaded.png 175w,
/static/3a11d055a35f4ddf2a7e768ec00cd938/13ae7/FileLoaded.png 350w,
/static/3a11d055a35f4ddf2a7e768ec00cd938/8c557/FileLoaded.png 700w,
/static/3a11d055a35f4ddf2a7e768ec00cd938/416ee/FileLoaded.png 930w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h3 id=&quot;invoice-validation&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#invoice-validation&quot; aria-label=&quot;invoice validation permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Invoice validation&lt;/h3&gt;
&lt;p&gt;The next step is validation. AI models may hallucinate, so it’s crucial to establish proper validation.&lt;/p&gt;
&lt;p&gt;In our case, we have three validation points:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The total quantity of all lines must match the &lt;strong&gt;Total Quantity&lt;/strong&gt; from the invoice.&lt;/li&gt;
&lt;li&gt;The total amount of all lines plus &lt;strong&gt;Charge amount&lt;/strong&gt; must match the &lt;strong&gt;Total amount&lt;/strong&gt; from the invoice.&lt;/li&gt;
&lt;li&gt;For each line, &lt;strong&gt;Quantity × Price + GST&lt;/strong&gt; must match the line value. The &lt;strong&gt;Rounding&lt;/strong&gt; field should be &lt;strong&gt;0&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/ad40e097c4f5c0bea6e2e37d4c2d3023/a1dd2/StagingValidation.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 67.42857142857143%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACK0lEQVR42m1Ti26cMBDk/3+uUqtUyV0uBz4DBmwMxjwMXKa7Jpc2apBGfrA7Hu94E20sClXD2hZlpVHXNbRuUFUVjNEwTQMdUaOlNYNjbWvQ9x2GwUXwuqG4JJcCr6cXZOkbcnnDtoa/2Fbs9x3bvmH/AO9tYcHKWOYDjzUhMbqGEAKyUFGFp9PWZUEIM5a+h1cKkyrh6DBX5BitwTxPCET0HRIpc8i8wLIEGLpqlmU0n7GTwi5NcXl5hvz9hOb1jOJyQfrrJ2o6eA1flX0qFKXDObOw3UiBBpKUdNZi8h42S2GHHtX1Cnk6objdoNNrrK13fSzLf4QVXecmMiq2gSoLmgsMzsFR4d1NoCLV+fkEQ7Vuae4pnmvKZflWoaoMOWtI0UAjO2gxkrqISmHIJSxd113f4En9RKRszHdkkXBbybWIQCRMWsVaclIs9DQisAkMmj8SHyZ8cZtNGZwnZwcslMA/52k6XIxJnHzUKfyjgveZbJ4/CLfjia0kKul6j8ZQzdyIO/34xLqQ04z5E/ft2DtiaNwDdpoHfkq1QuhaJHXrofQIUViIvMHpckNe2bh3yRq0LkCWLYq6h1QWtfHIaczkEdu0I9RZ4PnpNY5J2y/0NFa4cSdHB7xlKiYp7VE0A+3foe0c/zHxg1A1Dpe0gCZCW5KxdkAjKyTcTu/v99hWbavjE+J35qhPVZmDP37oXUc9X0iq8Rj7mTuK25WN9NRB2c8f6ITAH0ym378TfXW5AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Staging validation&quot;
        title=&quot;&quot;
        src=&quot;/static/ad40e097c4f5c0bea6e2e37d4c2d3023/8c557/StagingValidation.png&quot;
        srcset=&quot;/static/ad40e097c4f5c0bea6e2e37d4c2d3023/4edbd/StagingValidation.png 175w,
/static/ad40e097c4f5c0bea6e2e37d4c2d3023/13ae7/StagingValidation.png 350w,
/static/ad40e097c4f5c0bea6e2e37d4c2d3023/8c557/StagingValidation.png 700w,
/static/ad40e097c4f5c0bea6e2e37d4c2d3023/a1dd2/StagingValidation.png 838w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;You can also edit any field in the staging tables if needed.&lt;/p&gt;
&lt;h3 id=&quot;purchase-order-creation&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#purchase-order-creation&quot; aria-label=&quot;purchase order creation permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Purchase order creation&lt;/h3&gt;
&lt;p&gt;After validation, select &lt;strong&gt;Process&lt;/strong&gt; to create a purchase order. The purchase order is created, and the staging data reference is updated (so you can always trace an individual order to the original PDF file).&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/c92bf707e32a47b59b47407f8239e97d/1ac29/POStagingData.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 54.285714285714285%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABuUlEQVR42q2SW2/UMBCF858XCiqCUpUtAt74XUi8LRUtWzZLdjc3x058ix3nMDbbsqrEG5Y+nZkztpPMJDt7e43zqw94cfEeZxfXxBIvyXt19QmXHz/j2et3WLxZki6xOL/EIuYxJo2153TmlGz0AcYF+GnGmHTC6CdMYUYgJvJnALO1GHd7BOdBNvkh1Z+ubJvf4/ZmhfXdd7CmgrMGo1EJqyPyr8rhj8Za3GN1whqdfENkZcVwKGsIziF6AWMMNF2gtU5YypVSUFKmPNbN0ROHA/huB1nXULFGZBXT2Ow4tgeOfS0pZthVPYqyxzqvUXUW+Z7jx6bEr1Jg32ociC15qy8r3Hy9Rf7tJ+4LQb5C5r1L3x5CwDxTv6gtTzldp3naT72cj72Mtcw7h/+5MufG9HYTTTcSIsf8VB+YvP9nLZIJ3qMXPE030OdP9IDJWTo4wkc98hD70TxqiHtIT8kYXdh2HIwxlFWLhglwoVC3Ar00aFpOuYQYFDo+oKpbsK7HoCzqpoPUI5Rxj2RNp8HVBD5Y3NEkc5pyQdMuKgk2eNKeptwljazzEpuiRSen9Cc0wlE8EyHxG2HUONrmLrrUAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;PO created&quot;
        title=&quot;&quot;
        src=&quot;/static/c92bf707e32a47b59b47407f8239e97d/8c557/POStagingData.png&quot;
        srcset=&quot;/static/c92bf707e32a47b59b47407f8239e97d/4edbd/POStagingData.png 175w,
/static/c92bf707e32a47b59b47407f8239e97d/13ae7/POStagingData.png 350w,
/static/c92bf707e32a47b59b47407f8239e97d/8c557/POStagingData.png 700w,
/static/c92bf707e32a47b59b47407f8239e97d/1ac29/POStagingData.png 1022w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;From this form, you can also open the created purchase order using &lt;strong&gt;Open PO&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/bb71c31bf6b0152f443e80a4201bc1bc/25260/POCreated.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 34.85714285714286%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAAA7EAAAOxAGVKw4bAAABEklEQVR42o2R2W7DIBBF/f//14dKUZriJm4CNvsOvgVbzfLUjnTEzJ3hCg0DIWccjgRk/AL5POE6TZguFyglkVNEiuFPjFZw1iAGj4ExjnlmMMbAew/r3JaH0IfjvwjNKIbdfNBKQQqO0MyAFeta97MW1Ce6fudeP+l1PwfODSYqcVssFhkwC99wEDpBmQRpIpTN4NI/eipstdABi7BgIkDbhnHNUEXMKuMwMkzMYZwE3t4JjuS2M9Km90sRH2eO8VuBydQe0Ex1wenMcKEWlHscTlcMpWT0UFKi567tkNIbGKMbyzxv++nhnEVsO+uxruuLVkppn6Mfhjnnbag3+kAnpXRffI/eq7W+GP5qvc654Aew7h3oOwO3cgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;PO created&quot;
        title=&quot;&quot;
        src=&quot;/static/bb71c31bf6b0152f443e80a4201bc1bc/8c557/POCreated.png&quot;
        srcset=&quot;/static/bb71c31bf6b0152f443e80a4201bc1bc/4edbd/POCreated.png 175w,
/static/bb71c31bf6b0152f443e80a4201bc1bc/13ae7/POCreated.png 350w,
/static/bb71c31bf6b0152f443e80a4201bc1bc/8c557/POCreated.png 700w,
/static/bb71c31bf6b0152f443e80a4201bc1bc/e996b/POCreated.png 1050w,
/static/bb71c31bf6b0152f443e80a4201bc1bc/25260/POCreated.png 1113w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;resources-for-this-blog-post&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#resources-for-this-blog-post&quot; aria-label=&quot;resources for this blog post permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Resources for This Blog Post&lt;/h2&gt;
&lt;p&gt;All resources mentioned in this blog post are available on &lt;a href=&quot;https://github.com/TrudAX/XppTools/tree/master/DEVTutorial/DEVExternalIntegrationSamples&quot;&gt;GitHub&lt;/a&gt;. Here’s a brief overview of what’s included and how you can use these resources as a starting point for your AI integration projects.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 367px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/111a98c3474057340192949ffdd2193c/46684/ProjectStructure.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 99.42857142857142%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAA7EAAAOxAGVKw4bAAADoElEQVR42mVU2bLaVhDk/z8hcTnXrlvlVNlx7CSveU6qzM1lF1pAC2gBJEBoQWy30zNg7FQeps4mzZnu6T6tj38GePfHEG8/9fD6Q1vj7a8dvHrfxuPn697jb338+PPfePiljR/e/YWfPjzh8fchXr//ggeev+H3Dx+f8OZTF62qeYHjJej0xhibUwyNKYL5ErK/q47IyxN2jLw4YlscdJ1zXOcNY3+P7a7R81a6KbFLQ8w8DyNjgsk0gOvNEcwSzMMF6uaM8wU4nl9w4tgcLzidoXsSlxeenYDDLVrV/qyb/wz7aD91YDseej0Dg5GNwdDCeCyXzGDbLkwiGFsuL3bgTAI9s2yfFTe8CNgfLmit1iXqzQKzwIdpe4gWa8glEnVzQc2x3J9Q1dfYH170rCAdJdflbe9rtMr6iANrDYIIhmHDYoVTVjT1Qkzduc59wndva4drx/HhBzHR+Ji4s+8qZMIDyxQuJi4hGBYheDAIV6DJfETY8qPAG/HCPtfCtUOul2nOhjWK5F5htilQ5xmieQhD+OKNY2uqvFlMtN5WEBQCsagOGhXXO1YlCaQR/4N8bBqMTBPd7lB5tNgAbQSJdwkzjFPtusD0SI3rR7relYc71HvCzW6PpiphTiwY5kS5MghJYNpMHi8ybLY1MspL0Ky3JVZZjmS5YcNOKqXD6buEIkhJOJ14lIlJYdtM6Kg0hiNL5SE/h/EKYbTSBgXzBRKqYUp6pOJkuf3WlJxl76uK1UzgEYrcvlptsVrnyNY7jXRdIJX9dIs1K5ULYtIQJ+Se4zLdfUu4zmutcOK4+NLukjcfCRNGrGix2qh85vxJXDOLlqwu1sYFXAsdzZGNYahmGS3xq1QYhYly1u2PmfhZYyC65AWuH2rI3J/FOh/dNCvuEB7FjmLB1obGroscUZSQL7rFZIfJ25BaNEU2hCiREbbEKiMFjG3OvawgXKIhtzE5lf2WtH5PApJFqlIROYQkXaQSRqnyKs24yiZiE2L9Tir9OoqbXD8mrxk5pHD3OZPZNjpdgxUUqq8tuS3oAnGCzEv1LoPC5sODy+UWnMtaXySBLNaTzU5vhOfnHkxart839KURkQ8GJkdX942xg/7AwoKWy6lf0aUoQFx0b4qIU5+vzgDtdkftZtKCY8tTcVt8suRREPdYtOSISXu8RJpi6Hfufx8HySodknfN5A/ClbwmDpOIa8R6ImbPv85FyOoihqw3pEz93Fyd8i+o78lvRj4+AwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Project structure&quot;
        title=&quot;&quot;
        src=&quot;/static/111a98c3474057340192949ffdd2193c/46684/ProjectStructure.png&quot;
        srcset=&quot;/static/111a98c3474057340192949ffdd2193c/4edbd/ProjectStructure.png 175w,
/static/111a98c3474057340192949ffdd2193c/13ae7/ProjectStructure.png 350w,
/static/111a98c3474057340192949ffdd2193c/46684/ProjectStructure.png 367w&quot;
        sizes=&quot;(max-width: 367px) 100vw, 367px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The main components are:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Tables and a form to manage staging data.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;Processing class&lt;/strong&gt;, &lt;a href=&quot;https://github.com/TrudAX/XppTools/blob/master/DEVTutorial/DEVExternalIntegrationSamples/AxClass/DEVIntegTutorialPurchOrderOCRProcess.xml&quot;&gt;DEVIntegTutorialPurchOrderOCRProcess&lt;/a&gt;, which contains the logic for parsing JSON data from AI, saving it to staging tables and creating a purchase order based on it.&lt;/li&gt;
&lt;li&gt;A class for a &quot;&lt;strong&gt;New order import&lt;/strong&gt;&quot; dialog, &lt;a href=&quot;https://github.com/TrudAX/XppTools/blob/master/DEVTutorial/DEVExternalIntegrationSamples/AxClass/DEVIntegTutorialPurchOrderOCRManualImport.xml&quot;&gt;DEVIntegTutorialPurchOrderOCRManualImport&lt;/a&gt;. In this sample it’s empty, but you can extend it to handle parameters in addition to the provided file (e.g., different formats, missing fields, etc.).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Once these components are set up, the &lt;a href=&quot;https://github.com/TrudAX/XppTools/tree/master?tab=readme-ov-file#devexternalintegration-submodel&quot;&gt;External Integration&lt;/a&gt; framework automatically handles the remaining integration process. The solution uses vanilla X++ code without external DLLs and works even on a local VHD.&lt;/p&gt;
&lt;h2 id=&quot;summary&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#summary&quot; aria-label=&quot;summary permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Summary&lt;/h2&gt;
&lt;p&gt;In this post, I explained how to use AI to implement a complex PDF document import into Dynamics 365 Finance and Operations using the &lt;strong&gt;External Integration&lt;/strong&gt; framework. We covered these key topics:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How to setup an AI prompt and test it.&lt;/li&gt;
&lt;li&gt;Examples of processing AI output and creating purchase orders in Dynamics 365 Finance and Operations.&lt;/li&gt;
&lt;li&gt;How to validate the results and create a document.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I hope you found this information helpful. If you have any questions, suggestions, or improvements, please feel free to reach out.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[D365FO Integration: Import Sales Orders from an External Web Application]]></title><description><![CDATA[Learn how to implement robust and efficient process to import complex documents into Dynamics 365 Finance and Operations from external Web services. This post covers integration design, practical code examples and troubleshooting strategies.]]></description><link>https://denistrunin.com/integration-inboundwebsales/</link><guid isPermaLink="false">https://denistrunin.com/integration-inboundwebsales/</guid><pubDate>Wed, 12 Mar 2025 22:12:03 GMT</pubDate><content:encoded>&lt;p&gt;In this blog post, I&apos;ll walk you through the process of importing sales orders into Dynamics 365 Finance from an external web service using REST API calls.&lt;/p&gt;
&lt;p&gt;Although the example provided here is simplified to illustrate core integration concepts, the approach and code samples are based on real-world scenarios. This makes them highly adaptable for similar integration tasks you might encounter. We&apos;ll utilize the free and open-source External Integration &lt;a href=&quot;https://github.com/TrudAX/XppTools?tab=readme-ov-file#devexternalintegration-submodel&quot;&gt;Framework&lt;/a&gt;, which provides reusable components explicitly designed for building robust integrations in X++.&lt;/p&gt;
&lt;h2 id=&quot;integration-scenario-overview&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#integration-scenario-overview&quot; aria-label=&quot;integration scenario overview permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Integration Scenario Overview&lt;/h2&gt;
&lt;p&gt;Let&apos;s start by defining our integration scenario:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Goal: Design and implement an integration solution that imports sales orders into Dynamics 365 Finance from a partner&apos;s website via a REST API endpoint.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;To illustrate this integration, I will refer to the Purchase Order Management application mentioned in my previous &lt;a href=&quot;https://denistrunin.com/integration-outboundweb/&quot;&gt;post&lt;/a&gt;. This application offers an API endpoint that retrieves created or updated orders. Although the example provided is simplified, similar APIs are frequently found in other systems, such as &lt;a href=&quot;https://shopify.dev/docs/api/admin-rest/2025-01/resources/order#get-orders?status=any&quot;&gt;Shopify&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You can access the complete source code for the Purchase Order Management application on &lt;a href=&quot;https://github.com/TrudAX/TestWebService_PurchaseOrderApp&quot;&gt;GitHub&lt;/a&gt;. The application consists of two primary components:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Frontend Application:&lt;/strong&gt; Provides a user interface for viewing and managing orders.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/66d0f04c6ae9ac12e9adcb3d50130048/0f7d5/PurchManagementAppScreen.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 76.57142857142857%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB/ElEQVR42o1U226bQBDN//9PlT5Ueany2oeUFjtWHQe7xoC57BWwgdOZcaCmjtSsdLQ7w3B2Lkd753yN9KhwLIwgKw3SQqNQHq4dCL3Av8H9B3dVVUFrBe8drDFofUNoYa2BIdtZS2cre13Xf+H9zPZkM4SwLEuoSiFODnj49oDHp0csFiHCMETwI0AQBIiiCBxbFAVK2sf/RlS8k+9CWJXQSiPOYnwK73H/9BnRdgujNRRlv9vtJkLOer//jc1mA6UUVaclbrePkR3iC+GEspJyq/wS2DQNhmGQs7UOXdcJmIgz9dR/toe+Q5TXUM+rOSGnHkWvSNIUh0Mivfvo4ot53RCmRMZ7nudTs7k/x2MO55z4qort4zQIiSGfoQRmhFyGNlp6lmWZlHQ+n+XMOJ1OZJ/onEoM95N9fXfGak/SC37eZrilYWR0e5qk0rePrp5KHujyd0vmIZRlMWnMUNaKVODftMcaZe3OdOgMasr2pmSeIEsijmPpGZecJInYbduKfSB5cAwPbSx5sSuQfQ/+lU0pwTkRc8+YcJzgOMVr+9rX9WRfZ8iZ8WSXyxDr9S+8vKyxWj2LoL23UuYI5+a2+MTv5hkyqVUsAQNlHLT1sK5B3Z4n+OZE3+jhqNuZf8S8ZFXhy+orlvtX1A3gGnptmv4Gxnewdffutz+wt30nS0Y9VwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Purchase Order Management App&quot;
        title=&quot;&quot;
        src=&quot;/static/66d0f04c6ae9ac12e9adcb3d50130048/8c557/PurchManagementAppScreen.png&quot;
        srcset=&quot;/static/66d0f04c6ae9ac12e9adcb3d50130048/4edbd/PurchManagementAppScreen.png 175w,
/static/66d0f04c6ae9ac12e9adcb3d50130048/13ae7/PurchManagementAppScreen.png 350w,
/static/66d0f04c6ae9ac12e9adcb3d50130048/8c557/PurchManagementAppScreen.png 700w,
/static/66d0f04c6ae9ac12e9adcb3d50130048/0f7d5/PurchManagementAppScreen.png 993w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;&lt;strong&gt;Backend API:&lt;/strong&gt; Exposes a REST API endpoint to retrieve orders created or updated after a specified date.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/d8639f357ddfcd9bbf30922078fe8d4e/cc8d6/ApiPicture.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 82.28571428571429%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAYAAAAWGF8bAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABR0lEQVR42qWTy27DIBBF/f+/l26SLpKqjuMHBoPxC2PfzEyz6aJSXJBGjBAMZ7iXzDmHsEQs04TO9njUBkr3aCQcWuOhTE8zRedh7ADN0b3CDa81L+tZURRQjcZ35WCtg+/pgrBgDQHrGigPkoc3gvdlqmkwTSPsuCLuO7Zte+vwX5Fpo1FXFbRuidBiHEekjMw6i8v5jDwvUFHhsnzAmA5936PrOszzcqzg4D24KB9m5BijtL1T+xyHCUNYiUjjdPrA9Xol0hx7SsvTNGMYyBpK0TwI5X/IfhF6arssSyHVxiQWXCMVMjiLMDmprdNUnueZfDiJqpyzKEmEMW4w5EEmvN/vZJ06jZBFYLrb7Qttq+BJmCRCQ/5j38ngOuI/TnfJDxdslKY2S1H352fM2FIIud3Py0UUruua3jGXd2QryQXLsa/3BN3P5zOdkrIgAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;API sample&quot;
        title=&quot;&quot;
        src=&quot;/static/d8639f357ddfcd9bbf30922078fe8d4e/8c557/ApiPicture.png&quot;
        srcset=&quot;/static/d8639f357ddfcd9bbf30922078fe8d4e/4edbd/ApiPicture.png 175w,
/static/d8639f357ddfcd9bbf30922078fe8d4e/13ae7/ApiPicture.png 350w,
/static/d8639f357ddfcd9bbf30922078fe8d4e/8c557/ApiPicture.png 700w,
/static/d8639f357ddfcd9bbf30922078fe8d4e/cc8d6/ApiPicture.png 791w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The API requires an &lt;strong&gt;UpdatedAt&lt;/strong&gt; date parameter and returns all orders created or modified after this timestamp. Our integration task is to retrieve these orders and load them into Dynamics 365 Finance.&lt;/p&gt;
&lt;h2 id=&quot;planning-and-scoping-integration-project&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#planning-and-scoping-integration-project&quot; aria-label=&quot;planning and scoping integration project permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Planning and Scoping Integration Project&lt;/h2&gt;
&lt;p&gt;Before diving into the technical implementation, I recommend organising a kickoff meeting involving key stakeholders from both the Dynamics 365 Finance and Operations (D365FO) team and the external Web application provider. During this meeting, ensure you cover the following critical points:&lt;/p&gt;
&lt;h3 id=&quot;define-the-web-api-endpoint-and-parameters&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#define-the-web-api-endpoint-and-parameters&quot; aria-label=&quot;define the web api endpoint and parameters permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Define the Web API Endpoint and Parameters&lt;/h3&gt;
&lt;p&gt;Most web applications have well-defined endpoints that accept multiple parameters and return structured data. In our scenario, the API endpoint retrieves orders modified after a specified date using the &lt;strong&gt;updatedAt&lt;/strong&gt; parameter. For example:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;https://purchaseorderapp20240916.azurewebsites.net/api/PurchaseOrder?updatedAt=2025-02-07T16:00:00Z&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Discuss what authentication should be used; in a typical scenario, a token-based approach is used.&lt;/p&gt;
&lt;h3 id=&quot;confirm-the-scope-of-returned-documents&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#confirm-the-scope-of-returned-documents&quot; aria-label=&quot;confirm the scope of returned documents permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Confirm the Scope of Returned Documents&lt;/h3&gt;
&lt;p&gt;At this stage, it&apos;s essential to clearly define and document exactly which documents the API will return based on the provided parameters. In my experience, API sometimes may also return internal or irrelevant documents—such as orders for locations not managed in D365FO or internal transfer documents. This can significantly complicate integration logic and data validation processes. To avoid these issues, ensure you obtain a confirmation from the external Web application team that only documents relevant to Dynamics 365 Finance will be returned by the API.&lt;/p&gt;
&lt;h3 id=&quot;establish-rules-for-handling-updated-documents&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#establish-rules-for-handling-updated-documents&quot; aria-label=&quot;establish rules for handling updated documents permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Establish Rules for Handling Updated Documents&lt;/h3&gt;
&lt;p&gt;A document may be modified after it is retrieved via an API. Typically, when a document is updated, the &lt;strong&gt;updatedAt&lt;/strong&gt; timestamp changes, while the document&apos;s unique &lt;strong&gt;ID&lt;/strong&gt; remains constant. It&apos;s important to define when these updates happen and to understand how often they occur. Ideally, updates after initial retrieval should be minimized or avoided altogether, but this may be a business requirement.&lt;/p&gt;
&lt;p&gt;To manage document updates effectively, consider requesting the external Web application team to implement a clear status indicator. This indicator should explicitly mark when a document has been finalized and exposed via the API. For example, users might initially create an order, add necessary details, and then explicitly mark it as &quot;Confirmed&quot; or &quot;Completed.&quot; Only after this explicit action the order should become available through the API.&lt;/p&gt;
&lt;p&gt;On the Dynamics 365 Finance side, you must establish clear rules for processing updated documents. For sales orders, common approaches include reversing or deleting the original order and creating a new one. Keep in mind that reversing transactions can introduce complexities, e.g. the ledger period for the original order may be closed. In such cases, you might need to use the nearest available open date or implement alternative business logic to handle these scenarios.&lt;/p&gt;
&lt;p&gt;In this blog post, I use a simplified approach: I delete the original order if it remains open and generate an error if the order status is no longer open.&lt;/p&gt;
&lt;h3 id=&quot;discuss-the-test-endpoint&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#discuss-the-test-endpoint&quot; aria-label=&quot;discuss the test endpoint permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Discuss the TEST Endpoint&lt;/h3&gt;
&lt;p&gt;Confirm whether a test version of the Web application is available and clarify what kind of data it contains. Typically, a test environment exists, but may include dummy data. This can cause issues because Dynamics 365 Finance integrations usually require close to production data. If the test data isn&apos;t suitable, you might need to perform some integration testing directly against the production endpoint.&lt;/p&gt;
&lt;h3 id=&quot;request-a-guide-for-creating-documents-via-the-user-interface&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#request-a-guide-for-creating-documents-via-the-user-interface&quot; aria-label=&quot;request a guide for creating documents via the user interface permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Request a Guide for Creating Documents via the User Interface&lt;/h3&gt;
&lt;p&gt;Ensure someone from the D365FO team knows how to create documents using the external Web application&apos;s user interface. These documents should then appear in the API—for example, creating a sales order that will be imported into D365FO. This step is essential for testing, so request clear instructions on how to perform this task.&lt;/p&gt;
&lt;h3 id=&quot;resolving-mapping-errors&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#resolving-mapping-errors&quot; aria-label=&quot;resolving mapping errors permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Resolving Mapping Errors&lt;/h3&gt;
&lt;p&gt;It&apos;s common for certain entity codes to need mapping between systems. Define which system will handle this mapping and discuss the steps for adding new mappings values.&lt;/p&gt;
&lt;p&gt;In our example, I&apos;ll store the Customer account mappings in a separate table.&lt;/p&gt;
&lt;h3 id=&quot;create-a-data-mapping-document&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#create-a-data-mapping-document&quot; aria-label=&quot;create a data mapping document permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Create a Data Mapping document&lt;/h3&gt;
&lt;p&gt;Mapping documents is a key integration document that defines how fields from the Web application API will be mapped to D365FO fields.&lt;/p&gt;
&lt;p&gt;In our case, it will look like &lt;a href=&quot;https://github.com/TrudAX/denistrunin-blog/tree/master/src/posts/integration-inboundwebsales/FieldMappingWebAPI.xlsx&quot;&gt;this&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/5276d3b85406435be1c55845a039abff/ec3e2/MappingSOSample.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 45.142857142857146%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACG0lEQVR42i2SWW/aUBSE+f+v7UN+QKs8RKoStUJNGrOFxQZssPGODWZJvAEmJksrEb7eJr3S6M7ch9HMObcyW+bo7g7d2+NHj4RLwa01un2PE6QYboLnLUgshXI55bDyeVpPyXxLaE9A6NjhZTvhd2FR8V0LrV/D1huYlsXI3aKM12i2MPNzVHuD4y6I1Rt2jsbe0yinI8GHvM7G7GyVfahwiO84FjIVz+zR+/UJs/OZfreKaqXIWsjAWDA0V+jOA5IS0LqtEY8aLIYfWGstCnfAIRjzvBwIM4U/G0UknG+Q+hk964Vmf4UymiO1J9S7ljB/EPVXXHYjzn80SVSJ+1GbRO8QiVb/DJ9DnV3QIQ6uKZZ1kdBWuLs5Q5bOaDertPohjZ5FQ3boqAGKOuW8ZvPlSmJrNJkP6iz6AoMaudV7TxoMqswmVyTBDZXQH2EOLpibl0x0mUlQ0B1O6QqzsZvizbZcyQsufrY5uDK5CFAGGonR4dFXxTw1YqtBZH0nm91SMb011bpLV89oKCFNxeOu79MSprKYY0/c39pzvl5KZJrEXJHIJx2WIuHeVXgUtXOnwSa65umhScV2QyZOxHSeYIptGnb0DtNbEa62zKIUxYnFKAw2gcHa1ckDi8Q3KMUX2i98ygeX18LheWtTSdOUfVGQJglJHJNlGWmakOc5ZVlyPB7hdOLt7cSJjyPkO8QTR0GOgrz9138BuLN856qglQIAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Mapping SO Sample&quot;
        title=&quot;&quot;
        src=&quot;/static/5276d3b85406435be1c55845a039abff/8c557/MappingSOSample.png&quot;
        srcset=&quot;/static/5276d3b85406435be1c55845a039abff/4edbd/MappingSOSample.png 175w,
/static/5276d3b85406435be1c55845a039abff/13ae7/MappingSOSample.png 350w,
/static/5276d3b85406435be1c55845a039abff/8c557/MappingSOSample.png 700w,
/static/5276d3b85406435be1c55845a039abff/ec3e2/MappingSOSample.png 997w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;high-level-design-description&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#high-level-design-description&quot; aria-label=&quot;high level design description permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;High-level Design Description&lt;/h2&gt;
&lt;p&gt;A single web service call might return multiple unrelated orders, but we still need clear traceability from each individual order back to the original web request. To achieve this, I introduced the concept of a &lt;strong&gt;parent message&lt;/strong&gt;. Here&apos;s how the processing logic works:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The load class sends a request to the Web service using the current message&apos;s &lt;strong&gt;UpdatedAt&lt;/strong&gt; date.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The response from the web service creates a parent message. The returned JSON data is attached to this parent message, and processing begins.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;To process the parent message, we parse the attached JSON data and create multiple child messages—one for each order. Each child message contains parsed data stored in staging tables. During this step, we also perform basic cleanup actions based on unique identifiers, such as deleting previous messages with an &quot;Error&quot; status that share the same ID. This step is executed as a single transaction in a single thread.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If the parent message processing completes successfully, we update the message&apos;s &lt;strong&gt;UpdatedAt&lt;/strong&gt; date to the new value. (If paging is used, we update the paging information instead).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Finally, each child message is processed separately in batch tasks. These tasks can run in parallel (multithreaded mode) and use the staged data to create the final documents in Dynamics 365 Finance and Operations. Errors encountered during this stage do not affect the parent message.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;setting-up-the-integration&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#setting-up-the-integration&quot; aria-label=&quot;setting up the integration permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Setting Up the Integration&lt;/h2&gt;
&lt;p&gt;Let&apos;s walk through the steps to set up and validate our integration solution.&lt;/p&gt;
&lt;h3 id=&quot;configuring-connection-types&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#configuring-connection-types&quot; aria-label=&quot;configuring connection types permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Configuring Connection Types&lt;/h3&gt;
&lt;p&gt;First, we need to create a connection to our web service. To do this, go to &lt;strong&gt;External integration &gt; Connection types&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Here, we define the connection details for our web application:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 583px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/d12723fb621f530bd5347d22159776c0/9fc4b/ConnectionTypeForm.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 74.28571428571428%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB0ElEQVR42qVTy47UMBDM/9/5BBBHOCwHxIUP4ICG0TJotUx22dh5OXEcOw/HKbo9wz7EILGzllq2nE51dXU5wTrg1YcObz83WMYO2jh0XYe86lHXNZSqkec5pjkgrIhrXVeEEE5GUlcl9lmLrOjgnIXpe/Qx+GxgjIkFqrLATZpCZBmapsHoHMZhiDHQeeCdIqnLEs5wgiEWE6ZpoiROtnC2p2QLT/dFLrDdbLC7/I7ttw3SdI95GmMEP2PmoLzk6ucd3n/6incfvyAvNVWZUSmD3XWGH3uBq9sCqhugWxUZSiHumXEhLirEHUrqgJknu2uJ1xdbvLnYoFAOdvBoe49U9pDaI9eBAH0E/HV7g7IoojTOWliWxugogzFdlCdplMJRauCv02Et3pOmBgWB5TKHkCLq9WcQj4eUqCNgCE9hOGk9XoVlARcuSe/DtwPIQ95DnGSIUwypJSklmEBP7bITDE1/nucnuf8PSC0LkUWWWrdo2wZ1VZGe7vmAngDZa/zzyDa51+6wn8XQEkO2Bb+cqq6i6VnbswF7soSk6QryIWu4ENiy+Lif1TJ7T3ca4zhFVgewlwASq5aG0TQqPk9PT42DQV80FH4RlsD/tX4DvE+NOHy+ft0AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Connection type&quot;
        title=&quot;&quot;
        src=&quot;/static/d12723fb621f530bd5347d22159776c0/9fc4b/ConnectionTypeForm.png&quot;
        srcset=&quot;/static/d12723fb621f530bd5347d22159776c0/4edbd/ConnectionTypeForm.png 175w,
/static/d12723fb621f530bd5347d22159776c0/13ae7/ConnectionTypeForm.png 350w,
/static/d12723fb621f530bd5347d22159776c0/9fc4b/ConnectionTypeForm.png 583w&quot;
        sizes=&quot;(max-width: 583px) 100vw, 583px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Provide the following information:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;URL&lt;/strong&gt;: The web address of our application (for example, &lt;a href=&quot;https://purchaseorderapp20240916.azurewebsites.net/&quot;&gt;https://purchaseorderapp20240916.azurewebsites.net/&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Timeout&lt;/strong&gt;: How long the system waits for a response before timing out&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Credentials&lt;/strong&gt;: Username and password details for authentication&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Dynamics 365 Finance offers several ways to store passwords securely:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Manual entry&lt;/strong&gt;: An unencrypted string, suitable for development. It will persist even after database restores.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Encrypted&lt;/strong&gt;: A secure option that encrypts the password value.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Azure Key Vault&lt;/strong&gt;: Links to the standard D365FO key vault for the most secure password storage.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;defining-inbound-message-types&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#defining-inbound-message-types&quot; aria-label=&quot;defining inbound message types permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Defining Inbound Message Types&lt;/h3&gt;
&lt;p&gt;Next, we&apos;ll set up the import parameters using the &lt;strong&gt;Inbound message types&lt;/strong&gt; form.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/154806881a738e2f4f15fe29b63a6129/2e195/InboundMessageTypeSetup.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 75.42857142857143%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB00lEQVR42pVTy5KbMBD0/39PPiK3XFLZrXKSNRjbgAG9EQ/hzsysoXwLS9WUxJTU092jOfz4HfDtu8I8eBjr0SoHrRSM1lC0OufQtq3sObRW8JRz1sIaQ2c1xnHCPH/GwTuN2HtMY8Qw9BSR9iOmaZR/zluj8PbrJ97f33DOM2Qff5FlJ+T5icAGLGmmc4PE4aO4409eozETilLhXJToTIC2PS6lxvUeYF3A9ZKjritUVYnzOUNzryUMMb4UZ4zP4oe6C2g0sYiA9hOUJsk2QBkP5SYQLnyIKG9XkcrRda1YYkgyy67KUpgmlpxSwv++cRjo0o0ujfL/eDxkHSjPfqclbXkBfLxc5rNbPHPs6a1qcW81GT9TfAJYakxRFMI6+CAFdzFkwH5IiGPCsiwCugJmpwxt05C/Nbz3OyWTP7EPCMGjp3Uh+gzMkp2zwpC97EPY7+GNmpLnubBirx4MGCO9Sy2Awnr1cA9DRc+DZQVisTZFqQ7H45GKlVTICOvdDPkCAxhjN8C+7ynvZGX5XwJs20aYsMStWc9xSwS0frsl80wb8i+lectH8pCt8NSsLwHKfMts0zS8nOd3J9NChZYny93vcPXtdVIYqOs6RCq0vs1/HvWQxHZQiKUAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Inbound message types&quot;
        title=&quot;&quot;
        src=&quot;/static/154806881a738e2f4f15fe29b63a6129/8c557/InboundMessageTypeSetup.png&quot;
        srcset=&quot;/static/154806881a738e2f4f15fe29b63a6129/4edbd/InboundMessageTypeSetup.png 175w,
/static/154806881a738e2f4f15fe29b63a6129/13ae7/InboundMessageTypeSetup.png 350w,
/static/154806881a738e2f4f15fe29b63a6129/8c557/InboundMessageTypeSetup.png 700w,
/static/154806881a738e2f4f15fe29b63a6129/2e195/InboundMessageTypeSetup.png 782w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;This form includes the following key sections:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Connection Details&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Here, you link the message type to the previously created connection and specify the processing class (&lt;strong&gt;DEVIntegTutorialWebSalesProcess&lt;/strong&gt;).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;INCREMENTAL LOAD&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Last date time&lt;/strong&gt;: The date and time used for the data load. This value (adjusted by the Overlap setting) is passed as the &lt;strong&gt;UpdatedAt&lt;/strong&gt; parameter in the next request. After each successful load, this value updates to the current time.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Overlap (seconds)&lt;/strong&gt;: The number of seconds subtracted from the &lt;strong&gt;Last date time&lt;/strong&gt; when making a request. This helps account for delays between data being written and the transaction being committed in the source database, ensuring no data is missed.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Offset&lt;/strong&gt;: Indicates the current page number if paging is enabled. This value updates automatically during the load process.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Limit&lt;/strong&gt;: Defines the maximum number of records returned per page if paging is used. If the number of records returned equals this limit, the system increments the Offset by one(goes to the next page) and does not update the Last date time.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Do not process on load&lt;/strong&gt;: This is a debug option that prevents messages from being processed immediately after import.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;mapping-setup&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#mapping-setup&quot; aria-label=&quot;mapping setup permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Mapping Setup&lt;/h3&gt;
&lt;p&gt;In real-world integration scenarios, you&apos;ll likely need to map certain fields between systems. The &lt;strong&gt;External Integration&lt;/strong&gt; module provides a simple form and table to handle these mappings. Let&apos;s walk through an example.&lt;/p&gt;
&lt;p&gt;We&apos;ll map the &lt;strong&gt;Order account&lt;/strong&gt; from the Web service to the corresponding &lt;strong&gt;Customer account&lt;/strong&gt; in D365FO. You can configure this mapping under &lt;strong&gt;External integration &gt; Setup &gt; Mapping setup&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/d45b323caaebde0a290ce0733c6eb613/66caf/MappingCodesSetup.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 52.57142857142857%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABeklEQVR42p2S2U7EMAxF8/+fBrwAb0hAZ2s7nWZPmqRJe3E7wwjEJvFwZMvXsbyEcWkRhgDjIqTSkJLDeY8xZ+R/wB4f7rGpXtHUNRX2SDGsjCn+C1ZTIc578L6Hd+6PB+nvgt1JAHPBPGWUnFbyuIiBLEH2Gl980qacVv3MsMYz2UVj1YGj7gw6EXDkA04qrmxriX2r8Lw5UtxD2IxdI7Gh/J70fStQNRybRuDppcFT1eH1IMDMkCFMhNABvfSQNsKGGY4wvoCrgQiw5GubwClPuUw5RJxWlvfKFno7gk1lBFDWsWluzJfx3znHCwpp0zyfc6bvcxaYoK6cD9frphg/+JeL5xFxt4W5u0VwFil9zYkXWN8rSO1o6eOKNYrQ10MpwWkcDX97g+HlGdQjSeOnDj/CDp3DrpWo9oIWTktfjnE04Kag15liAttGg8cZPID2RTuzP8OkCeioy7YTaOkLnbiGUB5DmuFp4Sdh6FgOQyjwdIhA8d94A+aWU0Yo3GaqAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Mapping codes setup&quot;
        title=&quot;&quot;
        src=&quot;/static/d45b323caaebde0a290ce0733c6eb613/8c557/MappingCodesSetup.png&quot;
        srcset=&quot;/static/d45b323caaebde0a290ce0733c6eb613/4edbd/MappingCodesSetup.png 175w,
/static/d45b323caaebde0a290ce0733c6eb613/13ae7/MappingCodesSetup.png 350w,
/static/d45b323caaebde0a290ce0733c6eb613/8c557/MappingCodesSetup.png 700w,
/static/d45b323caaebde0a290ce0733c6eb613/66caf/MappingCodesSetup.png 853w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;running-the-integration&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#running-the-integration&quot; aria-label=&quot;running the integration permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Running the Integration&lt;/h2&gt;
&lt;h3 id=&quot;generating-test-data&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#generating-test-data&quot; aria-label=&quot;generating test data permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Generating Test Data&lt;/h3&gt;
&lt;p&gt;To test our integration, we&apos;ll first generate some sample data. Enter three or more item numbers (for example, M0001; M0004; M0007) and click &lt;strong&gt;Load initial data&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/c467f0f210532f242e406a8334e55f67/b4098/LoadInitialData.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 92%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAYAAABb0P4QAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACjklEQVR42qVUy27bMBDU/39F0Z7aU9tzL70FbRonbu34GTuybEuy3hKpV+zpDl2lSgIEKEpgQHK52N0ZLmlVVYVKNyh1iSQr4AcJoqQwCOMccarMOslKlPXxVShdw0rTFGlaIMsyA6UUqqpEXVd4eGjRtA2ahqiN/TXUtQTcbDaYjMaYTWYYj0b4ORxieHODweAaV1cDTKdTJEmCOI4F3Rz39mdEnKMI1sC+xpvLt3g//oj51y9wPn3GIY7gui48z0MQBCbgc5BZf5+nMVJVwHJcB2v/HsPZEOv1CpkclqXoVWrZr7FYLEw1WmsURYH5fI7JZILD4WDkIbTgZrmD92sEK5FSVa7guz4iKZnZjscjTqeTXJQGL60btCmlTXAm7R3ATk/QksyKwgDj21tDjVk9z8W/DiYiOCwKyWCcGZA3zapYAauNwhB5nps9KyP9UGzdvqtWZSJL28LiIY277RYHCczDLqDjOLBt22hHG/WiruvVyhRx1lr8BT9WIfxv36VCyUjtGND3D8aRGnKw/1rJ2qfGXjN9KXNfw0AkbfauaBiFmM7mhh6rZcD/0jCUSwnDCJ703VaqZH+RGmmyF0mbLGijlrvdztgyWdOngys9m4jfXw3FkdSpyfmpNaaxPdcz+pF6JTTpt9ttjW/n1wqunBzhxQU1jLA3r8KHfxD4/mP5fSrP6XU6P2or25Mktth309nM0CUVYr/fG5pda3Qvgui3S2cjZT4Czc+BOi2WC2mHO2ycDVb2Pe6WSwTSk2wHJc76z/PS8laLPOvtX8IqClnkLTLVQMn/1yS5KV/zf6ueItet/I3KzM/POlj7yMW7wQeMvDXyhY3k8hpaZNNlCy0OT2A+0tNLew+/ATM3YXoiUvPcAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Load initial data&quot;
        title=&quot;&quot;
        src=&quot;/static/c467f0f210532f242e406a8334e55f67/8c557/LoadInitialData.png&quot;
        srcset=&quot;/static/c467f0f210532f242e406a8334e55f67/4edbd/LoadInitialData.png 175w,
/static/c467f0f210532f242e406a8334e55f67/13ae7/LoadInitialData.png 350w,
/static/c467f0f210532f242e406a8334e55f67/8c557/LoadInitialData.png 700w,
/static/c467f0f210532f242e406a8334e55f67/b4098/LoadInitialData.png 816w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The web application will generate three orders based on these items.&lt;/p&gt;
&lt;p&gt;Once you&apos;ve completed all setup steps, you can run the &lt;strong&gt;Load messages&lt;/strong&gt; batch job.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 483px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/c5c4851c7898afa8f3e10c8e587bc802/77a9e/LoadIncomingMessages.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 112.57142857142857%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAXCAYAAAALHW+jAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACaklEQVR42qVV246bQAzl5/s1VR+r/kGlSpX62IdNSgj3AOF+GS5zapuwgd2skmiRrBmGmTP28bEx8jyHfTwiCHw4jiMWBIGMlmVBKYVnHqPvB/R9j2Ho5XDXdTIqGtu2hdZ63snjYrceWh/HEQYDeJ4H13UFYP52PTRNk9i8pmVc1hZjh5TqEJ1OMAZ6ydIEeZ6iLEtMenpzQMvmuipR0PeiKMST9R5+58uiiADbtsPfnYcXK0Z8zug2haqqKPQrd07U4fuvBEkSoazqG9HOEcVRBIPR07xFVigBURR22zTE6fB6QNE0qzU4Gn2Dww1g27TwXBvn5ATP9+F6roDxprUt/OkLn2vj/ZxICXkYNeK0R1oyyDUBt8j/yGYOMSel61rs/5k4mEccSXe2bUvWwzB8WHubkNlV0zSJ8Bh1XUtCeHxG0G84bLDbvZB0zsizlOSTEZ/xqyafBhzHgbJaU4YbNOQZzxls4eWRh3nkSonEQ9LhwXIouz7VroP9/gCHqkZdJLKQ/pFdK0XNSRmpEtJyEqs6jaSY0PUrmVzCmZWjN2Gu1XDlkMLzPUf4i6kSuLbXvHA3chxbug9nnxNWcyXRuZ68Wl8qgA0lxSdB5xmX3bDtLgxI67Z9pEtdAeW9lnVARut8dvFOAGMCvEd4QR5yfwyJHy7NUaqi25TgMhcO7wGyrErqMKJPsoYsTdONZ3oVjXFPW3yYeyW3sYc69iMhR6dQkvPuUtbgqomzE3cBOdQwDGTUWn/ew+Hyz+FOvvp9zEnIR3z7WePPviVuM+oH5/uAS2jQeAdohgO+fM3w43eBLPZhOw7+A7X+BmnDA4EcAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Load messages&quot;
        title=&quot;&quot;
        src=&quot;/static/c5c4851c7898afa8f3e10c8e587bc802/77a9e/LoadIncomingMessages.png&quot;
        srcset=&quot;/static/c5c4851c7898afa8f3e10c8e587bc802/4edbd/LoadIncomingMessages.png 175w,
/static/c5c4851c7898afa8f3e10c8e587bc802/13ae7/LoadIncomingMessages.png 350w,
/static/c5c4851c7898afa8f3e10c8e587bc802/77a9e/LoadIncomingMessages.png 483w&quot;
        sizes=&quot;(max-width: 483px) 100vw, 483px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;This batch job executes the processing class linked to your inbound message type. As a result, four initial messages will be created and processed:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;One parent message containing the original API data.&lt;/li&gt;
&lt;li&gt;Three child messages created from parsing the parent message data into staging tables.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/d4bf4e8c0924788937d7ca5f6e71bd77/681f1/4InitialMessages.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 53.14285714285714%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABZElEQVR42q2T3U7DMAyF8/7PB+MG0GCbymgTp/lP2vXghK4aIG4QkT7ZPYmdxHGFsRYhRigyICVBRFBs5dDDe4fgPesKWmtotjEmTNP0g1ImjCZD3N/f4WG3w8t+z0HqM+mKGTVyikgxbNTv3yiMkHIAaYJztgXE4L8Q2ind5t9qofpXVk30g153j7w4YCplI+eMwuSU4Lg0iW0tQV1b9eo3OGFZ14q+7zHPUxO7roM1BoapNat6HfU6p+Nrq1XkzateOZ87jjlh5Bt+jgXi6SDxJiN6Sti/djiczjgcz80fLZ86z+h1wuPRQJoZys4gt+CdMp5Yez4SusE1TdkLhNIOPk5woUDSyC/lGA898hUzv+C8IKQJUnNN8wWpLI2QLlCsWV82rSLwz0Msy4JbLjd815df+JKQSLV+G//ANS7ntHWGqH8ESQnNiTVxQ3NfKtkzQ9Pq/NVvdm14urGkhjbnncUHkN5Szv6MZLcAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Initial messages&quot;
        title=&quot;&quot;
        src=&quot;/static/d4bf4e8c0924788937d7ca5f6e71bd77/8c557/4InitialMessages.png&quot;
        srcset=&quot;/static/d4bf4e8c0924788937d7ca5f6e71bd77/4edbd/4InitialMessages.png 175w,
/static/d4bf4e8c0924788937d7ca5f6e71bd77/13ae7/4InitialMessages.png 350w,
/static/d4bf4e8c0924788937d7ca5f6e71bd77/8c557/4InitialMessages.png 700w,
/static/d4bf4e8c0924788937d7ca5f6e71bd77/681f1/4InitialMessages.png 899w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;From this form, you can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;View the original data from the web application by clicking the &lt;strong&gt;Download file&lt;/strong&gt; button.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/1b1386b118c7a9d9548d44dae665aed3/8b69f/DownloadFile.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 32.57142857142857%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAAA7EAAAOxAGVKw4bAAABLUlEQVR42m1R2W7CMBDM//8Y5QuQWglBCLkgic/YOdB0Nib0pQ+j9d4746xparSPDveiRFNXqKoKZVGgKktYY2CtQfd8Qg09+q5DCBHLPP8LZSKyy+WC8/kMrQdMMSCOY7Ih2WWaWPyHOcYPJL9D/GXmQDUM0GqAdw5h9Bi9+0Bi3trtLTnv5O1T/F2/96SY5UCtsS7zRk3wWtd0zeuFFcBKXxqUEgZxk0HszMu1VjxGwXHpTjurqeFImk3T4E7dHm2Llpp13z8wpxNi31MbjZK5EAKH6M16XlrX9YaBLCcukHh2pYZ5fsPtViC/5tsH9Gwavo54Hg5wLJ65WYqj6MZGsTGIhmmIxHZkcp17a2IJ8WW7l43LmmL0jTak5lhrYUjRcKn0bZSdTz3e4xdkABmKEu1mxAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Download file&quot;
        title=&quot;&quot;
        src=&quot;/static/1b1386b118c7a9d9548d44dae665aed3/8c557/DownloadFile.png&quot;
        srcset=&quot;/static/1b1386b118c7a9d9548d44dae665aed3/4edbd/DownloadFile.png 175w,
/static/1b1386b118c7a9d9548d44dae665aed3/13ae7/DownloadFile.png 350w,
/static/1b1386b118c7a9d9548d44dae665aed3/8c557/DownloadFile.png 700w,
/static/1b1386b118c7a9d9548d44dae665aed3/8b69f/DownloadFile.png 912w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;View the staging data associated with each individual message.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/012c072d2aec9310f335fcb526b53836/82b28/StadingDataInitial.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 53.714285714285715%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABqUlEQVR42o2T23KbMBCGef9n6WUv2rte9AV640ychDgO1IABSeh8gL8r2dOOPe00DN/sSlqt0P5LxbgEJ5RSWJYFXd9jGAZM44gz2aHvYIyG0YriGMUIMDbD+4AY/xBCgFAOVV2/YLd7wNP+GaefJ2itISmxUrIkyQTvaIMvxGy9h3f2Mu8tJXfFj4ESdv0Z8zzRwAJbKgEpeqwpwFtdcEbBkc0brJFI4bru9O+YjKXDq9dmxudvO3z6+gNfvu/x9Dai6SW6OWD/xvBO/mvLcOwVOubxWHc40LibbLGHlqN+H1G3Ai8NRyWVhTIJTDqqAV0nbQQQV4DcG8oc4cnxYb3Exu26ZyvrlaWC013pXbGuqRQ4xXhT8Hu2jeL/8VRnUrU7nUjRHkou0KT2/8iCxKtA91TTObdGj5yYUztkGImU4YyBz5fxPI2lXbK/CE7jCYLaKMdnP7eZkpJqSC2SFV4TKRdJ4XBHdMVGbwo383+hajqB5yOdsoSLog19nUpoe4FjO+HQnDEKj1nGD1EJaTHMBtoDI3eU2MMEQOgILj0mYbGYFfQTfIhfJppPWo6vLYgAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Staging data initial&quot;
        title=&quot;&quot;
        src=&quot;/static/012c072d2aec9310f335fcb526b53836/8c557/StadingDataInitial.png&quot;
        srcset=&quot;/static/012c072d2aec9310f335fcb526b53836/4edbd/StadingDataInitial.png 175w,
/static/012c072d2aec9310f335fcb526b53836/13ae7/StadingDataInitial.png 350w,
/static/012c072d2aec9310f335fcb526b53836/8c557/StadingDataInitial.png 700w,
/static/012c072d2aec9310f335fcb526b53836/82b28/StadingDataInitial.png 931w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Check the infolog for detailed processing information, reprocess messages if needed, or open the created Sales order.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/155896194b4fd520dcfe876ca828462b/ecf19/CreatedSalesOrder.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 70.28571428571428%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACdklEQVR42l1T2W7cMBDz//9Un1sUfWgRBGmwWXt3fR+SJd+WzXJmkTzUAK1jRhLFoaJp3mCshzEWVd2haRq43qJuDWExDB55nuN+u8FaA9N1zLcoiwLWGDwed41ve2DugEh+zvfYtk2x77sG5nniBpbtjHVdtF2WRWOau64IIXzNb9uu/cj2HnXd6uneOwzew7leWRZFrkxk7J1D1zaoylKZub5/rtHcHj0Pl5zocknw/n5Bcr0iSRLciJj9LH2QxYJ1mTBPo2Ih63WZtX2Ox6/YJ6Kms7BkMzFxGEey9MSAUa7GDQX7xuvt29dYEIJItPyXs/PKVY2KbHzb4uTEcR7UcWMw4DgOxTxNmAjpnxIPT52llXzBQv30ysmv34hfXtG8vWGmPis3TQtW20wY55UbjVrFLMsxU3z5XJYieXlBEyeY6hpTmqJtSKyqENVFjTqvMFDwwMpJxa7XD+RZhr5/VlkSy7KgtQwOcQEPkDmx0MzrLrSaZ4FEsqjjZMlrO2on3zgOSOmtuipZOaMMm84jK6m1mzTHs/Ll5YKezBw3n8UJarEJkZRbNhUrfHpRAlJJKcxK1o52EnaW9jjPU/0nHpXb7OzLJwfLI4gChRWhnzgp8MkW4B/yl4Gan4KLGwILI0ZPya4W/VgsIfG43ynVFZEkGlpnXVnZcOjp27oTHB8nKx4UEpMqC6OgOPVVydzzkE0ZR8bNKNsJaeVR5AZ/frzi72uM6uOBe873bRYYvyOvHIpmgB0D8wfcMr6kZkRRe43lbGUcdf2Mtl9QE13j8P3bT1zeYnQfMS5xjpr2McOuC1q36oaab2TdiqobNEfQ2AX/AKx4MKwgwlPgAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Created sales order&quot;
        title=&quot;&quot;
        src=&quot;/static/155896194b4fd520dcfe876ca828462b/8c557/CreatedSalesOrder.png&quot;
        srcset=&quot;/static/155896194b4fd520dcfe876ca828462b/4edbd/CreatedSalesOrder.png 175w,
/static/155896194b4fd520dcfe876ca828462b/13ae7/CreatedSalesOrder.png 350w,
/static/155896194b4fd520dcfe876ca828462b/8c557/CreatedSalesOrder.png 700w,
/static/155896194b4fd520dcfe876ca828462b/ecf19/CreatedSalesOrder.png 948w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h3 id=&quot;running-an-incremental-load&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#running-an-incremental-load&quot; aria-label=&quot;running an incremental load permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Running an Incremental Load&lt;/h3&gt;
&lt;p&gt;To test how an incremental load works, I&apos;ll create a new order in my web application using a new account (&lt;strong&gt;ACCT-004&lt;/strong&gt;) that doesn&apos;t yet exist in our mapping setup. I&apos;ll also update an existing order (order number 95).&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/177c286ffe92927a1eaf5bff6078d839/ef916/CreatePOnew.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 38.285714285714285%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABVElEQVR42o1STU/CQBAtCfz/E3/AkyfXxETxQm+cCFhs+JCCbcWmRVr6vYVu+5xWCCom+JKXNzuZzM68XUlVVSiKguHTEMpoBFV9rtXzPERRhDAMTwwChJwLoWnwBoOuRIAkNQA0pCN4whFuQ6S7HURZQoicKM5YFAXSNEUQxwKGgdQ0/274tl3h9UNH6fsA57iEsizFQeW6IdDq9/stWZabFDel+0Vn+mjJs7Qrz/xeb0bJSxwTVzTx1aHhaboKkRvdGS/6zVhfsk0csygImO/7TNM0NplMmOM4jLxkAeWXiwUjv5nrurdxHF9Trk3afl/b7fl8XsfVDUiSpPi9WuVXlmU/clRXk/OsWhnllwmwd4Cp24ChQbJtG6Zp7g3DEJZlVf6IyqeyKL70G2lN4lFFVZtn02kePnRyOuTI97nkrNf0ikVBa55N9B/sNhvk9EOO+AQkgSYFuFYDJwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Create new PO&quot;
        title=&quot;&quot;
        src=&quot;/static/177c286ffe92927a1eaf5bff6078d839/8c557/CreatePOnew.png&quot;
        srcset=&quot;/static/177c286ffe92927a1eaf5bff6078d839/4edbd/CreatePOnew.png 175w,
/static/177c286ffe92927a1eaf5bff6078d839/13ae7/CreatePOnew.png 350w,
/static/177c286ffe92927a1eaf5bff6078d839/8c557/CreatePOnew.png 700w,
/static/177c286ffe92927a1eaf5bff6078d839/ef916/CreatePOnew.png 815w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;After running the &lt;strong&gt;Load messages&lt;/strong&gt; job again, you&apos;ll notice two new records in the web staging data:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;One record will show an &lt;strong&gt;Error&lt;/strong&gt; status because we haven&apos;t set up mapping for the new account (&lt;strong&gt;ACCT-004&lt;/strong&gt;).&lt;/li&gt;
&lt;li&gt;Another record will reflect the updated details for order 95.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Additionally, the system automatically removes the sales order (&lt;strong&gt;001035&lt;/strong&gt;) linked to the original message, as it has now been replaced by the updated data.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/f68614642b4206c604bd007f24b9b624/525d3/SecondRunIncremental.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 47.42857142857142%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABhUlEQVR42lWR2XKrMBBE+f9PS9V9SiqpVDbbGJAEQgLtLO6MZMfJfTh0z2ig1EPVDTMa1kNITUxohQTrR3REIwaIcYKyAXKyGLTFHFaYO8vdjybhLBOqc33Cx/sbOO+wpIhtXbAt8cqaSFPxa8qEG/F3pvA7U41SQQ8DojWERXIGKXisNBCcRfAZhxRD0dzPxODu5H6kd7Kv6tcjnh/+4fD8is+nFxwfX3BqBoqw4tAocGnRcopN9Vct8Hlk4IPFsZFU9zicezCqM62YUVltoHgPRfuSTGAaRhgX4dMOH1ek9YK47Fg2wPkFk/FwtDMft6KWevk8pMyGypgZWmuEELDQ/hLtI+Z4JcI1pndXcp2j5T3jsuNC0OOmVO/0QcFafH28o6lrCM7A2gacdejJd+RZ10JQXXpCFOXsp8fuZ5zmJq1QKT3B0c/w9APMnL0pWLp5xucbEs7Z223tf7g/5FRVKwxObIZyO1parLIb+Ohx6hSYdNAe1NvLedEfT+gbuafdpeg3Ks6xRS9m+TsAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Incremental run&quot;
        title=&quot;&quot;
        src=&quot;/static/f68614642b4206c604bd007f24b9b624/8c557/SecondRunIncremental.png&quot;
        srcset=&quot;/static/f68614642b4206c604bd007f24b9b624/4edbd/SecondRunIncremental.png 175w,
/static/f68614642b4206c604bd007f24b9b624/13ae7/SecondRunIncremental.png 350w,
/static/f68614642b4206c604bd007f24b9b624/8c557/SecondRunIncremental.png 700w,
/static/f68614642b4206c604bd007f24b9b624/e996b/SecondRunIncremental.png 1050w,
/static/f68614642b4206c604bd007f24b9b624/525d3/SecondRunIncremental.png 1090w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;monitoring-and-error-handling&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#monitoring-and-error-handling&quot; aria-label=&quot;monitoring and error handling permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Monitoring and Error Handling&lt;/h2&gt;
&lt;p&gt;For any integration, it&apos;s essential to monitor each step and have a clear plan to handle potential issues.&lt;/p&gt;
&lt;h3 id=&quot;connection-errors&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#connection-errors&quot; aria-label=&quot;connection errors permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Connection Errors&lt;/h3&gt;
&lt;p&gt;If Dynamics 365 Finance and Operations (D365FO) can&apos;t connect to the specified API, an exception occurs. This exception stops the &lt;strong&gt;Load messages&lt;/strong&gt; batch job, and the batch job status changes to &lt;strong&gt;Error&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Another common issue is when the &lt;strong&gt;Load messages&lt;/strong&gt; batch job isn&apos;t running at all.&lt;/p&gt;
&lt;p&gt;You can detect both situations by setting up an alert on the &lt;strong&gt;Last Date Time&lt;/strong&gt; field. If this timestamp is outdated, it indicates a problem.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/a8dd3e37c53f17f41f93b47fec23c3a8/99072/LastDateTimeIssue.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 62.28571428571429%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAA7EAAAOxAGVKw4bAAABqElEQVR42pWTy3KcMBBF+f8vSmWbRXZeZOOkZuLMwzDDgASSeAghuLktyhOvPE5X3RI0zeluqZXV2uL5YOCcg7UOrbEwpkXbtjDWoqP/UuT4vd8hz1+h6gq3sqSusMZgngPCNN2VNY3mhwZTCOj7PoHjsiDGmJ4nBglEgNdLgdPxgNfzOSUZ+g7OGoL8XZlUY1kJ1hXjMBBKYAzUjDlMdC/QqibswjiTQHV1g9YKDSUJ/DggMFbis0upsftToHEBmrpWNqlUHUy/oPMrpAuR2MLqVyaX9lI37ERMEsu3TDUd6nbiz/zRRT57aBsI7NPqBgG2OOclRj/dAX3X4Xg4pO4GdjZzy8SyyXt8ZJLVEzT4hW3FBJQKx3FEwfaVUqiqKr0noB834JrKRgre1s0Xl3jP/t4ELIf4pvA/FcpofNYeA1mJxGyV/1NKFGW8tsN4O6yHQDm9zlkeTIOGwz7Pc2pXAEzHNaakIvF/Arjy5hicTse0+VKRWPGS4+uXJ+x+/MJ4uyIovY3NQyCDBm66jIeA5RbRiWJ3xLfvP7F/3kPxBrk8xxoj/gJBJqTdmRlTtwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Last update date&quot;
        title=&quot;&quot;
        src=&quot;/static/a8dd3e37c53f17f41f93b47fec23c3a8/8c557/LastDateTimeIssue.png&quot;
        srcset=&quot;/static/a8dd3e37c53f17f41f93b47fec23c3a8/4edbd/LastDateTimeIssue.png 175w,
/static/a8dd3e37c53f17f41f93b47fec23c3a8/13ae7/LastDateTimeIssue.png 350w,
/static/a8dd3e37c53f17f41f93b47fec23c3a8/8c557/LastDateTimeIssue.png 700w,
/static/a8dd3e37c53f17f41f93b47fec23c3a8/99072/LastDateTimeIssue.png 842w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h3 id=&quot;parsing-errors&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#parsing-errors&quot; aria-label=&quot;parsing errors permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Parsing Errors&lt;/h3&gt;
&lt;p&gt;Parsing errors happen when the &lt;strong&gt;Load messages&lt;/strong&gt; job receives data but can&apos;t correctly interpret it.&lt;/p&gt;
&lt;p&gt;To monitor parsing errors, you can create an alert on the &lt;strong&gt;Incoming messages&lt;/strong&gt; table for records with a status of &lt;strong&gt;Error&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;When a parsing error occurs, the system creates a parent message containing the original data. You can analyze this data and forward it to a developer, who can then use the &lt;strong&gt;Manual load&lt;/strong&gt; function to troubleshoot and process the message.&lt;/p&gt;
&lt;h3 id=&quot;manual-load-function&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#manual-load-function&quot; aria-label=&quot;manual load function permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Manual Load Function&lt;/h3&gt;
&lt;p&gt;The &lt;strong&gt;Manual load&lt;/strong&gt; function is a valuable feature of the External Integration Framework. It allows you to process messages without connecting to the Web application. You simply provide JSON data as text, and the system processes it exactly as if it came from the API.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/90e997a9db954cead43e3cb2ea9f9466/e548f/ManualLoad.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 26.857142857142858%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAYAAABFA8wzAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAA4klEQVR42nWQ2W7EIAxF8///N/NeVWrVECBsYUs4Nammb2PJAow53Oul1UrrjTpXyVoLvTVC8Djv8Nagnk/Wx4PgPbu1NLmfMc6TUSpXyVxZUupLLkUeR2JK1NZJ6SDniheYUivWarZNoY3GWM9m/A28xiCtip+PT+JmSGbHfX2zpDJwsbEHgaSGP05mLaYo8CTwQz4Mt7osanLt9N5F3iALSBlLiJFzQDCOhTcxLR/H8X+eIznF4m11/NWmQq0Mu7bEmMni4C3wHoU0nZfMSQjT5gv4IlbnRKWmiMqijew3fgEpBIR5DDAMYwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Manual load function&quot;
        title=&quot;&quot;
        src=&quot;/static/90e997a9db954cead43e3cb2ea9f9466/8c557/ManualLoad.png&quot;
        srcset=&quot;/static/90e997a9db954cead43e3cb2ea9f9466/4edbd/ManualLoad.png 175w,
/static/90e997a9db954cead43e3cb2ea9f9466/13ae7/ManualLoad.png 350w,
/static/90e997a9db954cead43e3cb2ea9f9466/8c557/ManualLoad.png 700w,
/static/90e997a9db954cead43e3cb2ea9f9466/e548f/ManualLoad.png 975w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;For example by providing the following JSON data&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;96&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;purchId&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;PO-002&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;orderAccount&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;ACCT-002&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;updatedAt&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2025-03-12T02:58:18.641909&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;lines&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;172&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;purchId&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;PO-002&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;itemId&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;M0004&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;quantity&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;lineAmount&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;120&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We can create a new sales order, which will be marked as &lt;strong&gt;Manual&lt;/strong&gt; in the Messages table.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/afb40f6664dc334334e1cc7892de7e4c/d1d24/ManualLoadResult.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 48%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABpklEQVR42o1Sy47UMBDM/3/FCoGWL+CExJEzCLEzm0S7ycxuhpHjtxPbcaZoex4CBBKHUtnu7kqnqyulNJyzmOcJxmgYraG1glYKiuD9XM5aSUjBKddhWeJvSIR5DtDWo3rYbFE3LbgQiBSIMSAGT+yxlHMovMR4uwf6SEbOu3JGjleSMSTvgBSwkkikTpcS9PATdU7d+8lhJsQwE9tSmBYSmx38BYHqcqx6d/cB7+8/4e2bj/jy+SuGTYO6YzjKhMdOoBsMnl4k+h8Gr6PHpj3QXWCgc9uPeNoL1D0ruc+DRtV832L7bYPm4RFd3UIej1DaYD2dIJXBCaD5+MJpXcG5wOtwgLETxWnextK4JKybsa4nVFwKeuAQxIxzCjgqGsssJb1Fml02Lc8uGzSOY4H3nkw0mCg/m5jNXFNC1TY1dn0HQSK/IosJ+hDnrLhraQMyJmcv5vg/+HyuritRkq29FWYTbFkjVfhaeBX5F0hQl13KAlkwr0fuwtrz7yyXVQreX7oIN+G/oWr3Ckwl9AdHTlqMOmFPju4Ghd3hHGNqAaP3/8FPe2r97URtsHcAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Manual load result&quot;
        title=&quot;&quot;
        src=&quot;/static/afb40f6664dc334334e1cc7892de7e4c/8c557/ManualLoadResult.png&quot;
        srcset=&quot;/static/afb40f6664dc334334e1cc7892de7e4c/4edbd/ManualLoadResult.png 175w,
/static/afb40f6664dc334334e1cc7892de7e4c/13ae7/ManualLoadResult.png 350w,
/static/afb40f6664dc334334e1cc7892de7e4c/8c557/ManualLoadResult.png 700w,
/static/afb40f6664dc334334e1cc7892de7e4c/d1d24/ManualLoadResult.png 987w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;This feature is also helpful for testing different processing scenarios.&lt;/p&gt;
&lt;h3 id=&quot;new-load-function&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#new-load-function&quot; aria-label=&quot;new load function permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;New Load Function&lt;/h3&gt;
&lt;p&gt;You can manually start loading orders from the user interface by clicking the &lt;strong&gt;New load&lt;/strong&gt; button.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/38864cbdd6e8403a5b971c2184dcc0e3/b6e34/NewLoadFunction.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 26.285714285714285%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAYAAABFA8wzAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAA30lEQVR42n1Qy24EIQyb//+5qvc99VCpnQUGCM8Argftob0UyXIEwYl9iERY6yBJUEXgHg+Ic6itohG99805Zxj2fZ0WPuaN1pR9iqYLtS+MMXGE4OGcgUTPC8WcgyCzXqw31oRqg70iPj6fiDFhzIVTBmwofFtoFJyTgjFVBE6rXVFqR+HElOueHCQjbhQ6KOSE8/uE9xcKHeW3d8yU8PscuXQ87QXjAtwliKltO7lOeGnkgbsnEV11f5rcbnEbNQaDUfwRVDYJs0vEzaVw21q2/Tu7HcEYO0t9Cf53fgDrjYWMs3wu0QAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;New load function&quot;
        title=&quot;&quot;
        src=&quot;/static/38864cbdd6e8403a5b971c2184dcc0e3/8c557/NewLoadFunction.png&quot;
        srcset=&quot;/static/38864cbdd6e8403a5b971c2184dcc0e3/4edbd/NewLoadFunction.png 175w,
/static/38864cbdd6e8403a5b971c2184dcc0e3/13ae7/NewLoadFunction.png 350w,
/static/38864cbdd6e8403a5b971c2184dcc0e3/8c557/NewLoadFunction.png 700w,
/static/38864cbdd6e8403a5b971c2184dcc0e3/e996b/NewLoadFunction.png 1050w,
/static/38864cbdd6e8403a5b971c2184dcc0e3/b6e34/NewLoadFunction.png 1103w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;In the load dialog, the &lt;strong&gt;Transaction time&lt;/strong&gt; field is automatically populated with the last loaded timestamp. However, you can change this value if needed. A typical scenario for changing this timestamp is when you need to reload data from a specific period.&lt;/p&gt;
&lt;h3 id=&quot;handling-repeated-errors&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#handling-repeated-errors&quot; aria-label=&quot;handling repeated errors permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Handling Repeated Errors&lt;/h3&gt;
&lt;p&gt;Each time the system attempts to process a message but encounters a failure, the &lt;strong&gt;Processing attempts&lt;/strong&gt; counter for that message increases.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 660px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/24326e5ad8a33c8ea4cc93425fb68024/1f083/ProcessingAttempts.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 87.42857142857143%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAARCAYAAADdRIy+AAAACXBIWXMAAA7EAAAOxAGVKw4bAAACdElEQVR42qVUaW/bMBTz//9rW3c1bdemSRzHh2z5km85GTg+OR7aIQOG7cODng4zJEXFK4ITop2P5OBDs48PAdLjiRVAn0J0mUajUrRphk6K81ZlXJO5vs5TNEmKPivgDeOIyrRo2xbD0KPtLYwx6PsOTdtwvUFZFm6Uecf1uq5QFDlMY9y6jDK3doankhiPm294uL/H48MG+90rpmmCnUZX829lx2tvp/d7nNtxgFfkOY6+D5UoSK+ShOx6x/ZmyR5Z3lob2Xt9t8jtuo7SKpzPMzcGspvc+LYmsjvPlmys69d1mUtJ71X0Jzj6CKMYumwxz4vcqiwXWdcSoK41SOIIqUocmwV8hM5SKBW7c15dlQ4wjkJKzhx1AZSPGlO7QxO9kY9NXdKeA8JT4KzpqEz2daoQxyFaXo4DlANyMApPkPk09gjZa3oq/ogdMhrebnBczsWsIteOqajM2QsBzwhgcHSgmVLuo3EYaYGCzzxGMTPW9IzMgJQ5CwLfRcVeb1aYV8QoVsCGNEPKjeiNZKmhTwMBjwz29vmJbAL4hx1K7glgTlvkR+V2RYnYUZOhAEo+vez7E3afP+H17g6vHz+goHQJ+8t2x1w+Yr/fY7N5IMsWtaE8AtdVtUTnWgI6XsG99OsXKIIoBrqm7J7y53lGXlT0sCQrjZRPrDYdMl04r0sCitS13qbBq2hu8vIMtd3C8C0PcrM8dDlb/LjMv+rCfE70bZDsUYHkV0oYvgMsxVBqt2Q1X84u2O4ZyfNbx7W3S0an9endKC/Xqcuc/NJ5fZ9/OPw35QCzNHZ5Eu/sf4AtHlY1TpFGnGj3L7O8y38H/AkGyhL6FOLCFgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Processing attempts&quot;
        title=&quot;&quot;
        src=&quot;/static/24326e5ad8a33c8ea4cc93425fb68024/1f083/ProcessingAttempts.png&quot;
        srcset=&quot;/static/24326e5ad8a33c8ea4cc93425fb68024/4edbd/ProcessingAttempts.png 175w,
/static/24326e5ad8a33c8ea4cc93425fb68024/13ae7/ProcessingAttempts.png 350w,
/static/24326e5ad8a33c8ea4cc93425fb68024/1f083/ProcessingAttempts.png 660w&quot;
        sizes=&quot;(max-width: 660px) 100vw, 660px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;When running the &lt;strong&gt;Process incoming messages&lt;/strong&gt; batch job, you can set a filter on this field to limit the number of times the system tries to process messages with errors.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 434px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/3152a5ef32ac8feb3966e77eb69d1e04/ade6e/ProcessMessageDialog.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 96.57142857142857%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB9klEQVR42p1U2XKjMBDk/39u99Hxg20wBiFAAgSYS3RmtECC493Eq6ouXVNztHrkDcMAxjRNGMcR657XDD5n/HR4Wmucz2fEcYwoinC9XhEEgUMYhjgej+6cxzzP3ztko53hst9grTv7cYb3+x1JIiCEQFVVi1O7d/oCPOZLaQVNKMoS/UA8jsynhbWvwzPtiN9vCr8OOQJhYNoJVWuhzPBKpR8lD9MMqSfE2YjmTlHIST/MtJ7wP4M4bKEygUJLaJUjuoVomnp71dc5JL6EapGXHUbis+s6pzu+XDW44pGvx3uGN9FFqgxEWrnMmqaBMRXqut6VsgYYx2mbn+nS44y4zDSVkFI6+TDSNN0Zqpwezb8gJOEzroFPNGlX0c4hZ/R2OEAmCfIsQ0bIsxRm1eQySpJUSgH5nFEb4xy2bfs1Q58i30JqOd93a0aeZ7t240CXyxllUaAhOpgSdtr3/d7hdzJYHXKAhPqdHWqlHLiilevVznVKUxv3IByxpjXPj9z86cjnLfml5ETmkJmiOcUtThARDEW2ZDz+QzabdHheQLKZkRQWsrQoGmq5eiZYzuevWTyjZRN233fEhURVEjc6dyU/DpZQQipgObEaBnqIfgGvOdOdbE6nk/tpuo4v99mwsRDx9uEyotvNfcQX+phZTp9f+h13X8tXRYFiVAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Process messages dialog&quot;
        title=&quot;&quot;
        src=&quot;/static/3152a5ef32ac8feb3966e77eb69d1e04/ade6e/ProcessMessageDialog.png&quot;
        srcset=&quot;/static/3152a5ef32ac8feb3966e77eb69d1e04/4edbd/ProcessMessageDialog.png 175w,
/static/3152a5ef32ac8feb3966e77eb69d1e04/13ae7/ProcessMessageDialog.png 350w,
/static/3152a5ef32ac8feb3966e77eb69d1e04/ade6e/ProcessMessageDialog.png 434w&quot;
        sizes=&quot;(max-width: 434px) 100vw, 434px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;This approach helps prevent the system from repeatedly trying to process error messages that no one is addressing, which could slow down overall performance. A good practice is to set this filter to allow several processing attempts. This way, temporary issues, such as a missing customer record, can be resolved automatically once the required data becomes available.&lt;/p&gt;
&lt;h3 id=&quot;canceling-messages&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#canceling-messages&quot; aria-label=&quot;canceling messages permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Canceling Messages&lt;/h3&gt;
&lt;p&gt;If a message can&apos;t be processed because it contains invalid data, you can choose to &lt;strong&gt;Cancel&lt;/strong&gt; it.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/b35f81f63aa85203276a0282b88afb62/02cd5/CancelFunction.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 35.42857142857142%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAAA7EAAAOxAGVKw4bAAABGElEQVR42nWQSW7DMAxFdf/Ltess0sZIGw+yrcGaZf+QalJ0kRJ4ICVS/BRFjBkhBKSc4ENqcXzgvUeMFMeI4AMcndXphOn9DXqeYd2GZV1QasHThJxG3L6/0Pc3aK1QSn5JJkGGBVjIUiP5eYG8dAhyhhsn8hLCGA1rLZxzNJ1vj1L6n8y+VqjrFf25Q3e+Yr5JrFJj/eggtHHYnKcpEioV8jT7Xn+p9J0nOedGIqxSyERcVyRmUUhaQ7Cqo4bHcbRiT5MWaswxC/D9D8C2be27pRQYY/DKxL7vLVkeDTSp8JnXwI+52dOsNW2HbJxrxvk/iFFlSBVg/A69FQzSYJwt3XkM5FcTYamHDQeGJWKxpdUqWtWrCe8mKx+zEGRPQQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Cancel message&quot;
        title=&quot;&quot;
        src=&quot;/static/b35f81f63aa85203276a0282b88afb62/8c557/CancelFunction.png&quot;
        srcset=&quot;/static/b35f81f63aa85203276a0282b88afb62/4edbd/CancelFunction.png 175w,
/static/b35f81f63aa85203276a0282b88afb62/13ae7/CancelFunction.png 350w,
/static/b35f81f63aa85203276a0282b88afb62/8c557/CancelFunction.png 700w,
/static/b35f81f63aa85203276a0282b88afb62/02cd5/CancelFunction.png 821w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The main goal of this feature is to ensure that messages don&apos;t remain in an &lt;strong&gt;Error&lt;/strong&gt; status indefinitely. Ideally, all messages should either be &lt;strong&gt;Processed&lt;/strong&gt; or &lt;strong&gt;Cancelled&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;full-traceability&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#full-traceability&quot; aria-label=&quot;full traceability permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Full Traceability&lt;/h3&gt;
&lt;p&gt;The system provides complete traceability, from the initial JSON message to the final Sales order, and from the Sales order back to the original Web request.&lt;/p&gt;
&lt;p&gt;Starting from the sales order:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 639px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/74e3ad4d34d65141ab7bc61093729ccf/738b8/SOStep1.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 33.714285714285715%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAAA7EAAAOxAGVKw4bAAABFElEQVR42o2R6W7DIBCE/f6vV+eqDyVuEje2wXZibvB0oVGk9leQPi3MwC4s2a68oj62OH81aE5HcM7AGcPQ92AEZwNG0qzRb5HtNh/Y77Zo22/UVY394YCqLJHnOcqywnazQfFZwFnzXsJhXCAFIQXWNSB4Tzis4TeGZ7RGvUXWszv49AAf71iEhlD2hTKecJA0l9r9QdsAQ/zXs9O5xbGhPp4u4LMg0VMyT8ktYrHI9FCQZk168iR5w4yOiGtpAsTzXNZcR9zIWJb4dAljDOLQWqV+FkWBS9vS2tDzQ/Is7amo35F+GGCdg/chkXVdj1vXYZ4nKKXgyEyHKPakR6LOR/Yq5pzFNE1URKeLCCHSH8R9PxukGYIkZ95RAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Sales order step1&quot;
        title=&quot;&quot;
        src=&quot;/static/74e3ad4d34d65141ab7bc61093729ccf/738b8/SOStep1.png&quot;
        srcset=&quot;/static/74e3ad4d34d65141ab7bc61093729ccf/4edbd/SOStep1.png 175w,
/static/74e3ad4d34d65141ab7bc61093729ccf/13ae7/SOStep1.png 350w,
/static/74e3ad4d34d65141ab7bc61093729ccf/738b8/SOStep1.png 639w&quot;
        sizes=&quot;(max-width: 639px) 100vw, 639px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;You can view the staging data with parsed values:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/c0a4dbf115a97f1a28edbcbff4aa21e3/f941f/SOStep2.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 25.142857142857146%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAYAAABFA8wzAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAA+0lEQVR42kVP25aDIBDz//9uX7Y3q1VbakVABERBNzvSPduHnEkOk0zIrJshlYaxBtM0QQ8DBqXQdR2E6NH3PQTh1baw1sJ7j4F2pJTQWtM7x+RnhBARY0TGHjUu5xPyPEddVejaJ7SSFMITlBSEt/aTwzL7f4Rl/uidE7K9SVlWeDKGllo4arHGkLCtMc0YSBPfZwwLtVkS3wNj4ssnUEiNjkv6jsG2rRQQ/wwLnLN0fU7mibgZddpzzhEfU8De2pjxfYA8GeMOx+KF72uL8qFxYyOujcKde5xKjkstwccfHG8DDqVAwTTOjcCp7sFUQEGer0ND3gFVa/ELeBN9XF6DQO0AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Sales staging&quot;
        title=&quot;&quot;
        src=&quot;/static/c0a4dbf115a97f1a28edbcbff4aa21e3/8c557/SOStep2.png&quot;
        srcset=&quot;/static/c0a4dbf115a97f1a28edbcbff4aa21e3/4edbd/SOStep2.png 175w,
/static/c0a4dbf115a97f1a28edbcbff4aa21e3/13ae7/SOStep2.png 350w,
/static/c0a4dbf115a97f1a28edbcbff4aa21e3/8c557/SOStep2.png 700w,
/static/c0a4dbf115a97f1a28edbcbff4aa21e3/f941f/SOStep2.png 736w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;And also, access the original message with the attached JSON payload:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/3ccef1e73c7a5640de07458ff810783c/d9217/SOStep3.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 37.714285714285715%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABYklEQVR42nVSXU8jMQzc//+3eAckoOVUDkoBtc1uutskdj6Xwevq4OHEw2gse8ZRbHfOB6QYMZ0D3PkM7xxcCJi2W6RxAktttFZr48mCOaLUivoLuvVqhcfHNfb7vTRmcPCItWC6ucZ4dYUkMQUnjQKYgmpyir+iO0gjOwyYpgnEpCaSppQTgncaMxEiy2Nav4BCuMQh/Hgk7kw/oOaIWpK8wJhbuaDmb7QSkdirLkdCUf0lVxKrr82zarun1x5mLHg/emxeDsofxuPt4DRv3Yz9kPDwt1f+MEE44mAz1pLb7E54fnqHvdtgEG0X8yc4zYjlEzHPoNgQuCootW+w6Ejq/A+Si028FSAvi7u+VU93lBn2vUF/NMonO8i8CE2WUUr+D3XhlCB9wOsVaPNH49Ka1jtj5MvGYJDFjOOI83I6fhkwKbMsw8tpeecRZOhOzipI3sv5DPf3sLsdltOjxUOELxK+ZoUAN534AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Sales message step&quot;
        title=&quot;&quot;
        src=&quot;/static/3ccef1e73c7a5640de07458ff810783c/8c557/SOStep3.png&quot;
        srcset=&quot;/static/3ccef1e73c7a5640de07458ff810783c/4edbd/SOStep3.png 175w,
/static/3ccef1e73c7a5640de07458ff810783c/13ae7/SOStep3.png 350w,
/static/3ccef1e73c7a5640de07458ff810783c/8c557/SOStep3.png 700w,
/static/3ccef1e73c7a5640de07458ff810783c/d9217/SOStep3.png 904w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Each of these steps can be performed without direct access to the Web API in a development environment, either by using the &lt;strong&gt;Manual load&lt;/strong&gt; function or by manually changing the status of individual messages.&lt;/p&gt;
&lt;h2 id=&quot;resources-for-this-blog-post&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#resources-for-this-blog-post&quot; aria-label=&quot;resources for this blog post permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Resources for This Blog Post&lt;/h2&gt;
&lt;p&gt;All resources mentioned in this blog post are available on &lt;a href=&quot;https://github.com/TrudAX/XppTools/tree/master/DEVTutorial/DEVExternalIntegrationSamples&quot;&gt;GitHub&lt;/a&gt;. Let&apos;s briefly review what&apos;s included and how you can use these resources as a starting point for your integration projects.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 458px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/b51ff0e1ea1b2c9b8d0ee46aa7a34f1a/f7a31/ProjectStructure.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 104.57142857142858%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAVCAYAAABG1c6oAAAACXBIWXMAAA7EAAAOxAGVKw4bAAADcUlEQVR42n1UyZKjRhTU/3+LD77MxXb0OCY8dk8vbrUWkNhBrGJHQgJt6axCmu6JcI8iMqqAIpXvvUxGWbGB5cZ4fJrg8XmCf1/nmCkaxhMFr9MFpooO3XShLm1Mpku88PlkrvHawutsiTnPTua6fGfGs6PdrkNT14gDH54XYEXUzRaHwwmXywW337stLleI3/nythdnRl/HBb5NS3z+Z4lfPj3j090Cv/42k/j9q427bx4+E38++ri7d7kGeFAaPC93RHtd3zDS/T00p8L90wx/fJng7ycTfz3o+HKvyf1MT6EYBRZ2BdUsoFolrKCDHfUSVti9Q4/R4TgInk8neHl5RRyt4dguXM9n+T4iXodhgjhJkcQpAj9CFCe8n/B+hK4/DKWfgRMxatojqqpBGoWYqQb8MEVRtsirFgWRl1uihRjeOq2RZkTO8zmvuS+qnTxf1nvsuguH0p3RH4F4zXIWOjTNgUJidWlC4eTEfqnZMK0VVWVYBQlB1XEOn2vAeyGRrMs3Qg6UZeQkWEI3PCxoEYNWWdAaglA3HDheiHZ/xIkdEgJu6A6X6wrs+/cKk5wEgxpBonGVKoVC3Zakpr2SipptL18W7+4Jse7680C4YQ9r9jAJV5irJjTdkUbWdZdtKNmbnUTV7GVPBSQRX/4/SIUd2b3Ak4oM06MikhouLCeA44ZwVxEsqjN4TwyiZ4s+Iv2ucB0FmMwYqcWgUvRPkOXVVk64P55ln26lfahwzwOi0Q5ViKGoCwtTZlRVdUyZ5fFYwfhV4VAiDuX0U7JB4e7ELG+Y5RUWtExONaJfA3ao6y2fb+nVrXxBTPWnhFv+a7vrEYXxUCaV2Cx15SeDz0Qy+CwIYvbRp6FriHD1V7vcrPNGKBTy65IlMW3hS9vMWa4gzYoGWZqjyEtkWSWnLlJym3YpUkLlm/aA/ZV01O7PaNsOabKGYfnSa0sqNbkXCfCZjIQpCqNUXotECeU3uKxIRE8am5OXCjdNi6oooCwMOWFFHQwd0ewCIlYiSYI4ijOpVPSXg5cp638s+ShLLtKU5Q5DKVmOeEHYRX4IskbuBXGSFkQly/2elh9s051wZJct08HD4xg2zWxfDS3NTKN7LMtyfDmUejMo+2jao46EJ8oOWYrGzIphiLIlmeVx73IdiMXXJ4hydMePk/IfUd4kjj/FFuQAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Project structure&quot;
        title=&quot;&quot;
        src=&quot;/static/b51ff0e1ea1b2c9b8d0ee46aa7a34f1a/f7a31/ProjectStructure.png&quot;
        srcset=&quot;/static/b51ff0e1ea1b2c9b8d0ee46aa7a34f1a/4edbd/ProjectStructure.png 175w,
/static/b51ff0e1ea1b2c9b8d0ee46aa7a34f1a/13ae7/ProjectStructure.png 350w,
/static/b51ff0e1ea1b2c9b8d0ee46aa7a34f1a/f7a31/ProjectStructure.png 458w&quot;
        sizes=&quot;(max-width: 458px) 100vw, 458px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The main components are:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;A &lt;strong&gt;Load class&lt;/strong&gt;, similar to &lt;a href=&quot;https://github.com/TrudAX/XppTools/blob/master/DEVTutorial/DEVExternalIntegrationSamples/AxClass/DEVIntegTutorialWebSalesLoad.xml&quot;&gt;DEVIntegTutorialWebSalesLoad&lt;/a&gt;, which connects to a custom API.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;Processing class&lt;/strong&gt;, &lt;a href=&quot;https://github.com/TrudAX/XppTools/blob/master/DEVTutorial/DEVExternalIntegrationSamples/AxClass/DEVIntegTutorialWebSalesProcess.xml&quot;&gt;DEVIntegTutorialWebSalesProcess&lt;/a&gt;, which contains the logic for processing incoming data.&lt;/li&gt;
&lt;li&gt;Tables and forms to manage staging data.&lt;/li&gt;
&lt;li&gt;A mapping extension to implement mapping between Web application and Dynamics 365 Finance and Operations.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Once these components are set up, the External Integration framework will automatically handle the rest of the integration process.&lt;/p&gt;
&lt;h3 id=&quot;sample-web-app&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#sample-web-app&quot; aria-label=&quot;sample web app permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Sample Web App&lt;/h3&gt;
&lt;p&gt;For testing purposes, I&apos;ve set up a sample web app. At the time of publishing this post, it is deployed at the following address: &lt;a href=&quot;https://purchaseorderapp20240916.azurewebsites.net/&quot;&gt;https://purchaseorderapp20240916.azurewebsites.net/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The source code for this sample web service is also available on &lt;a href=&quot;https://github.com/TrudAX/TestWebService_PurchaseOrderApp&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;summary&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#summary&quot; aria-label=&quot;summary permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Summary&lt;/h2&gt;
&lt;p&gt;In this post, I&apos;ve explained how to implement a complex document integration from a REST API web service into Dynamics 365 Finance and Operations using the &lt;strong&gt;External Integration&lt;/strong&gt; framework. We covered these key topics:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Designing an integration solution.&lt;/li&gt;
&lt;li&gt;Examples of querying a Web application and creating sales orders in Dynamics 365 Finance and Operations.&lt;/li&gt;
&lt;li&gt;Monitoring and troubleshooting common integration issues.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I hope you found this information helpful. If you have any questions, suggestions, or improvements, please feel free to reach out.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Optimizing Your Legacy Dynamics AX System(AX2012, AX2009, AX40)]]></title><description><![CDATA[Optimizing and maintaining a legacy Dynamics AX system can be challenging. This guide provides actionable steps, from technical audits to performance monitoring, helping you keep your system running smoothly.]]></description><link>https://denistrunin.com/ax2012-howtosupport/</link><guid isPermaLink="false">https://denistrunin.com/ax2012-howtosupport/</guid><pubDate>Tue, 19 Nov 2024 22:12:03 GMT</pubDate><content:encoded>&lt;p&gt;If you’re still running Dynamics AX 2012, AX 2009, or AX 4.0, maintaining efficiency is essential, especially if an upgrade isn’t planned. In this post, I will provide a structured approach to managing and optimizing such systems.&lt;/p&gt;
&lt;h2 id=&quot;perform-a-technical-audit&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#perform-a-technical-audit&quot; aria-label=&quot;perform a technical audit permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Perform a Technical Audit&lt;/h2&gt;
&lt;p&gt;The first step of system maintenance is to check that your system is configured properly and has no critical issues. To do this, you need to perform a Technical audit. The process has two primary parts. First, gather user feedback about their main pain points using a &lt;a href=&quot;https://github.com/TrudAX/TRUDScripts/blob/master/Performance/Jobs/PerformanceProblemsTemplate.xlsx&quot;&gt;structured format&lt;/a&gt; and resolve these issues.&lt;/p&gt;
&lt;p&gt;Next, validate the system’s configuration against best practices and make necessary adjustments. These steps are covered in more detail in my articles  &lt;a href=&quot;https://denistrunin.com/performance-audit/&quot;&gt;Dynamics AX performance audit&lt;/a&gt;, which discusses what should be checked and  &lt;a href=&quot;https://denistrunin.com/performance-projmanage/&quot;&gt;How to manage a Dynamics AX performance optimization project&lt;/a&gt; about how to organize this project.&lt;/p&gt;
&lt;p&gt;It’s important to involve upper management, as changes in legacy systems often involve risks that require approval.&lt;/p&gt;
&lt;p&gt;The technical audit&apos;s goal is to achieve a stable and well-configured system that meets best practice standards. This will provide users with a smoother experience and ensure the system operates within acceptable performance parameters.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 559px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/6746c8bb5c634634f57175721b24ef57/a65ce/PerfResults.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 17.71428571428571%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAIAAAABPYjBAAAACXBIWXMAAAsTAAALEwEAmpwYAAAA8ElEQVR42hXIzUrDQAAE4DyVBxEFT15brYhPI+ihoKBtxGeo1zXdbJqzmEg3f5vsT7IpsbZIemibrZKr22EYPsZQh7fbg5vN0d2mZ6oLs+kNVWfQXD3vfWmq7nCn/+sXdfbQdAfrzuP6/Kk9vW+P++1J34gzEibxNAyDKCJZpk3oflNGgyTSppxGJEkoS2nqfXrv3sfPqm7+dttfZXDOGeeU0rwoOGN5nlPGdPNCVlVVSDkrJReCCS7LUgjhef7XfF6v6u/lwoAQ6bwBAG3kTJzxGEJoT7QcpGVZluu6AIDX0chGKE4IxjgIwinGvu//AzJ5tUdOKvV+AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Perf results&quot;
        title=&quot;&quot;
        src=&quot;/static/6746c8bb5c634634f57175721b24ef57/a65ce/PerfResults.png&quot;
        srcset=&quot;/static/6746c8bb5c634634f57175721b24ef57/4edbd/PerfResults.png 175w,
/static/6746c8bb5c634634f57175721b24ef57/13ae7/PerfResults.png 350w,
/static/6746c8bb5c634634f57175721b24ef57/a65ce/PerfResults.png 559w&quot;
        sizes=&quot;(max-width: 559px) 100vw, 559px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;perform-regular-system-monitoring&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#perform-regular-system-monitoring&quot; aria-label=&quot;perform regular system monitoring permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Perform Regular System Monitoring&lt;/h2&gt;
&lt;p&gt;After stabilizing your system, it’s vital to conduct regular monitoring to catch and resolve issues early. Windows provides plenty of counters for monitoring, but it’s important to focus on actionable insights rather than just tracking metrics.&lt;/p&gt;
&lt;p&gt;For example, simply tracking CPU load isn&apos;t enough - seeing CPU usage at 90% doesn&apos;t tell you what to do next. In this section, I’ll outline key parameters that not only indicate system health but also lead to some actions.&lt;/p&gt;
&lt;h3 id=&quot;-database-size-monitoring&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#-database-size-monitoring&quot; aria-label=&quot; database size monitoring permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;-Database size monitoring&lt;/h3&gt;
&lt;p&gt;To effectively monitor database size, &lt;a href=&quot;https://github.com/TrudAX/TRUDScripts/blob/master/Performance/AX%20Technical%20Audit.md#database-size&quot;&gt;export the top 20 tables by size&lt;/a&gt; into Excel and use VLOOKUP to track monthly changes.&lt;/p&gt;
&lt;p&gt;In Excel, it looks like this:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/e2c67fb557d52191081a520e432e9c19/e2310/DBSizeCompare.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 25.71428571428572%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAYAAABFA8wzAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABVklEQVR42h2QzU/icBRF+1+7cuGWaDSoo2ZGUDHRoYmbmcTNOBLxA8QKrba0peXXgliB8iEQFm7OvMz25eS8e69Wq/3iyfjN+/sjy6VPv29g23+I1B2t+B7re5b+bYVk3OH+Vsd1/zKdvjKfNwnDMp5XQkV3uPY1L6UymmFkabcLfH7qzGY6aXqGaW3juQd4cR5vY4X0skRvbFE3tuh/FIUt/uejKI9p7tAKDvCdE1T1Ea1aNWk2lSScSbolw+GSRsOj5b8RdEe4P44Y3tzQS6dUHhp0uylJMmc0+pKEiQh92tGAwA4J9Au0Wi2L4xwK8FOq6CI8x7J28f1DWipPU99nYDj0BnUqlXU6nVPhikwmOnF8JOweQZjDfTkmuC6hmWZGjhmU+iaVC4zHOdlwnTDIohKB91YZXT3wMa3z/LSG7WxKkxyLRUGEu7LpljzZIVY54lebfxWdVe8D+T79AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;DB size&quot;
        title=&quot;&quot;
        src=&quot;/static/e2c67fb557d52191081a520e432e9c19/8c557/DBSizeCompare.png&quot;
        srcset=&quot;/static/e2c67fb557d52191081a520e432e9c19/4edbd/DBSizeCompare.png 175w,
/static/e2c67fb557d52191081a520e432e9c19/13ae7/DBSizeCompare.png 350w,
/static/e2c67fb557d52191081a520e432e9c19/8c557/DBSizeCompare.png 700w,
/static/e2c67fb557d52191081a520e432e9c19/e2310/DBSizeCompare.png 968w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The “Growth” column in Excel sheet will highlight any anomalies. This makes it easy to spot cases such as unintentional &quot;log&quot; activations, where a table may grow unusually and climb in the rankings.&lt;/p&gt;
&lt;h3 id=&quot;-long-queries-and-parameters-sniffing-monitoring&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#-long-queries-and-parameters-sniffing-monitoring&quot; aria-label=&quot; long queries and parameters sniffing monitoring permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;-Long queries and parameters sniffing monitoring&lt;/h3&gt;
&lt;p&gt;This monitoring type helps identify critical performance issues before users report them. Parameter sniffing can be visually illustrated by this image: operations that normally take 1-2 seconds to execute suddenly take minutes due to a poorly chosen SQL execution plan.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 430px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/4978cb9cb0141045b25d56f806abcdd7/05ed2/ParametersSniffing.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 64%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABw0lEQVR42n1TwY7TMBD1/3PkzBkuXJA4oaAFgTiAtEiAECva7m42TluSbZzEjp1k/Bi7jbZ0G0aa2LFn3sybGYvlYvHxJs3e3Ml1IqVMskwmZVEkZVmyFontXQJgVrXWiVIqIaKoAjNCHuhZMQzwRHNmGMcRdduiNQYMiABIxxokLF1P1Gqi90+fUPrpw+FupFN7Zy3lmw1leU6cLYkQ4Vj84dsOQNYQfr58ju1quT/1/sHusFeqglyvwaAwpsMjypNhdbvB8vUFhqsr+DNUJ7u6VhEwqHUOwvHnxDICfP+ywNfL2309/1PDcGeMhuYajuMAYXhzTl6tgIssusQGzYm1DnKzhWoNqkY/Bpx8n116fM5oSnpWOgbcMRA3EbW2EMd0/ANrvPjBtLeYBZyLIUJxJ4fJyHLjFzsgb/519Cdz6o+aE9YwMeJcwQc+uu+AdevPZrbkYN84e2aJruvQxYaMGPkRiIabfF1xNi3w+x5Ia+COM1N8/qsECgb+w2XWPSD5vOD9uxvg7fX+LjQlAPGA8wjV3BR+X4XmCx7kdOeQqvDvYfseOzNgtW0gKxfLkKsetSWE96K0i0H49US6gWmg/Bc50PFvjqFSrQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Parameters Sniffing&quot;
        title=&quot;&quot;
        src=&quot;/static/4978cb9cb0141045b25d56f806abcdd7/05ed2/ParametersSniffing.png&quot;
        srcset=&quot;/static/4978cb9cb0141045b25d56f806abcdd7/4edbd/ParametersSniffing.png 175w,
/static/4978cb9cb0141045b25d56f806abcdd7/13ae7/ParametersSniffing.png 350w,
/static/4978cb9cb0141045b25d56f806abcdd7/05ed2/ParametersSniffing.png 430w&quot;
        sizes=&quot;(max-width: 430px) 100vw, 430px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The monitoring process includes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A SQL Agent job, that runs hourly to detect new TOP SQL queries.&lt;/li&gt;
&lt;li&gt;Alerts when a query enters the TOP 3 resource-consuming statements.&lt;/li&gt;
&lt;li&gt;CPU usage statistics for the last 30 minutes to filter out false alerts.&lt;/li&gt;
&lt;li&gt;Storing the current execution plan and query text for analysis.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When a new query enters the top list, an alert email is sent with detailed information:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 543px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/affc2b1129d38618dde575db4ea80119/29579/QueryPlanAlert.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 37.714285714285715%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABFUlEQVR42pVSa2+DMAzM//9zG4MCKR/QoBLPhCAeAfG4xZZaaZXaaZZONnbk3F0Q8ppgmiZUdY22bdA0DUzfY3S9cRzQu9r0BsMwuO8R8zzjOA68ClHWFZRqobSCVhpN2/IF+75j2zbGeZ6/8C7EYmd3q8WyLFiXFcu6wlrLTKwD9f8TgiSRHMrPLO5cnhm+YyzIF/KNGGVZ9mD0l7TXkt0CYwx7pbVG13UPUJ+zQ0+187lzZ3rTOd81z5VSbBERoMcSrXsEGpBsauZ5jiAIEMcx5ygKcQljXCKJwOWA65jnnucxqJZSIkkSiPsvQJkWFkUB36dFER+KwhC+TPEhc3wlN3xebwiSb16SpimqqmLLyrJk/ACP+WYU3RtBjwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Query plan alert&quot;
        title=&quot;&quot;
        src=&quot;/static/affc2b1129d38618dde575db4ea80119/29579/QueryPlanAlert.png&quot;
        srcset=&quot;/static/affc2b1129d38618dde575db4ea80119/4edbd/QueryPlanAlert.png 175w,
/static/affc2b1129d38618dde575db4ea80119/13ae7/QueryPlanAlert.png 350w,
/static/affc2b1129d38618dde575db4ea80119/29579/QueryPlanAlert.png 543w&quot;
        sizes=&quot;(max-width: 543px) 100vw, 543px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;This monitoring takes some time to set up(initially, about 200 queries need to be analyzed) but allows the detection of complex AX performance problems. Full details can be found here: &lt;a href=&quot;https://denistrunin.com/performance-snifmonitor&quot;&gt;Monitoring the most problematic performance problem in Dynamics AX - parameters sniffing&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;-missing-indexes-monitoring&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#-missing-indexes-monitoring&quot; aria-label=&quot; missing indexes monitoring permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;-Missing indexes monitoring&lt;/h3&gt;
&lt;p&gt;Monitoring missing indexes is crucial for maintaining optimal performance. A daily SQL Agent job identifies the top 30 missing index recommendations with over 99% impact and sends email alerts.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/658139331acbeb50dc79a6fd43dce0b6/6c745/MissingIndexesAlert.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 26.285714285714285%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAYAAABFA8wzAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAApElEQVR42qVQyw6DMAzr///fOHIahT6g5dEiWoRXV2KHaactkpXEipw44tE0eHYdvHPoewmlFJZlwXVd+CWE0hrGGEzThHme4b3Htm3vAQrf+MZ9QpzniZxTQQbrf0OEENC2LYZhwLquxXZfMxcQvFhKCV2csD+Oo7oZxxHW2uqONcFaxBjrAP9GIZIUoX1X/spBXThTBMkR+74jpVQzey5iz2UvoF6EoXfAk0cAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Missing index alert&quot;
        title=&quot;&quot;
        src=&quot;/static/658139331acbeb50dc79a6fd43dce0b6/8c557/MissingIndexesAlert.png&quot;
        srcset=&quot;/static/658139331acbeb50dc79a6fd43dce0b6/4edbd/MissingIndexesAlert.png 175w,
/static/658139331acbeb50dc79a6fd43dce0b6/13ae7/MissingIndexesAlert.png 350w,
/static/658139331acbeb50dc79a6fd43dce0b6/8c557/MissingIndexesAlert.png 700w,
/static/658139331acbeb50dc79a6fd43dce0b6/6c745/MissingIndexesAlert.png 893w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;It consists of the following components:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;SQL Agent job that runs daily and emails TOP30 Missing Indexes recommendations with more than 99% impact&lt;/li&gt;
&lt;li&gt;In most cases, a new index should be created, but the script allows to define exceptions&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Detailed setup instructions are available here: &lt;a href=&quot;https://denistrunin.com/performance-monitormisind/&quot;&gt;Dynamics AX performance monitoring: missing indexes&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;-business-operations-performance-monitoring&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#-business-operations-performance-monitoring&quot; aria-label=&quot; business operations performance monitoring permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;-Business operations performance monitoring&lt;/h3&gt;
&lt;p&gt;This monitoring is used when you have critical business operations. It includes a Dynamics AX form to track operational details and a Power BI dashboard for visual insights.&lt;/p&gt;
&lt;p&gt;The Dynamics AX form:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Logs the performance of each operation.&lt;/li&gt;
&lt;li&gt;Records key data such as operation date, duration, and number of rows processed.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/77188cdf3a87b33a7f21e995f0195046/167b5/BusinessOperationAXForm.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 28.57142857142857%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABIElEQVR42m2QCW7CMBAA8/+/9UBQSoEQEkruy3biOOAwNRS1VYWlkXZnfe16z+sMpTpkN6DNiZOdMI7xAeYRZ8fJonpNFJd4yyAjyUrK7vSNGn/je150/9yd4u9eZYjrHk8rhRkG2lagtWZyr0ohEa3Eni1SyhvWWudalFSuI0Xfd4zG3M6prifc70mzHO9lnzE/VDxvY17dbxeHkqd1xDwqmO1TZmHOeypYJi1+M/JRdGzqgbekYRk3LBy17MnTlKqq8VZ+hB+mLFY7CjEgtOXq4kIQHkv8KCGpJMe8pbdQu/aluXB09au71qpGcF3TdMHb+iGHY8ouOFCUgqIWbPzAxS1xkhNEn5S1JHe5m78b/sgwTjdXNgqhNL02Pxd+AeAEx6/kUQFUAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Business Operation AX Form&quot;
        title=&quot;&quot;
        src=&quot;/static/77188cdf3a87b33a7f21e995f0195046/8c557/BusinessOperationAXForm.png&quot;
        srcset=&quot;/static/77188cdf3a87b33a7f21e995f0195046/4edbd/BusinessOperationAXForm.png 175w,
/static/77188cdf3a87b33a7f21e995f0195046/13ae7/BusinessOperationAXForm.png 350w,
/static/77188cdf3a87b33a7f21e995f0195046/8c557/BusinessOperationAXForm.png 700w,
/static/77188cdf3a87b33a7f21e995f0195046/167b5/BusinessOperationAXForm.png 776w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The Power BI dashboard helps detect anomalies and view performance trends over time.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 418px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/7065b69efd7da159a36e01b8784d3c27/d7398/PowerBIDashboard.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 79.42857142857143%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAYAAAAWGF8bAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACbElEQVR42o2UyW8TMRTG8ycjcULqtUhcQOKEeoGKC0IcKiQW0apUahpoaRO6JCE7nWyzZJbM6lk/nj1kUoU21JJnbMf+PX/ve5nSeDTGUBriWppgMplClhXwNU3VYFgWjLkNwzDgOC7WtSRJwBhDKY4j+EEM143ED9nNXSFD5q4HrbYSfzgE0w0GRAyxooC1WnArFVhHZQSDfh4oy+4LzDD3Eky7E3i7n+HUanD7PUSOg5Rk3IZZZd8MJm5oWgxT2f13M5/c42YzI1gBzkNMFS9nJOl/IZ4fI02Xe66HTnGETAnJTYaJ7K3NVZJkBUSb+Yh5YGp8rdu3CjElz7WhmyGksXMrcDFVCRKwRIxlUhNFaXHby4a+lMwCD4Nrm/r8DmA+H45deF4sxuOpS6WWiB5Qv6jPII0c4UUp8F2KHoiFuyRzub3fc1GvvJ1f5YBm26D82Tj8PsWPqooOSRemcCkzPXcqSZe5WrB1crF2oQl5LEzx+m0bOx/62HpVx/7hCNtvWviyL6FKe0QdxnFKic0ly5oP24kKmG1HAla71HDV1HF2rmJj8xgPN46w+fQMOx8HePCojBcv66icyChxiVzSSVWBReXT6VnkYgBF405maHVNHJ8q+HYq41fHJKAmDj9+VsXX8ghb2w28e9/Dk+c1fNqTcskc2Gyboh65Y/WmIW4tq77I10/qjZYBlYJwt/cOhiRxKNK0S+PRxBVvHkxIjugwdygvUlvAxT9A92GYrCgp3qIoQZ8M4k4vcp7XYCY6SU7FIBVmJJR4Roeyv5+jMAfPTKiKCo++PGEYUqlEtJfDQ1KSO8/X+Zk/NfDGpjV3n5oAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Power BI operation performance&quot;
        title=&quot;&quot;
        src=&quot;/static/7065b69efd7da159a36e01b8784d3c27/d7398/PowerBIDashboard.png&quot;
        srcset=&quot;/static/7065b69efd7da159a36e01b8784d3c27/4edbd/PowerBIDashboard.png 175w,
/static/7065b69efd7da159a36e01b8784d3c27/13ae7/PowerBIDashboard.png 350w,
/static/7065b69efd7da159a36e01b8784d3c27/d7398/PowerBIDashboard.png 418w&quot;
        sizes=&quot;(max-width: 418px) 100vw, 418px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;More details are here: &lt;a href=&quot;https://denistrunin.com/performance-operlog&quot;&gt;Implementing of Dynamics AX business operations performance monitoring&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;-batch-performance-monitoring&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#-batch-performance-monitoring&quot; aria-label=&quot; batch performance monitoring permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;-Batch performance monitoring&lt;/h3&gt;
&lt;p&gt;Batch job performance is a key factor in system efficiency. Using a Power BI dashboard, you can monitor the duration and performance of Dynamics AX batch tasks.&lt;/p&gt;
&lt;p&gt;Key features:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Analyse batch tasks by task name, server name, duration, start time, and company.&lt;/li&gt;
&lt;li&gt;Identify &quot;not enough threads&quot; issues, where tasks are delayed due to limited processing slots.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 699px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/b92cd1090afb4b49a89982f724773aef/3fe45/BatchByDuration.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 61.142857142857146%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB+ElEQVR42nVT227TQBD1lyB+oD/CX/CGhFAFfAhSP4CHipt4QC2CByRU0RaBVAKUKqRpESSQJnEubhzWjr3rXR/O2HGVhHalo50dzx7PzJn1tNbIsgxRHEMnCT4EQzzv/cGW38Gz3m9snrXwuNvGzqiPvWBwKfaJnbGPUzWF55yDrBnJknCKO/Uarr17hbX3b3Cjto/bR5/woH2CsdEIiLFOiz1YOcv3yGbwrLUlYZogJeG9xhdc332Nh8zM5A42L3945crzpeMFYZKmiMIQG60mtodd6HnmlhcEck3gFuzLzp70LyWZiiKMJuc4nU7mRK4MXsmgOl9JqEnoHE1mlFuW6NzSZcPvVmKInNVYY4q4isHRl8sdxortZSwzCAI0VIiT+C+aUYkGFfPZV1mKFQSsYEyE9IVzQSbENDMFQkIRXt7rY+PzR9w8OsD95iHWj7/iLnHrew1POTayvrVbWH/5Ak84So/o2xqcYZfjdcj2+OkM3SRGl/uIinvJcIi3v35AUfL/BSz79XPgY/u4jjoz78xiGGnPYm8rm7unOh1E/T40CbWz3EukhJEJYNA5S51l2dJlUb4S5EIYIZSPMYd6wl6K2tJgGXYZpyqLsCA0he0qlRcyzBd8xRzK6Bg+QSEUO+YzVEqVP2CQ+AQSa6hyta/65Bn/AyrKlB/T9KaXAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Batch By Duration&quot;
        title=&quot;&quot;
        src=&quot;/static/b92cd1090afb4b49a89982f724773aef/3fe45/BatchByDuration.png&quot;
        srcset=&quot;/static/b92cd1090afb4b49a89982f724773aef/4edbd/BatchByDuration.png 175w,
/static/b92cd1090afb4b49a89982f724773aef/13ae7/BatchByDuration.png 350w,
/static/b92cd1090afb4b49a89982f724773aef/3fe45/BatchByDuration.png 699w&quot;
        sizes=&quot;(max-width: 699px) 100vw, 699px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Additionally, batch jobs can be analysed by time of day, helping to identify patterns or peak load periods.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 573px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/d4afd31950a9b76bc05f0790828c3a50/3c024/BatchByTimeOfTheDay.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 49.142857142857146%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABk0lEQVR42m2S207DMBBE893AGx8CEkjcWgSon9EHoBeV8goIELQprdPYjj3M2ClFgkij3XjXZy9J0TQNJOccbF2jKRfwZQm/oP38hJ/NWjuHn8/zu+yiZG6ZcyXrEGJEIZi3FhVh9msJPxzCUm48hr29gxvQHwzghiNY2dGIGmc7mcDe36eYr6oMBB/vPazArGzOzrE6v4DpdGBOTmHoV1fXMNc3MN1LVLTSinnmooPl0TFzu2miQFYRQkhAxy7V7e8nsuKf9xCS76ZTlLt7iMslNk15xoqKrXrur+bIOvwN+rGtL4Vk89l8Zxe2388F2ND7wSEKgTYfJXVIRYE9rXzGI5OTr3jIcQGrXg/u8TEBG55pDUVqVSMLqETaIEAC0edIYbVCpPzrG14enmE+ShZ0iBxR+Sqou1rf9qPw0Lc7jP/sLEwf8LS3j+nkPYFSXMB2LWIEqlBnNWHr9TpVEWA7XsjjUmkFthYlj7xRuyatK3W4WbYkaN2CteTKGDjtmL7hyIbv+oF1lmKaSg3xju6K8Q0uqv7EYS/ugAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Batch By Time Of The Day&quot;
        title=&quot;&quot;
        src=&quot;/static/d4afd31950a9b76bc05f0790828c3a50/3c024/BatchByTimeOfTheDay.png&quot;
        srcset=&quot;/static/d4afd31950a9b76bc05f0790828c3a50/4edbd/BatchByTimeOfTheDay.png 175w,
/static/d4afd31950a9b76bc05f0790828c3a50/13ae7/BatchByTimeOfTheDay.png 350w,
/static/d4afd31950a9b76bc05f0790828c3a50/3c024/BatchByTimeOfTheDay.png 573w&quot;
        sizes=&quot;(max-width: 573px) 100vw, 573px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;While this approach may not be suitable for every customer(as there may not be stable load patterns), it may provide valuable insights about Dynamics AX batch performance. Read more here: &lt;a href=&quot;https://denistrunin.com/performance-powerbibatch&quot;&gt;Analysing Dynamics AX / Dynamics 365FO batch performance using Power BI&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;developing-new-ax-integrations&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#developing-new-ax-integrations&quot; aria-label=&quot;developing new ax integrations permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;strong&gt;Developing New AX Integrations&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Developing new system integrations may be necessary as business needs evolve. As many legacy AX modules, like AIF, are now outdated, I recommend using the &lt;a href=&quot;https://github.com/TrudAX/XppTools?tab=readme-ov-file#devexternalintegration-submodel&quot;&gt;External Integration&lt;/a&gt; module. Although designed for D365FO, this X++-based module can be adapted for older AX versions with some limitations.&lt;/p&gt;
&lt;p&gt;Using this approach, inbound flow integrations typically involve importing files from a shared directory. Outbound flows may consist of periodic or event-driven exports. Additionally, these can be enhanced with No-Code tools that handle file transfers to external services.&lt;/p&gt;
&lt;h2 id=&quot;maintaining-windows-and-sql-server-versions&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#maintaining-windows-and-sql-server-versions&quot; aria-label=&quot;maintaining windows and sql server versions permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Maintaining Windows and SQL Server Versions&lt;/h2&gt;
&lt;p&gt;Managing legacy Windows versions can be challenging. Dynamics AX components such as AX client and Application Object Server (AOS) often require specific Windows versions. To check which  versions are compatible, search for &quot;Dynamics AX [version] system requirements.&quot; For example, Dynamics AX 4.0 can be supported on Windows 2012 R2, which can probably be considered the minimum Windows version.&lt;/p&gt;
&lt;p&gt;SQL Server provides more flexibility. You can use the latest versions (e.g., SQL 2022 or SQL 2019)  in compatibility mode, which works really well with all Dynamics versions. Vasily Nosov also wrote an article about using the latest version of SSRS: &lt;a href=&quot;https://www.linkedin.com/pulse/how-install-ax-2012-r3-ssrs-extensions-sql-2022-you-really-nosov-dcvzc/&quot;&gt;How to install AX 2012 R3 SSRS extensions on SQL 2022 if you really want to&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;performing-data-cleanup&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#performing-data-cleanup&quot; aria-label=&quot;performing data cleanup permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Performing Data Cleanup&lt;/h2&gt;
&lt;p&gt;Data cleanup in Dynamics AX has two main activities: periodic cleanup for log-type tables and date-based cleanup for user data. Both processes can be implemented using a cleanup framework. Check this post &lt;a href=&quot;https://denistrunin.com/ax2012-sqldelete&quot;&gt;Implementing Dynamics AX 2009/2012 database &lt;/a&gt;&lt;a href=&quot;https://denistrunin.com/ax2012-sqldelete&quot;&gt;cleanup&lt;/a&gt; and some sample &lt;a href=&quot;https://github.com/TrudAX/TRUDScripts/tree/master/Performance/Jobs/DataCleanup&quot;&gt;implementations&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/e5dfdbf30a0a7adb0fe605eba1782665/5a6dd/DatabaseCleanupForm.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 26.285714285714285%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAYAAABFA8wzAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABRklEQVR42iWK2U7CUBRF+2d+i29+h3yCD0ZEwSFqVChtKSCdLgUCEUQIVRBxoBQ1TkGNvi6v+LCz1tn7KKZuo6dtjKxDNm2Rzbio0nVNoOllclqVvFnHLp3hWG1cq4vweghXxgvm7krW/IDxaIJyZZr0SgVGVY+h73JdEdy0HO5aglHT4aFV5+m8xVvQZdYP+Br2+Rxc8jG4mN8flxd8NdtEnTbP7S7KqW5SdAUly8MVVSy3jGX72I6P5ZSp1Bp4fhWzaOOICqJSQ9UMjo5V8icOQpTpHKQpHR5yruooYl8leVBkNZFhPZUjsVNgY7fA5o5Bas+UlN22QWJLZjtPPKkRl3/xlMHapkFeNHiKrfC6sMj70jLKNAiYzV54nE6IJiEP04hpFBGOx5Kyk/nz8H4sd+lh+N9Lj6SP5HabVPmOxflJZvkFu7FImjpYFkYAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Database Cleanup Form&quot;
        title=&quot;&quot;
        src=&quot;/static/e5dfdbf30a0a7adb0fe605eba1782665/8c557/DatabaseCleanupForm.png&quot;
        srcset=&quot;/static/e5dfdbf30a0a7adb0fe605eba1782665/4edbd/DatabaseCleanupForm.png 175w,
/static/e5dfdbf30a0a7adb0fe605eba1782665/13ae7/DatabaseCleanupForm.png 350w,
/static/e5dfdbf30a0a7adb0fe605eba1782665/8c557/DatabaseCleanupForm.png 700w,
/static/e5dfdbf30a0a7adb0fe605eba1782665/5a6dd/DatabaseCleanupForm.png 802w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The log-type table cleanup removes older data (e.g., over 90 days) and is usually run weekly.&lt;/p&gt;
&lt;p&gt;For user data, the process is more complex. Most regulatory bodies (tax authorities) require data to be retained for at least seven years, and legal records may have no retention period. The best approach is to keep seven years of data in the active database, perform long-term backups, and clean up top user tables annually to maintain stable database performance and size.&lt;/p&gt;
&lt;p&gt;The cleanup process is very customer specific, you will need to create a list of top tables and define rules for each table:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/8a17d3eef7b1692352c63bdf86076e7c/5caea/TableDeletePlan.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 46.857142857142854%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABjklEQVR42oVSa2+CQBDk//+yNsrDaIUir+NpVDgUUKvidHetTf1UksnBsjc3s3OGUgpVVWG32yHLMpRFCT8KsPA9uKGPME0QRxHyPJee7XaLpmlwuVxQFIVgv99Daw3bsmHg57ndbrherxjHEYehe5bRHXvotqVNLeq6IdREWKPrOpzPX9LD+/iJ6GDjfr/LBxP9JXzWm1YjTmKU5IKdVOs11gQm7vv+hTB8EjKeCnllwvE+SlOtG3ieB6VSscfW0zQjlVpsswBefxX+Z1mT1SzP0JJtTSQ8x81mQ3bP0s9iXiyvVis6tcDpdBJLHFIQh/ACH6rIkWQJ5vM5lq4Ll7An4uF4FFVlWSIIAgmFiZfLJQzTnGI6nSKOY/i+D8dxMJs5eHt/J2U5VJLAskzYVLdtR3pYBCv+pFGYpknEFQ6HAyaTCYxH5I3EzslxI2MYjo9QGp6hK2CyMAxFkdyAvhOiYRgeodA/g32rVMkdVCqRItvmFBlRFJJCS5TbtoXF4kNmxbPkPn5n2yyIFX4DWv2iQWZy5ZgAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Table Delete Plan&quot;
        title=&quot;&quot;
        src=&quot;/static/8a17d3eef7b1692352c63bdf86076e7c/8c557/TableDeletePlan.png&quot;
        srcset=&quot;/static/8a17d3eef7b1692352c63bdf86076e7c/4edbd/TableDeletePlan.png 175w,
/static/8a17d3eef7b1692352c63bdf86076e7c/13ae7/TableDeletePlan.png 350w,
/static/8a17d3eef7b1692352c63bdf86076e7c/8c557/TableDeletePlan.png 700w,
/static/8a17d3eef7b1692352c63bdf86076e7c/5caea/TableDeletePlan.png 996w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;One of the more challenging tasks is to delete records related to &lt;strong&gt;InventTrans&lt;/strong&gt;, which may require the creation of summary records and financial-related transactions.&lt;/p&gt;
&lt;p&gt;Another typical request is to delete inactive companies. This can be done with the following script: &lt;a href=&quot;https://github.com/TrudAX/TRUDScripts/blob/master/Performance/Jobs/deleteCompanyByList.txt&quot;&gt;deleteCompanyByList&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;summary&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#summary&quot; aria-label=&quot;summary permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Summary&lt;/h2&gt;
&lt;p&gt;This post covered essential concepts and actionable steps for optimising and maintaining a legacy Dynamics AX system. I hope you find these insights helpful. Don’t hesitate to ask questions or share your own experiences with system maintenance and support.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Practical Hints for Technical Management of D365FO Go-Live]]></title><description><![CDATA[In this post, I share practical insights from my experience managing the technical side of Go-Live for D365FO projects, focusing on key activities like delivering fixes, replicating production issues, and leveraging tools to streamline the process.]]></description><link>https://denistrunin.com/d365fo-goliveprep/</link><guid isPermaLink="false">https://denistrunin.com/d365fo-goliveprep/</guid><pubDate>Fri, 25 Oct 2024 22:12:03 GMT</pubDate><content:encoded>&lt;p&gt;Having recently completed several Microsoft Dynamics 365 for Finance and Operations (D365FO) projects,  I want to share a few practical hints that helped my team successfully navigate the Go-Live stage. These insights are based on real-world scenarios and are meant to complement &lt;a href=&quot;https://learn.microsoft.com/en-us/dynamics365/guidance/implementation-guide/prepare-to-go-live&quot;&gt;standard methodologies&lt;/a&gt; with a hands-on approach.&lt;/p&gt;
&lt;h2 id=&quot;environments-management&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#environments-management&quot; aria-label=&quot;environments management permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Environments management&lt;/h2&gt;
&lt;p&gt;In every D365FO project, Microsoft provides a single Tier 2 environment as part of the standard subscription. It’s important to name this environment correctly from the start—avoid calling it &lt;strong&gt;UAT&lt;/strong&gt; or &lt;strong&gt;TEST&lt;/strong&gt; and instead use &lt;strong&gt;PRE-PROD&lt;/strong&gt; (PP or PPN).&lt;/p&gt;
&lt;p&gt;A common issue is that, after Go-Live, business users continue using the &lt;strong&gt;PRE-PROD&lt;/strong&gt; environment for Testing purposes. This can lead to complications, as most post-Go-Live issues are data-related and can’t be reproduced in DEV you’ll often need a copy of the &lt;strong&gt;PROD&lt;/strong&gt; database to investigate these issues. However, the &lt;strong&gt;PROD&lt;/strong&gt; database can only be copied to &lt;strong&gt;PRE-PROD&lt;/strong&gt; before being distributed to other environments for debugging&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/a816634d4f14aa09958f69a90d03c2ab/a016c/DataFlow.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 29.714285714285715%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAIAAABM9SnKAAAACXBIWXMAAAsTAAALEwEAmpwYAAAA9UlEQVR42nVQa0/DMAzs//9PTBqgSUiITUWTgG5NX1maJk3SLUlLmwdp2eALnM6SJZ99tiN/g7XWORcSqVQKQFWVCKGqgnmeQwjnUii6RequLVF32uLsjiPACGMNCWwx7RAgxZoUGwohqTHFWFCmKMTFIy4feL1fXHzEmrRMX868CfPMNFkzOesHySHYVmA3KOmss8YGjrpr632dPxOUjONkjIn8Pxj1cDnr70N+4IzlWFxkL7pOCBG5G34V1vT8Q+Fdz14Vz4LzdZw8qTbuSTyI5FPree0/TJ2F6VN+uD++r2AWL++Zg+HD8W2VJess2WgpvfdfUmFUw8OxSywAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Data flow&quot;
        title=&quot;&quot;
        src=&quot;/static/a816634d4f14aa09958f69a90d03c2ab/8c557/DataFlow.png&quot;
        srcset=&quot;/static/a816634d4f14aa09958f69a90d03c2ab/4edbd/DataFlow.png 175w,
/static/a816634d4f14aa09958f69a90d03c2ab/13ae7/DataFlow.png 350w,
/static/a816634d4f14aa09958f69a90d03c2ab/8c557/DataFlow.png 700w,
/static/a816634d4f14aa09958f69a90d03c2ab/a016c/DataFlow.png 762w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The same rule applies to code deployments—before installing a new code package on &lt;strong&gt;PROD&lt;/strong&gt;, it must first be deployed on &lt;strong&gt;PRE-PROD&lt;/strong&gt;, which usually causes about an hour of downtime.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 570px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/5c4d55104901ae495822672ffc8f6189/432e7/CodeFlow.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 58.285714285714285%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAIAAADtbgqsAAAACXBIWXMAAAsTAAALEwEAmpwYAAABqElEQVR42oWSW2/TMBTH8/2/DPCAmASb0LrtASSKyLq0SZPl3sROYjvxNY5jTB8QRYIe/XTkI/3Pxcf2rF0d62qstWn6ut1u0zQNgiCKIt/3wyiMk+TFxftACGEvzfszUEoxxpznnDspF3wa8Nh2FCKQVfFuH/7YjW2/UKHQqBj3FjEa5ZiMokb9XdvpjFBWaY5Idjim+3CCgxGzpnKEvVel74+Ht+HLmyR811X3TZrXRVVnRZ0XWZygsnHXgsXX18MHUGyq5C493LTpk+YTRcQbwKbObvP4pso+geIRN3BdjJZqkbNDDmSdl77063hzih/r+OGUPNXHTRX5pMMew4SP2EExoWRaf0+8/jpKMtEeTcOIASLQgfEZAgen9+x/TVPeNE3X94SQAQ2Ms4ttr5dmLzurgfAOi4nOjLdF2ValUUoLsQipufx353OdmVBNmKGzZUvyHIXfA4W4HpXhyu3yytgLl25hqH4uj/cg/yLHYBV7CnZGa+Ke6kqykKs2qPx2ij/W8S3IPqPqASR3IN+jpruSPFPuvgcGPazargbOn2lQC0kLfwIYAKczJkIO1QAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Code flow&quot;
        title=&quot;&quot;
        src=&quot;/static/5c4d55104901ae495822672ffc8f6189/432e7/CodeFlow.png&quot;
        srcset=&quot;/static/5c4d55104901ae495822672ffc8f6189/4edbd/CodeFlow.png 175w,
/static/5c4d55104901ae495822672ffc8f6189/13ae7/CodeFlow.png 350w,
/static/5c4d55104901ae495822672ffc8f6189/432e7/CodeFlow.png 570w&quot;
        sizes=&quot;(max-width: 570px) 100vw, 570px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;If you name this environment &lt;strong&gt;UAT&lt;/strong&gt;, some users or consultants might think it’s a test area for them to play around with, leading to complaints when you have to restore the database and wipe their work.&lt;/p&gt;
&lt;p&gt;That’s why it’s crucial to establish from the start that the &lt;strong&gt;PRE-PROD&lt;/strong&gt; environment can be refreshed from &lt;strong&gt;PROD&lt;/strong&gt; at any time, and it should never contain any valuable data. This ensures that users don’t treat it as a permanent testing environment. The key here is to create a process where data refreshes and code deployments to &lt;strong&gt;PRE-PROD&lt;/strong&gt; don’t require formal approvals—just a quick notification to the team should be enough to keep things running smoothly.&lt;/p&gt;
&lt;p&gt;If your project involves ongoing development, I recommend having at least two Tier 2 environments: one for PRE-PROD and one dedicated to user testing, to avoid these kinds of conflicts.&lt;/p&gt;
&lt;p&gt;For more details on D365FO environments, you can check out my posts &lt;a href=&quot;https://denistrunin.com/performanceD365-tierperf/&quot;&gt;Understanding Dynamics 365FO different Tiers performance&lt;/a&gt; and  &lt;a href=&quot;https://denistrunin.com/devvm-perfv13/&quot;&gt;Development VM configuration&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;proactive-data-restore-process&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#proactive-data-restore-process&quot; aria-label=&quot;proactive data restore process permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Proactive Data Restore Process&lt;/h3&gt;
&lt;p&gt;During the first few days after Go-Live, I recommend proactively refreshing the &lt;strong&gt;PRE-PROD&lt;/strong&gt; environment with &lt;strong&gt;PROD&lt;/strong&gt; data at the end of each day(or in the morning). The main challenge is that certain data, such as integration-related or encrypted data, may not copy over or should not be copied during the refresh. To handle this, create an automated procedure to restore these settings. The key is ensuring this process doesn’t require significant manual intervention.&lt;/p&gt;
&lt;p&gt;Here’s the process we followed:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Run the &lt;strong&gt;PRE-PROD&lt;/strong&gt; data refresh from &lt;strong&gt;PROD&lt;/strong&gt; (for smaller databases, this typically takes around one hour).&lt;/li&gt;
&lt;li&gt;Execute a script that adjusts &lt;strong&gt;PROD&lt;/strong&gt;-specific settings to their Test values (in our case, it was an SQL script to modify integration settings, enable users, etc.).&lt;/li&gt;
&lt;li&gt;Perform a database export job for &lt;strong&gt;PRE-PROD&lt;/strong&gt; to LCS (which usually takes at least another hour).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This proactive approach offers a significant advantage: if an issue occurs on &lt;strong&gt;PROD&lt;/strong&gt;, there’s a high chance it can be replicated on the restored &lt;strong&gt;PRE-PROD&lt;/strong&gt; data. In such cases, a developer can restore the database from LCS and start debugging within 1-2 hours after the issue is reported.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 417px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/90096402952c9c864a534fa67739cfea/f27fb/ItWorksImage.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 54.85714285714286%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAC/0lEQVR42iWT7U+TVxjGnz9mybJ9ndEsizXEuYQxWRZnpi5qVDYy2gADhQxXy5higLmwKIoGhAiMCnsKfbEtpbRFCrVYLH1/efr0aXnRCYmf/Dp/O62fzsmdXNd9n/t3HSmllsiWtsmVdyjsvKL4ah/t332UrV0y2hb5okYsnmAzFiedy5Erlkln82TFmRWaij6llonnNdKiJiULGuFonPBmHIvdxYOH4ww9GMHpCxDNKOQLKgWlQDqToaCKu1aiqBaJp3Osx5LvDZUiijgjsQSS+vI17Z2/cPjIEWo+/4JPDx3iw48+xtjRjt8xRyxbqAoqr6g0r0yRLJQIuuxY7g8SiiaZkJ1sxNOMzbqQYlmFxiYDtbV1nL9wiRPfnUEnjMeud/ImKOMNBAj6Fwkt+4gkc7wQU1Q0yoqTtHyPVCJGc9cNGvRX6DT1I/01NMwnBw7S29tHaC1MxL9Ai8FAT0cbb8M2GhsNnLpoQJ63iT2phJ8/ZzUSRXnmRV22E1wLMTJhZmpyilBoDWl4dJzDuhpuDd7GsbCEbX6eySkzsm8Dn82Mvfs41y4eQ3YtCmB7pLVtYpsC0hMHe+UtlN09sf8UmaIAK0BKHq8XU89NnG4PzscjWGbMWOVZliJ5vOPd+No+YOnWWbzDdwkF/KRKO6x7PCSsc/DuP9TdfdY20+93q2hI1tlpfvxSR/up4/R8X0t/yyWG/hygz3SZSeNJVo0HuPfTUUyn65gdHSIj4GTFJM7gOv23R2j+tY/FYJi8qFWgSfZ5CyZDA5dP12P85jOGja209Azyw7mTDBjquNtUIxodo/vsVzyxPCa/+5qcVmba6sb19BmPZAfe1fVqbquGHv8KY54Ev3d1ca3+IA9/a2NiboGvzzSg1+tpqDuK8YQO07c67DOT5HaEYWmL8X8c5EWw/eEXTNvcqOJTVA3dKxsM/B3g5o1+ei/Uc//6VWTzDD83NdPaeoUOQyN/dOi5c7UFp8NGbvslURHqR2YZq3sJz/Iqo4JyOJaqhvx/DtKZFD46HJQAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;It works on my machine&quot;
        title=&quot;&quot;
        src=&quot;/static/90096402952c9c864a534fa67739cfea/f27fb/ItWorksImage.png&quot;
        srcset=&quot;/static/90096402952c9c864a534fa67739cfea/4edbd/ItWorksImage.png 175w,
/static/90096402952c9c864a534fa67739cfea/13ae7/ItWorksImage.png 350w,
/static/90096402952c9c864a534fa67739cfea/f27fb/ItWorksImage.png 417w&quot;
        sizes=&quot;(max-width: 417px) 100vw, 417px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;There’s also an option to automate this process further using &lt;a href=&quot;https://www.powerazure365.com/blog-1/lcs-api-database-movement-with-powerautomate&quot;&gt;LCS API and Power Automate&lt;/a&gt;, although we haven’t gone that far.&lt;/p&gt;
&lt;p&gt;If your database is large and the restore takes too long, first ensure there aren’t unnecessary &quot;log&quot; tables inflating its size by using [this script](&lt;a href=&quot;https://github.com/TrudAX/TRUDScripts/blob/master/Performance/AX&quot;&gt;https://github.com/TrudAX/TRUDScripts/blob/master/Performance/AX&lt;/a&gt; Technical Audit.md#database-size). Additionally, consider implementing tips from my post on &lt;a href=&quot;https://denistrunin.com/performance-restoretier2/&quot;&gt;speeding up BACPAC database restores from Tier 2 to Tier 1&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;timings-the-project-team-should-know&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#timings-the-project-team-should-know&quot; aria-label=&quot;timings the project team should know permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Timings the Project Team Should Know&lt;/h3&gt;
&lt;p&gt;When an issue occurs in &lt;strong&gt;PROD&lt;/strong&gt;, the first step is to investigate and try to understand the problem. If it’s still unclear, you’ll need to initiate a data refresh on the DEV environment. It’s important that everyone on the team is aware of the expected timings for this process. For example, if a normal data restore procedure is required, debugging can typically begin within 4 hours.&lt;/p&gt;
&lt;p&gt;Once the issue is resolved in the DEV environment, the fix should be deployed to &lt;strong&gt;PRE-PROD&lt;/strong&gt; (ensure the team understands how long this will take). After validation on &lt;strong&gt;PRE-PROD&lt;/strong&gt;, the fix will be included in the next &lt;strong&gt;PROD&lt;/strong&gt; release. It’s critical that the entire team knows the deployment schedule for &lt;strong&gt;PROD&lt;/strong&gt; to ensure smooth coordination.&lt;/p&gt;
&lt;p&gt;Issues are often raised by functional consultants working closely with key users, and having clear project timings in place makes communication and planning much easier for everyone involved.&lt;/p&gt;
&lt;h2 id=&quot;release-management&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#release-management&quot; aria-label=&quot;release management permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Release Management&lt;/h2&gt;
&lt;p&gt;Effective release management is key to ensuring a smooth Go-Live experience. It’s unrealistic to expect the first days to be error-free—even with a fully tested system, issues are likely to arise. Therefore, good planning should include an action plan for resolving possible errors, and it’s better to avoid relying too much on an &quot;agile&quot; approach during this critical period.&lt;/p&gt;
&lt;h3 id=&quot;issue-triaging&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#issue-triaging&quot; aria-label=&quot;issue triaging permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Issue Triaging&lt;/h3&gt;
&lt;p&gt;During Go-Live, you will encounter both critical and non-critical issues. Critical issues should be resolved as quickly as possible, while non-critical issues should be evaluated. If they pose no immediate risk, it’s better to address them within the ongoing work queue.&lt;/p&gt;
&lt;p&gt;Ignoring non-critical issues can cause users to lose interest in reporting problems. For example, imagine you’re a user of a new system and encounter an issue that, while not critical, adds an extra two minutes to your workflow. You take the time to report it, but nothing happens. The next time something goes wrong, you might not even bother reporting it, and eventually, you might tell your manager the new system isn’t working well.&lt;/p&gt;
&lt;p&gt;To avoid this scenario, it’s essential to maintain user engagement by responding quickly to their feedback and delivering improvements with minimal delay.&lt;/p&gt;
&lt;h3 id=&quot;prod-deployments-planning&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#prod-deployments-planning&quot; aria-label=&quot;prod deployments planning permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;PROD Deployments Planning&lt;/h3&gt;
&lt;p&gt;One of the biggest technical limitations of D365FO is that every &lt;strong&gt;PROD&lt;/strong&gt; release requires 40-50 minutes of system downtime, which makes planning your deployments around this window crucial.&lt;/p&gt;
&lt;p&gt;During the first two weeks of the Go-Live period, I recommend planning:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A scheduled release window every day (e.g., in the evening)&lt;/li&gt;
&lt;li&gt;An emergency release window in the morning&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Even if these windows aren’t always used, planning them in advance saves time and avoids last-minute discussions with users about system downtime. It also helps set realistic expectations for users regarding resolving their issues.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Here’s a breakdown of how a typical release happens and the associated timings:
&lt;ol&gt;
&lt;li&gt;The developer fixes and tests the issue on the DEV environment.&lt;/li&gt;
&lt;li&gt;The fix is deployed to &lt;strong&gt;PRE-PROD&lt;/strong&gt; for final validation via the Deployment Pipeline, which takes approximately 1.5 hours.&lt;/li&gt;
&lt;li&gt;The release manager logs into LCS, marks the &lt;strong&gt;PRE-PROD&lt;/strong&gt; package as a release candidate, opens the &lt;strong&gt;PROD&lt;/strong&gt; environment, and schedules the release (40 minutes of downtime).&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Keep in mind that &lt;strong&gt;PROD&lt;/strong&gt; releases cannot be fully automated and will require some manual effort, which can vary depending on the project.&lt;/p&gt;
&lt;p&gt;I recently ran a poll on &lt;a href=&quot;https://www.linkedin.com/posts/denis-trunin-3b73a213_question-to-people-who-maintain-d365fo-production-activity-7030514980114362368-sBVy?utm_source=share&amp;#x26;utm_medium=member_desktop&quot;&gt;LinkedIn&lt;/a&gt; and got the following results:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 546px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/9c155dbda06a6ada5b6fa95db9f53691/76aed/PollUpdateTime.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 53.714285714285715%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABRElEQVR42pVSyXKDMAz1/39dZzqTJmwOgQANDWYxYDD4xdKhh14aNCOEFmt5kijLEmmaIs9zllmWIY5jXK9XzxJJErMvSRJEUYQwDFmnOJJSSo4lWdc1RFVVbKBAenQJApbS207nEB+fJ4RRwkUoYdd12Pcdy7JgXVeWxhhm0oW1ln/meWbnNE3snGaDZtxQDxba7CBy+J9E3/e/7VN14lYp2G3DEaKu6a3oOGGOe1F4Q8/GZ9NgO5jQOccTilY1iMIA0oMfBhecv07IbikejweDTJXfIWqg8Y2IThvI4ge3qkH51KjUiO/W47lu2H2Qc++PrLWGIOCDosMlV7h3FrUBKg0sxybmDhlD5RdAZ1N4DGlBpBsz4yhRh8MwQGj/ufsN0z1SwrZt/ckcT0hLoZMTatpQ+FHb0XrDyEZi9y54f+7wBTLjUzL+sZvDAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Poll results&quot;
        title=&quot;&quot;
        src=&quot;/static/9c155dbda06a6ada5b6fa95db9f53691/76aed/PollUpdateTime.png&quot;
        srcset=&quot;/static/9c155dbda06a6ada5b6fa95db9f53691/4edbd/PollUpdateTime.png 175w,
/static/9c155dbda06a6ada5b6fa95db9f53691/13ae7/PollUpdateTime.png 350w,
/static/9c155dbda06a6ada5b6fa95db9f53691/76aed/PollUpdateTime.png 546w&quot;
        sizes=&quot;(max-width: 546px) 100vw, 546px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Lastly, make sure to communicate with the person handling the releases to clarify that some overtime may be required during this period.&lt;/p&gt;
&lt;h3 id=&quot;code-branch-management&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#code-branch-management&quot; aria-label=&quot;code branch management permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Code Branch Management&lt;/h3&gt;
&lt;p&gt;During the Go-Live phase, it’s essential to keep your code &lt;a href=&quot;https://learn.microsoft.com/en-us/azure/devops/repos/tfvc/branching-strategies-with-tfvc?view=azure-devops&quot;&gt;branch management&lt;/a&gt; as simple as possible. In some projects, we used only a single &lt;strong&gt;Main&lt;/strong&gt; branch, while in others &lt;strong&gt;Main&lt;/strong&gt; and &lt;strong&gt;Release&lt;/strong&gt; branches, with &lt;strong&gt;Release&lt;/strong&gt; being mostly a copy of &lt;strong&gt;Main&lt;/strong&gt;. This approach requires quality control, and Javier Lopez’s series of &lt;a href=&quot;https://javi-kata.medium.com/ci-cd-the-journey-of-a-dummy-team-f51a061684bc&quot;&gt;blog posts&lt;/a&gt; provides some useful insights.&lt;/p&gt;
&lt;p&gt;It’s easy to overcomplicate this process and end up with a full-time person just to manage branches and releases. But for the Go-Live period, I recommend sticking to a &quot;simple mode.&quot;&lt;/p&gt;
&lt;p&gt;There are two key factors to consider when planning your branch strategy:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Speed of Deployment&lt;/strong&gt;: How quickly can a validated fix be deployed to &lt;strong&gt;PROD&lt;/strong&gt;? During Go-Live, this should ideally be within 1 day.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Effort Required&lt;/strong&gt;: How much time does it take to deploy? A good setup shouldn’t take more than 1 hour of work time.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;integration-issues&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#integration-issues&quot; aria-label=&quot;integration issues permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Integration Issues&lt;/h2&gt;
&lt;p&gt;During the initial Go-Live phase, you’ll likely encounter a wide range of integration-related errors.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;For inbound integrations, typical issues include:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;External systems sending messages in the wrong format (e.g., missing XML tags, incorrect date or numeric formats)&lt;/li&gt;
&lt;li&gt;Messages containing invalid values (e.g., references to data that doesn’t exist in D365FO)&lt;/li&gt;
&lt;li&gt;Duplicated messages&lt;/li&gt;
&lt;li&gt;Incorrect field mapping on the D365FO side&lt;/li&gt;
&lt;li&gt;Misconfigured or missing D365FO settings during message processing&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;For outbound integrations, common problems are:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;External systems reporting that they didn’t receive some documents from D365FO&lt;/li&gt;
&lt;li&gt;Or Received messages containing wrong values for individual fields&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;For Service/OData-based integrations:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Complaints from external systems about incorrect data returned by D365FO (often accompanied by screenshots showing empty or incorrect fields in their UI)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In addition to these issues, you may also encounter errors in the X++ code that processes integration messages(so need to reverse and reprocess existing messages), or experience performance bottlenecks during high message volumes.&lt;/p&gt;
&lt;p&gt;On my most recent project, I used the &lt;a href=&quot;https://github.com/TrudAX/XppTools?tab=readme-ov-file#devexternalintegration-submodel&quot;&gt;External Integration&lt;/a&gt; framework, which provides comprehensive logging and allows for replaying/debugging individual messages to troubleshoot issues. It worked exceptionally well for investigating and resolving common integration problems.&lt;/p&gt;
&lt;p&gt;If you’re using a different integration approach, make sure the team has a plan in place to address at least the types of issues mentioned above.&lt;/p&gt;
&lt;h2 id=&quot;update-planning-and-feature-management&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#update-planning-and-feature-management&quot; aria-label=&quot;update planning and feature management permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Update Planning and Feature Management&lt;/h2&gt;
&lt;p&gt;Microsoft releases eight updates per year for D365FO, and you can pause two of them. I highly recommend using one of these pauses during your Go-Live phase to ensure the system remains stable without the added complexity of updates.&lt;/p&gt;
&lt;h3 id=&quot;feature-management&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#feature-management&quot; aria-label=&quot;feature management permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Feature Management&lt;/h3&gt;
&lt;p&gt;Feature management in D365FO allows you to gradually enable new features, but it’s not a configuration tool. If you&apos;re a new client, a good strategy is to enable all relevant features before starting your main user testing. This ensures that you’re testing the system as it is in its current version rather than working with legacy code that may no longer be supported.&lt;/p&gt;
&lt;p&gt;To do this, simply press the &quot;Enable all&quot; button in the Feature Management workspace, but make sure to exclude any features marked as &quot;Preview,&quot; as these are not yet fully supported for production use.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/499ec40d9598ec5a7425058508b03a21/a016c/FeatureManagement.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 29.142857142857142%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABH0lEQVR42oVPy07DMBDMN/Fx/AwXjvwCSNxBKpRCU0qrtvSRtsR52YntJHYyrF3UAxxYabSz692ZdfA6WeDmborH4QzPoxBPo4nHYDjG4GWMt8kc77MVwo8lwuniXwQPswYXlwmu73MUyRbbKMIu2uFztcRms4ZSGkCPvu9xCspn/jeCVBhc3QrMIw1ravCyglSSoFBJibKqUHAOSbyjBSsE2pidpH8Juzrouw6dbc5Na60Xc3BhjCHR0vddlGmKnH7RGgslf4zJVNf16UK3UEl1dhOCY78/eKGOzDhdpLUmbuHMWZLgizHwokBCnLEEh+MBWZb7mSCm8zkvkGcpDTAI4nF89AtlKeiKCk2tUWvl0TY1DMH1HPd12/js3r8BnY3HHqgBgmsAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Feature management&quot;
        title=&quot;&quot;
        src=&quot;/static/499ec40d9598ec5a7425058508b03a21/8c557/FeatureManagement.png&quot;
        srcset=&quot;/static/499ec40d9598ec5a7425058508b03a21/4edbd/FeatureManagement.png 175w,
/static/499ec40d9598ec5a7425058508b03a21/13ae7/FeatureManagement.png 350w,
/static/499ec40d9598ec5a7425058508b03a21/8c557/FeatureManagement.png 700w,
/static/499ec40d9598ec5a7425058508b03a21/a016c/FeatureManagement.png 762w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;x-tooling&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#x-tooling&quot; aria-label=&quot;x tooling permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;X++ Tooling&lt;/h2&gt;
&lt;p&gt;Having the right tools can significantly simplify issue resolution during the Go-Live phase. I highly recommend exploring the available resources in the &lt;a href=&quot;https://github.com/anderson-joyle/awesome-msdyn365fo?tab=readme-ov-file#x-tools&quot;&gt;X++ community&lt;/a&gt;. Below, I’ve listed some of the tools our team relied on most during the initial Go-Live phase.&lt;/p&gt;
&lt;h3 id=&quot;field-list&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#field-list&quot; aria-label=&quot;field list permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Field List&lt;/h3&gt;
&lt;p&gt;The &lt;strong&gt;&lt;a href=&quot;https://denistrunin.com/xpptools-fieldslist/&quot;&gt;Field List&lt;/a&gt;&lt;/strong&gt; tool is useful for quickly checking data and comparing values between different records. For example, if you have two sales orders that appear similar, but one of them is missing certain buttons or actions, you can easily compare the records to identify the differences.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/04304e0317a8925a9ca314e1a912650b/f941f/FieldList.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 88.57142857142857%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAYAAABb0P4QAAAACXBIWXMAAA7EAAAOxAGVKw4bAAADVklEQVR42o1TaW8URxAdKaBEAhwIArI2xoYvEQgJJMjPAQkQIOCnQBLARgn3r8D2ru1FFgb8DSzAXsfee3eOnmPn2FmPZ3b2paq9NgaBlJaeqru66nV1HcrbhQXMv8zj1cQLzM/M4NXsNOayWWSnc5iYnEQ2m8MknRlTtJ+YmkIul8P0bJ4wixz5zObzUvJZOXjoMIZHRnBkcAiHfx3E7h9/ws+/HMTwsVFkSDd0dAgjo6M4OnwMe/buww+7dmPvvgEcyWSQyQxiYGAAh4hj/4EDdL8Hytnr93Hm+hjO3xjH+ZvjOHn5LynP3XyA09fu4dyNMZy+eg+/3xoH25689CfZjuHUlbv47fJdHL9wBycu/iFx/MJtKE9eqxifKeJBvoS/X1ZIlum8in/mqnj61iDoePxak/IZ4ckbHc8XDKl7NK/iEcmHfclQmqqOwsoqVlbXsLS8ImW13oSqGdB0AZUgTBuGafVhQxebUnwDiqap+LC4iMX37/Dp40eUyyWsFJZRLK6hsLyEUrEEIQwYht7Hzr3+ld6AYpomGo0GyqUynFYLruvCcRy5d1oOLMuCbdto8Zn0vP98/xVIr7BDFEXwPJfgI04S9Ho9pGmKbjeRRJ7nIY5j8ArbIYJ2GynZdLvdbbA9L4VZWeG2+HULntuCT1EmREzM8H2PoiYdPRgQcSdsww98bGxs4FtLqakC7ysWKnUNdc2Cv54g6CQIN1K0owSVpo6aZpIuhk/QbR91g1LhdeAEkZS2H2E97kf4qdTE87k1FJsCNSuA5kZo2CEMP5YoNk3USW+FKcx2FyXDR6FuoVAVWFNdLFUM/NtsodXpfv5yksQwTQHTEvRlVyLp59KhIrQpZ5wWXlvye0sSxkTIpdd0HQ7la6sATCgM6kVVpR6jbwdteuh/ECaymtQKtkOO1jZhmnapKD4VxUMYhvKBaH1d6rgzvh8hEViWKRu4Qw69XrpNyH1nW7aUTMLtwRXmlOxsly8jpC9b9CVBeWTHkFpDEpKD42w2Mk9B1CfiVup0OggoUs7vF4RC0KyKfp7ISac8qpomJ8QUJpqslzaGlDJigkdk/HVu+p1Q+OVatSongg2CIJBkPMu1Wk1O0Kbel9WvVCqoN+oyyi0SHtetYP4DWJ/waGGkXDQAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Fields list&quot;
        title=&quot;&quot;
        src=&quot;/static/04304e0317a8925a9ca314e1a912650b/8c557/FieldList.png&quot;
        srcset=&quot;/static/04304e0317a8925a9ca314e1a912650b/4edbd/FieldList.png 175w,
/static/04304e0317a8925a9ca314e1a912650b/13ae7/FieldList.png 350w,
/static/04304e0317a8925a9ca314e1a912650b/8c557/FieldList.png 700w,
/static/04304e0317a8925a9ca314e1a912650b/f941f/FieldList.png 736w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h3 id=&quot;call-stack-to-infolog&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#call-stack-to-infolog&quot; aria-label=&quot;call stack to infolog permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Call Stack to Infolog&lt;/h3&gt;
&lt;p&gt;The &lt;strong&gt;Call Stack to Infolog&lt;/strong&gt; tool is a real &lt;a href=&quot;https://denistrunin.com/xpptools-devinfocallstack/&quot;&gt;time saver&lt;/a&gt;. It has saved us a lot of time, helping resolve issues in minutes instead of spending hours on data restores and debugging. When enabled for key users, this tool logs an X++ call stack for every error or warning message.&lt;/p&gt;
&lt;p&gt;Some D365FO error messages may be unclear—for instance, encountering &lt;em&gt;&quot;Account not specified&quot;&lt;/em&gt; during a complex document posting. With this tool, you can see the exact X++ call stack that generated the message, providing crucial insight into the issue.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/b607d41687e67d9fd9ababd025fe62c9/ec821/DevCallStackInfoMain.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 61.71428571428571%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAMABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAEDAgX/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIQAxAAAAHruyJGw//EABkQAAIDAQAAAAAAAAAAAAAAAAACAQMSIP/aAAgBAQABBQKVrgwhhOP/xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAaEAABBQEAAAAAAAAAAAAAAAAAAQIgMpEh/9oACAEBAAY/Auo0q3CiZD//xAAaEAEAAgMBAAAAAAAAAAAAAAABABEQMXHx/9oACAEBAAE/IR7F0JaWMcTxUdRMf//aAAwDAQACAAMAAAAQuM//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/ED//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/ED//xAAeEAADAAEEAwAAAAAAAAAAAAAAAREhMUFxkbHB8P/aAAgBAQABPxBBWrKkRmhumVdH1XoVPJCmppwSY8n/2Q==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Call stack&quot;
        title=&quot;&quot;
        src=&quot;/static/b607d41687e67d9fd9ababd025fe62c9/29d31/DevCallStackInfoMain.jpg&quot;
        srcset=&quot;/static/b607d41687e67d9fd9ababd025fe62c9/e52aa/DevCallStackInfoMain.jpg 175w,
/static/b607d41687e67d9fd9ababd025fe62c9/70ebb/DevCallStackInfoMain.jpg 350w,
/static/b607d41687e67d9fd9ababd025fe62c9/29d31/DevCallStackInfoMain.jpg 700w,
/static/b607d41687e67d9fd9ababd025fe62c9/ec821/DevCallStackInfoMain.jpg 1030w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Standard approach&lt;/strong&gt;: Without this tool, the usual process would involve restoring the database and setting a breakpoint in &lt;code class=&quot;language-text&quot;&gt;info.add();&lt;/code&gt;—a much more time-consuming approach.&lt;/p&gt;
&lt;h3 id=&quot;sql-execute&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#sql-execute&quot; aria-label=&quot;sql execute permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;SQL Execute&lt;/h3&gt;
&lt;p&gt;The &lt;strong&gt;SQL Execute&lt;/strong&gt; tool is incredibly useful for data analysis. When I first &lt;a href=&quot;https://denistrunin.com/xpptools-sqlexecute/&quot;&gt;introduced&lt;/a&gt; it, some people considered it unsafe (despite similar modifications being possible through ER), but it actually becomes true. Over time, consultants began writing update queries, which brought attention to potential risks. It&apos;s important to note that &lt;a href=&quot;https://learn.microsoft.com/en-us/power-platform/admin/support-overview?toc=%2Fdynamics365%2Ffin-ops-core%2Fdev-itpro%2Ftoc.json&amp;#x26;bc=%2Fdynamics365%2Fbreadcrumb%2Ftoc.json#does-microsoft-provide-support-for-data-corruption&quot;&gt;Microsoft does not provide support for correcting damaged data&lt;/a&gt;, so care is needed.&lt;/p&gt;
&lt;p&gt;To enhance safety, I added separate roles for &lt;strong&gt;Select&lt;/strong&gt; and &lt;strong&gt;Update&lt;/strong&gt; modes, along with extended logging. &lt;strong&gt;Update&lt;/strong&gt; mode was disabled for everyone except one system administrator, who wasn’t involved in user support. This setup worked well for us.&lt;/p&gt;
&lt;p&gt;Another feature added since the initial release is the ability to export results to Excel with proper formatting, including displaying Enum labels and converting DateTime to the user&apos;s time zone.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/79d4a9a362014e603571ad5023906ae2/a8417/DEVSQLExecute.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 73.14285714285714%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACuElEQVR42qVU204TURSd/1ExxhA1PvkDEk28xsSEv0BIUGLiNxjfJD5oIhDUxk6pmJggSEFuGtppp9My07n2zH1aoGW5z2kQ4qM8rOyzzt57nXNm7z1SEPjQ9T202x6iKESWZTjY3yd0/wsSIyFVVdFoNAkNhGGIw4MzCCZJik6XC3TQ7WTonUFscEPWRrPZRBQG4mb7XS7cEc/ma47TCf/ywR5ZyuX5kue5sB0LWZoKoYieHAQB0jSB13YF5wnc5/uMYm106DtzztHJUrikwT9VHEeQoiimYiTiJB6YkRAXSJMYIRcme5ycRBEYY38PF6CcwPfFPrdSGqeUlAH9Po4OD9Hv9dAne0T2GKc5BQh+GsLX7wkNSbd0lOsV7FR2oKgVVOsKqmoZNa2Kmq5BqZVRqQ54y7NhEmzmwmKOsI7vwWEerLZDfgvS6Ktx3HjxGKMvx3Bp4jYujI1giHB+7CaGJm4JfnGc7JMRwYef3sP1549wdeoBrk09xPDkXVx5dh+XJ+/gHMVIueUPyK0UYVBhcmtfMbdSQGF7CR9Li5il/fdLebwpzmHmu4y333J4R5hfLWJuuYBP6xS/uoDXxRlMF2cxvThPbeNaMKhtDF0Hcz0wx0MnzgghEtdBFibwPUY+Bs8e+NOQCsnIH0S0TmAbJoyGDlM3IVmU1KZetCwLrkvlp/GzHQeWbcI0dBitFo1lW8RwxHEsYnhreTRlAW8z4owq7FMvS4paRV2ri7Gr17nVxCgKEFcUKlJVEX7TNKFpGsVrgmsaodnArz0FW9ouNtTfkFZ/lrBS+gHbttGi25TLu1hbXxdrh9+Ubn4CEqQDzZYp/C7568TlLwXICwXkCzKk0uYaNrY2qSnpCR7/UdSwtb1Nz2TU8JGYAA6+dlwbekunifHFc5MkgWG28FnOQ84TZBl/APvuQNpdfCooAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;SQL Execute&quot;
        title=&quot;&quot;
        src=&quot;/static/79d4a9a362014e603571ad5023906ae2/8c557/DEVSQLExecute.png&quot;
        srcset=&quot;/static/79d4a9a362014e603571ad5023906ae2/4edbd/DEVSQLExecute.png 175w,
/static/79d4a9a362014e603571ad5023906ae2/13ae7/DEVSQLExecute.png 350w,
/static/79d4a9a362014e603571ad5023906ae2/8c557/DEVSQLExecute.png 700w,
/static/79d4a9a362014e603571ad5023906ae2/a8417/DEVSQLExecute.png 941w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Standard approach&lt;/strong&gt;: Without this tool, you would typically need to export the database to Tier 2 and connect via SQL Management Studio, which is much more time-consuming.&lt;/p&gt;
&lt;h3 id=&quot;execute-custom-code&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#execute-custom-code&quot; aria-label=&quot;execute custom code permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Execute custom code&lt;/h3&gt;
&lt;p&gt;In every project I’ve worked on, there was at least one issue that required modifying inventory or ledger transactions. This happened for various reasons: data wasn’t loaded correctly, Unit of Measures contained a wrong conversion, or users selected incorrect accounts or pressed the wrong buttons.&lt;/p&gt;
&lt;p&gt;Microsoft introduced the &lt;a href=&quot;https://learn.microsoft.com/en-us/dynamics365/fin-ops-core/dev-itpro/deployment/run-custom-scripts&quot;&gt;Run custom X++ scripts with zero downtime&lt;/a&gt; utility, which has been a valuable tool. However, the approval process they implemented is quite strange. The script runs within a transaction, which doesn’t allow for dialogs, and it requires approval from two people before the final run.&lt;/p&gt;
&lt;p&gt;The process is different in real-world project scenarios. Typically, you write a custom class to correct the data and run it in &lt;strong&gt;PRE-PROD&lt;/strong&gt; first, then ask key users to review and confirm the changes. Once they approve, you run the same class in &lt;strong&gt;PROD&lt;/strong&gt;. At this point, since the changes have already been tested and validated in &lt;strong&gt;PRE-PROD&lt;/strong&gt;, no further approval is necessary when the code reaches &lt;strong&gt;PROD&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;The improved &lt;a href=&quot;https://github.com/TrudAX/XppTools/tree/master/DEVTools/DEVCustomScripts&quot;&gt;Custom Scripts&lt;/a&gt; utility eliminates the standard validations and allows you to run a custom class without external transactions, enabling the use of dialogs.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/77d5189f82228df081b037242d98419b/914ae/DEVCustomScripts.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 32%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABBElEQVR42nWQR27DMBBFdf9dzpIr5ApZxIWSXIJYxVZhbz8ztBBkYwJP+KSm/Jnq41Ph7X2CNQbWOTjvsEpiXaGUIi0hlcSyLlCkjdGQcoXWGill5JyIjBhDodJaITgLz8U2vGc8JUo0pyva0wU/tx7DcEfXD+i6HjdiHO+bHilWUxODil1wNy4QY0QIAdY6wpT3ur3gIBqcz98QzQmibrHbCxxFi4b+7Y81vnYC80IFjUe1LDQKuWTbSiqkmEpRHi8Ej8f0KGPzoZDCf503zeMzFbbDrg7UmW0/E3JZA7s0tN9E7lNKL+F4puKPtbYksVsuwHcO8u65S36b5hkxxb/EV/wCdmvQKvRS23EAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Custom script&quot;
        title=&quot;&quot;
        src=&quot;/static/77d5189f82228df081b037242d98419b/8c557/DEVCustomScripts.png&quot;
        srcset=&quot;/static/77d5189f82228df081b037242d98419b/4edbd/DEVCustomScripts.png 175w,
/static/77d5189f82228df081b037242d98419b/13ae7/DEVCustomScripts.png 350w,
/static/77d5189f82228df081b037242d98419b/8c557/DEVCustomScripts.png 700w,
/static/77d5189f82228df081b037242d98419b/914ae/DEVCustomScripts.png 860w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Another option for similar tasks is the &lt;a href=&quot;https://github.com/milnet92/MXTXppInterpreter?tab=readme-ov-file&quot;&gt;MXT - X++ Interpreter&lt;/a&gt; from &lt;a href=&quot;https://www.linkedin.com/in/oriol-ribes-amen%C3%B3s-16055667/&quot;&gt;Oriol Ribes Amenós&lt;/a&gt;, which may have some compile risks but works well for &lt;a href=&quot;https://www.linkedin.com/pulse/mxt-x-interpreter-useful-tool-developers-denis-trunin-huhec/&quot;&gt;simple scripts&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/bb49a2629cd6152e7d36616c70b1cf6a/91b67/XppScript_deb.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 21.714285714285715%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAYAAACOXx+WAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAzklEQVR42nWQy2rDMBBF/f//kE0bcAsJtN9QKN114dBsUuJgJRS7SZV4JPmZ07HoposIjq5mRswwN/HOIu5H8Tjv8FED/nhCaofTONRC2zZ0f7RNIAT9432sR1WmXGJFsGfP5eI425orcJ2uqOM/xnGI+V1heFw+ky6emD8suU8XzO5SXl7ftOHqg8P+wPbznb3JOB03VOUaJ1/cOiI12zwny1YYYyiKgjzf8V1VJFKWOjkonmFQekfXi77DzYZ91+lA0Y1stKKZLFC7Jn4BKKgwEYabz+oAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;MXScript&quot;
        title=&quot;&quot;
        src=&quot;/static/bb49a2629cd6152e7d36616c70b1cf6a/8c557/XppScript_deb.png&quot;
        srcset=&quot;/static/bb49a2629cd6152e7d36616c70b1cf6a/4edbd/XppScript_deb.png 175w,
/static/bb49a2629cd6152e7d36616c70b1cf6a/13ae7/XppScript_deb.png 350w,
/static/bb49a2629cd6152e7d36616c70b1cf6a/8c557/XppScript_deb.png 700w,
/static/bb49a2629cd6152e7d36616c70b1cf6a/e996b/XppScript_deb.png 1050w,
/static/bb49a2629cd6152e7d36616c70b1cf6a/2cefc/XppScript_deb.png 1400w,
/static/bb49a2629cd6152e7d36616c70b1cf6a/91b67/XppScript_deb.png 1527w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;automation-scripts&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#automation-scripts&quot; aria-label=&quot;automation scripts permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Automation Scripts&lt;/h2&gt;
&lt;p&gt;One of the most important steps in a project is to automate as much as possible to streamline processes. In our project, we used the following automation scripts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Automated build and deployment pipelines&lt;/strong&gt;: This setup requires a service account without MFA. You can find a sample instruction for setting up the pipeline &lt;a href=&quot;https://denistrunin.com/d365fo-buildrelease/&quot;&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Script to prepare the development VM&lt;/strong&gt;: This &lt;a href=&quot;https://github.com/TrudAX/TRUDScripts/blob/master/D365FO/PrepareNewVMScript.ps1&quot;&gt;script&lt;/a&gt; ensures that all necessary tools(e.g d365fo.tools) are installed and available on every project VM.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Script to refresh code on the DEV VM&lt;/strong&gt;: This &lt;a href=&quot;https://github.com/TrudAX/TRUDScripts/blob/master/D365FO/RestoreCode.ps1&quot;&gt;script&lt;/a&gt; allows you to compile one or all models in the correct sequence.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Various scripts to support the development process&lt;/strong&gt;: These &lt;a href=&quot;https://github.com/TrudAX/TRUDScripts/blob/master/D365FO/UsefulScripts.ps1&quot;&gt;scripts&lt;/a&gt; include important tools such as restoring the Tier 2 database and sharing it through a separate storage account.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SQL script for post-PROD data restore&lt;/strong&gt;: This script enables users and updates integration settings to test values after restoring the &lt;strong&gt;PROD&lt;/strong&gt; database.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;summary&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#summary&quot; aria-label=&quot;summary permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Summary&lt;/h2&gt;
&lt;p&gt;In this post, I’ve shared practical insights from my experience in technical management for Go-Live D365FO projects. At a high level, the process is simple: you need to organize an efficient workflow for the following activities:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Delivering fixes from Development to Production&lt;/li&gt;
&lt;li&gt;Replicating test cases for Production issues on the Development VM (via data restore)&lt;/li&gt;
&lt;li&gt;Monitoring the system to address typical issues&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;However, the complexity lies in the details. I hope you found this post helpful. Feel free to ask any questions or share your own insights—I’d be happy to discuss them further.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[D365FO Integration: Event-Based Exports to External Web Services]]></title><description><![CDATA[How to implement robust, efficient integrations between Dynamics 365 Finance and Operations and external Web Services. This post covers design, code samples, troubleshooting and performance testing techniques for seamless event-based data synchronization.]]></description><link>https://denistrunin.com/integration-outboundweb/</link><guid isPermaLink="false">https://denistrunin.com/integration-outboundweb/</guid><pubDate>Mon, 07 Oct 2024 22:12:03 GMT</pubDate><content:encoded>&lt;p&gt;In this blog post, I will describe how to implement event-based data export from Dynamics 365 Finance to the Web service using REST API call.&lt;/p&gt;
&lt;p&gt;While a simplified example illustrates the core concepts, the approach and code samples are rooted in real-world integration scenarios, making them easily adaptable for similar tasks. We&apos;ll leverage a free and open-source External integration &lt;a href=&quot;https://github.com/TrudAX/XppTools?tab=readme-ov-file#devexternalintegration-submodel&quot;&gt;framework&lt;/a&gt;, offering reusable components for building robust integrations.&lt;/p&gt;
&lt;h2 id=&quot;modification-description&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#modification-description&quot; aria-label=&quot;modification description permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Modification description&lt;/h2&gt;
&lt;p&gt;Let&apos;s begin with our task sample definition:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Goal: Design and develop a Dynamics 365 Finance integration solution that automatically sends confirmed purchase orders from D365FO to a partner website via REST API endpoint.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;To illustrate this process, I utilized Claude Sonnet 3.5 to generate a simple Purchase Order Management application and deploy it to Azure.&lt;/p&gt;
&lt;p&gt;The source code is available on &lt;a href=&quot;https://github.com/TrudAX/TestWebService_PurchaseOrderApp&quot;&gt;GitHub&lt;/a&gt;. The application comprises two main components:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;A frontend for displaying orders:&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 621px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/207192a580c470947f97ae90feb660e7/3075e/PurchManagementAppScreen.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 81.14285714285715%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAYAAAAWGF8bAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAC8klEQVR42oVU72vaUBT1/x9jMAZjlI3BYIyxL/uyQvuhTC3Vdo22NVq1an4YTaL5nZjEJD2797WR7tMeHN71vsfx3nPPS6OsSlSEPM+QphkcL4JibDDXbcw1C3PVxEwzsVjaUAgz3cKCzjZ+CifIYG89OFGJbVgiTWI0Yj9HGISI4xi+H2C3S1FWFYqyfIHqOVejpN+PeHwEFcM7BbSSXUKEcUIkOwFO7AhZlj0jFcjznKpP/wHnE6qIEccR5XYw1ms09KWGhbKApmtQ1AWMlQFN07FYLKDrOnSKpw8PWC6XMAxD5DhWNQ2u68LzPLEHQYDhcIjGfDpD/7KPW+kW3XYHfy6ucX0tod1qoUXoSRJ+HR+j1W7j9PQEzWYT5+1zXHS6gsz3fbGHYfhE2Ddu8WnwGd9G3/Fl+FXsXughJS1j0VIiEEWRAMesd0QETMZENQTh1fwSr36/xvuLD3jTfIuj7keYtkmtaqJFhmVbsG1btKppKlakVV3dmmLOBzWhv3Whz3QoEwX6VIVF1mBN5MEA9/djyPKQyCxBLMsyev0+HmYzUSUPQiWtx3QnDCOMRiMiDHy4vkvthKjXfr+H53tUhS8swiugarjKehAby0ZO+bJ1hv3ROxSuA+nmjmxDulh0GIWRsINlWaIFx3FgmibBItICJXvvgIr8V4HdV5LOheeSIQucdyQ02Eej4QiKotLofYwnE0ynU6GNPBgKe7Cp/7dK+lNVM5gwgUkVzkiXrbMV0+WVktG5ZV71S6AIhxCHlFhFUWBJOjeEBaht1objLMvFy6hfB19kTXnnNhncNucYJefpd0Z3uauGTTrd0UQZbGKeLE9V6klPU+31xOtQVAU3NOFOt4vReCx8F4UBxvM5+uMJPPoemEzo08RY/M1mg4TeNVfF75oP15TnJ8XVuiT8er063HUdFxn1H0tXCH7+QEY8SyYULifLsJYvbcMy8FeIW+W1o3M2sngx5IiAvkx8Ut3LKM9OsKdqjfUKfwGtZq6E188zwwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Purchase Order Management App&quot;
        title=&quot;&quot;
        src=&quot;/static/207192a580c470947f97ae90feb660e7/3075e/PurchManagementAppScreen.png&quot;
        srcset=&quot;/static/207192a580c470947f97ae90feb660e7/4edbd/PurchManagementAppScreen.png 175w,
/static/207192a580c470947f97ae90feb660e7/13ae7/PurchManagementAppScreen.png 350w,
/static/207192a580c470947f97ae90feb660e7/3075e/PurchManagementAppScreen.png 621w&quot;
        sizes=&quot;(max-width: 621px) 100vw, 621px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;A backend that includes an API for accepting these orders:&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/9888a8ffca9bfd7ccb8a5ea975838a92/cecac/ApiPicture.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 65.71428571428571%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABVUlEQVR42p1Sy26DMBDM/39eD+0hUQkkpME4NviBbV7T9aaJqqqXgDTa9Xg1mvGym+cZ5bFEQdjvD1xDiNj67VIa4ZyDJfS9QUdw3jO3LMtLYmsWHIYBRVGgLCvU9YUdVtUJR6pZOMZIjgO7zrP+h/PU5/vB37k8ww6zC601u8sujbUwxqLreiilcbsphtL3vpWS7g2kvEGIFm0rmbvRLAuu64qQJthA0RkJvQuI44xxXpAmwqMSMve4Y0wr1RWJuCGO5JAE/ZDwUWkc6h5V06GsJc6NgtQOISb48Af/cYSnYKCmUY6d2SHy+ffQK2DBSJGNj6iExVV51I3G50nA+rv4a4ILCY4kSLHfPhX2FPssCBR9s8NA/6I2DspEyD6Q20TLmXhZmyPn98uRRefx1WoUZ/F8z22RydV7SW93oU1fNU4U2W2PnAUDhB54KcoGaJs2Rf4GY3LvwDFLoNwAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;API sample&quot;
        title=&quot;&quot;
        src=&quot;/static/9888a8ffca9bfd7ccb8a5ea975838a92/8c557/ApiPicture.png&quot;
        srcset=&quot;/static/9888a8ffca9bfd7ccb8a5ea975838a92/4edbd/ApiPicture.png 175w,
/static/9888a8ffca9bfd7ccb8a5ea975838a92/13ae7/ApiPicture.png 350w,
/static/9888a8ffca9bfd7ccb8a5ea975838a92/8c557/ApiPicture.png 700w,
/static/9888a8ffca9bfd7ccb8a5ea975838a92/cecac/ApiPicture.png 728w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;In our scenario, we will send confirmed Purchase Orders (POs) from D365FO to this API. The UML diagram below illustrates our test process:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 423px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/231a70d7c599afb1960118b311f6b86a/f687d/UMLDiagram.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 80.57142857142858%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAYAAAAWGF8bAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABvklEQVR42q1U72+CMBTs//8fbVmybB90WdzvRaNIVMANRFGcVBDqrVcHg2Tsk03O0j767t69osiyA9brHdrG8Xis8F+shMiyDJtNjHMNoVSBNE3/ZCM+PkLYtqfhYrtNfpSdDjM2mcwxm33CcQKE4QbC9329MWtlHAwmuL19QKfzCt+PqlI53t5sHXtEt/uCu7t3WJYHURSF9nCN5XJpsFqtsFgszBwEgbZjg8PhgKJQUKrpo1LK7Od5bmJcCwZ4eDwea/kTo9a2bfNMOI5jErdZQlBU5SF/wjDEcDiskjC5ZVmYTqfo9/ugLf/dgkZCbpwkKxMoUV/HcQzP8yq4rmtAQq55UxoJS4bS7PpcErJslk8wEauiv1TPHpTvi1JJvYT6zJEkibGByWgJ7WAyKpNSmqY1PIyiyLxEv8jOZzZmNBrpu7fVB7IGadlhTauJKSj/TUgG13WMCoLrOsIw0tdopRV9Yb/PfpKc1O92e+3vzsTimOf3EEGw0GU4rV18frZwednF1dU95vNlw45eb4CLiw6ur3u4uXnSFU4hWD9Z2oaUqWFOklSXnv8R+4WUGQQ7KGVyzj+H06dzroTfyqTVpLj2ahcAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;UML Diagram&quot;
        title=&quot;&quot;
        src=&quot;/static/231a70d7c599afb1960118b311f6b86a/f687d/UMLDiagram.png&quot;
        srcset=&quot;/static/231a70d7c599afb1960118b311f6b86a/4edbd/UMLDiagram.png 175w,
/static/231a70d7c599afb1960118b311f6b86a/13ae7/UMLDiagram.png 350w,
/static/231a70d7c599afb1960118b311f6b86a/f687d/UMLDiagram.png 423w&quot;
        sizes=&quot;(max-width: 423px) 100vw, 423px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;planning-and-scoping-integration-project&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#planning-and-scoping-integration-project&quot; aria-label=&quot;planning and scoping integration project permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Planning and Scoping Integration Project&lt;/h2&gt;
&lt;p&gt;To initiate an integration project like this, I recommend organizing a kickoff meeting with key stakeholders from both the D365FO team and the Web Service provider (third-party team). During this meeting, address the following aspects:&lt;/p&gt;
&lt;h4 id=&quot;1-create-a-data-mapping-document&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#1-create-a-data-mapping-document&quot; aria-label=&quot;1 create a data mapping document permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;1. Create a Data Mapping document&lt;/h4&gt;
&lt;p&gt;Discuss and document what data needs to be sent and how it should be mapped to the third-party system&apos;s accepted format. This is a fundamental question for the entire integration and often requires significant time and attention.&lt;/p&gt;
&lt;p&gt;A template for this document can be found &lt;a href=&quot;https://github.com/TrudAX/TRUDScripts/blob/master/Documents/Integration/Field%20Mapping%20Sample.xlsx&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In our example, to simplify the process, we&apos;re sending all confirmed purchase orders for vendors from a specified Vendor group without any complex mapping.&lt;/p&gt;
&lt;h4 id=&quot;2-reference-data-management&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#2-reference-data-management&quot; aria-label=&quot;2 reference data management permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;2. Reference Data Management&lt;/h4&gt;
&lt;p&gt;Data exchange often involves &apos;reference data&apos; such as Item codes or Vendor IDs. Aligning how both systems manage this data is crucial. Let&apos;s explore some common scenarios:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;a) Limited data acceptance: The Web service may accept only a predefined set of data. In this case, you might need to create additional tables in D365FO to maintain possible options.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;b) Stable, manually loaded data: When reference data is relatively static, manual updates might suffice. For instance, a user could periodically(e.g. monthly) upload an updated item list to the external system&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;c) Frequently changing data: If reference data changes often, you may need to develop a separate integration process to keep it synchronized.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;d) Automatic reference data creation: Some web services can automatically create reference data entries based on the incoming message. In this scenario, ensure all required fields (e.g., Item name, Vendor name) are included in the transmission.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;3-error-handling-rules&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#3-error-handling-rules&quot; aria-label=&quot;3 error handling rules permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;3. Error Handling Rules&lt;/h4&gt;
&lt;p&gt;Establish clear protocols for error handling. Consider these common approaches:&lt;/p&gt;
&lt;p&gt;a) Real-time validation: All business logic validations occur during the API call. A successful call indicates the document has been accepted. This is generally the preferred method.&lt;/p&gt;
&lt;p&gt;b) Format-only validation: The Web service only checks the message format during the call. If the format is correct, the message is accepted for further processing.&lt;/p&gt;
&lt;p&gt;Option (a) requires designating a D365FO team member to respond to integration errors. Ensure this person has a documented support channel with the Web Service support team. For example, how will the returned message &quot;Item AAA can&apos;t be purchased&quot; be processed?&lt;/p&gt;
&lt;p&gt;Option (b) is more straightforward from the D365FO side, but it creates some challenges. You need to know the document&apos;s current status. This may be implemented as another integration(inbound to D365FO).&lt;/p&gt;
&lt;h4 id=&quot;4-data-structure-and-cardinality&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#4-data-structure-and-cardinality&quot; aria-label=&quot;4 data structure and cardinality permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;4. Data Structure and Cardinality&lt;/h4&gt;
&lt;p&gt;Address potential differences in data structure between systems. For example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;D365FO might allow multiple lines with the same ItemID in a Purchase Order, while the receiving system may not support this.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Identify these discrepancies early to plan appropriate handling mechanisms.&lt;/p&gt;
&lt;h4 id=&quot;5-handling-document-updates&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#5-handling-document-updates&quot; aria-label=&quot;5 handling document updates permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;5. Handling Document Updates&lt;/h4&gt;
&lt;p&gt;Define how modified documents should be handled. For instance:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In our case, multiple confirmations can be made for one purchase order. The Web service should be capable of accepting and processing updated versions of previously sent documents.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;6-api-flexibility&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#6-api-flexibility&quot; aria-label=&quot;6 api flexibility permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;6. API Flexibility&lt;/h4&gt;
&lt;p&gt;Understand the web service provider&apos;s constraints regarding API modifications. Possible scenarios include:&lt;/p&gt;
&lt;p&gt;a) Fixed public API: The API is used by multiple clients and cannot be modified.
b) Flexible API: The third-party team can allocate resources to adjust the API for this integration.&lt;/p&gt;
&lt;p&gt;If option (b) is possible, establish clear communication channels, developer availability, and bug tracking procedures.&lt;/p&gt;
&lt;h4 id=&quot;7-batch-vs-real-time-integration&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#7-batch-vs-real-time-integration&quot; aria-label=&quot;7 batch vs real time integration permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;7. Batch vs. Real-time Integration&lt;/h4&gt;
&lt;p&gt;Decide whether document export should occur:&lt;/p&gt;
&lt;p&gt;a) Via a batch job (introducing a delay of at least a few minutes), or
b) Immediately after a triggering action (real-time).&lt;/p&gt;
&lt;p&gt;This blog post will focus on implementing the more complex real-time integration scenario.&lt;/p&gt;
&lt;h2 id=&quot;implementing-the-export-functionality&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#implementing-the-export-functionality&quot; aria-label=&quot;implementing the export functionality permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Implementing the Export Functionality&lt;/h2&gt;
&lt;h3 id=&quot;key-components-of-the-export-class&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#key-components-of-the-export-class&quot; aria-label=&quot;key components of the export class permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Key Components of the Export Class&lt;/h3&gt;
&lt;p&gt;The External integration framework provides a base class for implementing event-based integration. To provide an example, I created &lt;a href=&quot;https://github.com/TrudAX/XppTools/blob/master/DEVTutorial/DEVExternalIntegrationSamples/AxClass/DEVIntegTutorialExportPurchOrder.xml&quot;&gt;DEVIntegTutorialExportPurchOrder&lt;/a&gt; class that extends this base class. Let&apos;s examine it&apos;s key methods and components:&lt;/p&gt;
&lt;h4 id=&quot;1-validation-method-isneedtocreatelog&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#1-validation-method-isneedtocreatelog&quot; aria-label=&quot;1 validation method isneedtocreatelog permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;1. Validation Method: isNeedToCreateLog&lt;/h4&gt;
&lt;p&gt;This method defines the rules for determining whether a record should be exported. In our purchase order scenario, it checks if:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The purchase order is in a Confirmed state.&lt;/li&gt;
&lt;li&gt;The vendor belongs to the specified Vendor Group&lt;/li&gt;
&lt;li&gt;Other relevant conditions are met.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token return-type class-name&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;isNeedToCreateLog&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;PurchTable&lt;/span&gt;  _purchTable&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;boolean&lt;/span&gt;                             res&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;DEVIntegParametersPerCompany&lt;/span&gt;        integParametersPerCompany &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; DEVIntegParametersPerCompany&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isMessageTypeEnabled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;
        _purchTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;DocumentState &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; VersioningDocumentState&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;Confirmed  &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;
        _purchTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;PurchaseType &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; PurchaseType&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;Purch &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;
        integParametersPerCompany&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;POExportOnConfirm &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; DEVIntegTutorialExportOnConfirm&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;None &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;
        _purchTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;vendTable_OrderAccount&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;VendGroup &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; integParametersPerCompany&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;VendGroupId
        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        res &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token named-parameter punctuation&quot;&gt;DEVIntegExportDocumentLog&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sentRecordExists&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;_purchTable&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; messageTypeTableOutbound&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ClassName&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;//already marked to send&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            res &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id=&quot;2-bulk-export-method-exportalldata&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#2-bulk-export-method-exportalldata&quot; aria-label=&quot;2 bulk export method exportalldata permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;2. Bulk Export Method: exportAllData&lt;/h4&gt;
&lt;p&gt;This method is used for two scenarios:
a) Initial data load when starting the integration
b) Re-exporting data after making changes to the export logic/contract&lt;/p&gt;
&lt;p&gt;It allows users to specify which records to export through a query dialog.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;exportAllData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;Query&lt;/span&gt;                   query &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;Query&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;QueryBuildDataSource&lt;/span&gt;    qBDS&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;PurchTable&lt;/span&gt;              purchTable&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;/span&gt;                     processedCounter&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; insertCounter&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    qBDS &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; query&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addDataSource&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;tableNum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PurchTable&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    qBDS&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addRange&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fieldNum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PurchTable&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; DocumentState&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token named-parameter punctuation&quot;&gt;SysQuery&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token named-parameter punctuation&quot;&gt;VersioningDocumentState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;Confirmed&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    qBDS &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; qBDS&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addDataSource&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;tableNum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;VendTable&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    qBDS&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;joinMode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token named-parameter punctuation&quot;&gt;JoinMode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;InnerJoin&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    qBDS&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;relations&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    qBDS&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addLink&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fieldnum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PurchTable&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; OrderAccount&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fieldNum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;VendTable&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; AccountNum&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    qBDS&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addRange&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fieldNum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;VendTable&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; VendGroup&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token named-parameter punctuation&quot;&gt;SysQuery&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token named-parameter punctuation&quot;&gt;DEVIntegParametersPerCompany&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;VendGroupId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  
    &lt;span class=&quot;token class-name&quot;&gt;QueryRun&lt;/span&gt;     queryRun&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    queryRun &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;QueryRun&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;query&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;queryRun&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;prompt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;queryRun&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            purchTable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; queryRun&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;tableNum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PurchTable&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;insertFromPurchTable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;purchTable&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                insertCounter&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
            processedCounter&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;strfmt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;%1 record(s) processed, %2 marked to export&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; processedCounter&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; insertCounter&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;insertFromPurchTable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;PurchTable&lt;/span&gt;  _purchTable&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;boolean&lt;/span&gt;  res&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isNeedToCreateLog&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;_purchTable&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createLogFromCommon&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;_purchTable&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _purchTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;PurchId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        res &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id=&quot;3-core-export-method-exportwebmessage&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#3-core-export-method-exportwebmessage&quot; aria-label=&quot;3 core export method exportwebmessage permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;3. Core Export Method: exportWebMessage&lt;/h4&gt;
&lt;p&gt;This method implements the actual export call to the web service. It handles:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Preparing the data for export&lt;/li&gt;
&lt;li&gt;Making the API call using an HttpClient. As we used a custom service, we also need to define a new load class &lt;a href=&quot;https://github.com/TrudAX/XppTools/blob/master/DEVTutorial/DEVExternalIntegrationSamples/AxClass/DEVIntegTutorialExportPurchLoad.xml&quot;&gt;DEVIntegTutorialExportPurchLoad&lt;/a&gt; that implements communication with the service, but In case we integrate using Azure file share or Azure service bus, the External integration framework already has base load classes for this&lt;/li&gt;
&lt;li&gt;Processing the response, in our case, getting the number from an external Web Order and linking it to our PO.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;exportWebMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;DEVIntegExportDocumentLog&lt;/span&gt;    _exportDocumentLog&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;DEVIntegMessagesLoadBaseType&lt;/span&gt;     _loadFileStorageCache&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;PurchTable&lt;/span&gt; purchTable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; PurchTable&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findRecId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;_exportDocumentLog&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;RefRecId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;DEVIntegTutorialExportPurchLoad&lt;/span&gt;  exportPurchLoad &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; _loadFileStorageCache &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;DEVIntegTutorialExportPurchLoad&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    exportPurchLoad&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;initConnection&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;DEVIntegTutorialExportPurchContractHeader&lt;/span&gt;  contractData &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;DEVIntegTutorialExportPurchContractHeader&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    contractData&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;initFromPurchOrder&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;purchTable&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token class-name&quot;&gt;str&lt;/span&gt; sJSON &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; FormJSONSerializer&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;serializeClass&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;contractData&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;Num&lt;/span&gt;  externalId &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; exportPurchLoad&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;postContract&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sJSON&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _exportDocumentLog&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;DocumentId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    ttsbegin&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    purchTable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; PurchTable&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findRecId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;_exportDocumentLog&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;RefRecId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    purchTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;VendorRef   &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; externalId&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    purchTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;doupdate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ttscommit&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id=&quot;4-data-contract-classes&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#4-data-contract-classes&quot; aria-label=&quot;4 data contract classes permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;4. Data Contract Classes&lt;/h4&gt;
&lt;p&gt;To structure the JSON data for export, we use data contract classes. In our case, we have:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A &lt;a href=&quot;https://github.com/TrudAX/XppTools/blob/master/DEVTutorial/DEVExternalIntegrationSamples/AxClass/DEVIntegTutorialExportPurchContractHeader.xml&quot;&gt;header&lt;/a&gt; class for purchase order header&lt;/li&gt;
&lt;li&gt;A &lt;a href=&quot;https://github.com/TrudAX/XppTools/blob/master/DEVTutorial/DEVExternalIntegrationSamples/AxClass/DEVIntegTutorialExportPurchContractLine.xml&quot;&gt;lines&lt;/a&gt; class for line items&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;What I found is that the &quot;&lt;strong&gt;X++ Dev Helper for Dynamics 365 F&amp;#x26;O&lt;/strong&gt;&quot; custom &lt;a href=&quot;https://chatgpt.com/g/g-F7D3IGTqo-x-dev-helper-for-dynamics-365-f-o&quot;&gt;GPT&lt;/a&gt; for ChatGPT is quite good at creating these classes based on just the sample JSON.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/6a851d00f93dd72d88373765f2096322/baaa6/chatGPTGenerateClasses.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 51.42857142857144%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABeUlEQVR42nWS6Y6DMAyEef9X20rt36UcoZSjBRIg3KXM2qlgEdqNZBEX++uMjaV1i74fUVUN+K51h+ezQF6USNIMaZJByhIF5VJWW3DO9W3b0bOhnhxlVcOSSqLrOrxeLwzDgGmaoJTCOA4UIzW05n23PvsOy7Jgfzif3298n0+w8jynfyxQlqWBcTB4nuetmONNDRxrjuX33RoTibAq9YCSOVksyEZh1O2BmwLKoyiCbdvwPA/Xqw3HdRHebvim3xzHIdtPWPcswCO9o2kammVvbB2B6/EI8HU6wXVcCN+HEAFuBPSFMDm7pRkqc8myzAz4aHl/kjiG67lGoU8AViiCgHpzpOnDjM3SWpOq3ixgosXwcia6H4Fsm2edJMknCM4jYggvjoNdWuw7pgKeYUb3QkrUdW3Ax8O158sFrssKBcIwNO5WmAEqVW6WWbr8B8gKWQ3XcGPb8nerN9AGZADDKoKwTWOZ5viXZW74zE+YrUZRbJa4B/4AJHf99XL/TAcAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Chat GPT X++&quot;
        title=&quot;&quot;
        src=&quot;/static/6a851d00f93dd72d88373765f2096322/8c557/chatGPTGenerateClasses.png&quot;
        srcset=&quot;/static/6a851d00f93dd72d88373765f2096322/4edbd/chatGPTGenerateClasses.png 175w,
/static/6a851d00f93dd72d88373765f2096322/13ae7/chatGPTGenerateClasses.png 350w,
/static/6a851d00f93dd72d88373765f2096322/8c557/chatGPTGenerateClasses.png 700w,
/static/6a851d00f93dd72d88373765f2096322/baaa6/chatGPTGenerateClasses.png 813w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h4 id=&quot;5-event-handlers-for-export-triggers&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#5-event-handlers-for-export-triggers&quot; aria-label=&quot;5 event handlers for export triggers permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;5. Event Handlers for Export Triggers&lt;/h4&gt;
&lt;p&gt;These methods mark records for export when certain events occur, such as confirming a purchase order. They should:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Execute within the posting transaction&lt;/li&gt;
&lt;li&gt;Update or insert a reference in the &lt;strong&gt;DEVIntegExportDocumentLog&lt;/strong&gt; table with Export status to &quot;To send&quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token attribute&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;DataEventHandler&lt;/span&gt;&lt;span class=&quot;token attribute-arguments&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;tableStr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PurchTable&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token named-parameter punctuation&quot;&gt;DataEventType&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;Updated&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;PurchTable_onUpdated&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Common&lt;/span&gt; sender&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;DataEventArgs&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;PurchTable&lt;/span&gt; purchTable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; sender &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PurchTable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;purchTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;DocumentState &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; VersioningDocumentState&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;Confirmed  &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;               
        purchTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;orig&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;DocumentState &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; purchTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;DocumentState &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;DEVIntegTutorialExportPurchOrder&lt;/span&gt;  exportMessage &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; DEVIntegTutorialExportPurchOrder&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;construct&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        exportMessage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;insertFromPurchTable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;purchTable&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id=&quot;6-post-operation-export-methods&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#6-post-operation-export-methods&quot; aria-label=&quot;6 post operation export methods permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;6. Post-Operation Export Methods&lt;/h4&gt;
&lt;p&gt;These methods run after the main operation (e.g., purchase order confirmation) to initiate the actual export process. They:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Execute outside the main transaction, so any failure in export should not block the document posting&lt;/li&gt;
&lt;li&gt;Check for records marked for export&lt;/li&gt;
&lt;li&gt;Trigger the export process for those records&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The export sequence is presented on the following diagram:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 570px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/09979c09ca9389f9255de429b4e658f7/432e7/ExportSequence.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 68.57142857142857%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACJElEQVR42qWU227TQBCG/YgIuEIUoYKoyiPwDrwBqBVccoOEUJMKSgqVmrSUBOE0pyZOfIjjpKljOyfHsT82dkkpVBUqa33+Zw+endnVWOKaNp1OcV2X8XiM53kx8/n80powDImiaNmXrnL0a4Ft21SrVVRVpVarxfbCebLm0hfXO/yXtohs0T5ldqlUqssxKfEeXkkUzYnCeaxhmNjiFYe3eJj7yHsZWnJhmdnNIjzPd9gtYyhptMoWdkdNUp64RSbuniDL1MsycvYJJjmi2WFM6F9oKHQ+PiAYnuK7fTyrgX60h/F9H6erEIwdJK3+nIP9u/worPI1t8LRwQpleRVNWaPVENTXUE6e0DGeoirrqPVVDPkNWjGD0Uih17axmjuolXci9QySa+t0tCJdo4xllOiaZdEvYWrHmGpCW7CY6+gl2i0Zz+kzHY05MxqY8hHmcR7bMhgNhze/ZYIIp5MXEafQBD2xaXyGwfQM/eQlenND7L6Jca4dbRNLT1RXNuiZr+gZr8XcCwbtHXGOHrZRpV3IYhYPGZh1wsBHmk005PwdcrlbFITmv92O0bX7KI179LoPcZ1HeK7AeSz0AZbyTKSZRau+x6inaSvbNOW39NtNpDAY0tPEYGsLs5USmoptS0/H9qm5jXP6kUHvg2ChafpmFn/iM/IGWA2FvqaJTW1mvv//lfJl9zOl4vHvlUJSGdEfxJVyYf/NxQ9kNpsta/knKkQYSZKFnkUAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Export Sequence&quot;
        title=&quot;&quot;
        src=&quot;/static/09979c09ca9389f9255de429b4e658f7/432e7/ExportSequence.png&quot;
        srcset=&quot;/static/09979c09ca9389f9255de429b4e658f7/4edbd/ExportSequence.png 175w,
/static/09979c09ca9389f9255de429b4e658f7/13ae7/ExportSequence.png 350w,
/static/09979c09ca9389f9255de429b4e658f7/432e7/ExportSequence.png 570w&quot;
        sizes=&quot;(max-width: 570px) 100vw, 570px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;In our case, we want to check at the end of Purch confirmation whether any export records have been created and, if so, run an export operation for these records.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token attribute&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;PostHandlerFor&lt;/span&gt;&lt;span class=&quot;token attribute-arguments&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;classStr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;FormletterService&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;methodStr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;FormletterService&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; postPurchaseOrderConfirmation&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;FormletterService_Post_postPurchaseOrderConfirmation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;XppPrePostArgs&lt;/span&gt; args&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token named-parameter punctuation&quot;&gt;DEVIntegParametersPerCompany&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;POExportOnConfirm &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; DEVIntegTutorialExportOnConfirm&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;OnConfirm&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token class-name&quot;&gt;PurchFormLetterPurchOrderContract&lt;/span&gt; contract &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; args&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getArg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&apos;_contract&apos;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PurchFormLetterPurchOrderContract&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;contract&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;PurchParmUpdate&lt;/span&gt; purchParmUpdate &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; contract&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parmParmUpdate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;PurchParmTable&lt;/span&gt;  purchParmTable&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;PurchTable&lt;/span&gt;      purchTable&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;DEVIntegExportDocumentLog&lt;/span&gt;  integExportDocumentLog&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;ClassName&lt;/span&gt;       exportClass &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;classStr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;DEVIntegTutorialExportPurchOrder&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;DEVIntegExportRecordList&lt;/span&gt;  exportRecordList&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;//or if one record - DEVIntegExportRecordList::constructFromRecord()&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;select&lt;/span&gt; ParmId &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; purchParmTable
            &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;purchParmTable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ParmId &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; purchParmUpdate&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ParmId
        &lt;span class=&quot;token keyword&quot;&gt;join&lt;/span&gt; PurchId &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; purchTable
            &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;purchTable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;PurchId        &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; purchParmTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;PurchId 
        &lt;span class=&quot;token keyword&quot;&gt;join&lt;/span&gt; integExportDocumentLog
            &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;integExportDocumentLog&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;RefTableId &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; purchTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;TableId
                &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; integExportDocumentLog&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;RefRecId &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; purchTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;RecId
                &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; integExportDocumentLog&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ClassName &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; exportClass
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt; exportRecordList&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                exportRecordList &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;DEVIntegExportRecordList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;    
            exportRecordList&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addExportLog&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;integExportDocumentLog&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;recId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;exportRecordList&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            DEVIntegExportDocumentsLog&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;exportRecordList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;exportRecordList&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;comparing-custom-export-class-vs-standard-business-events&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#comparing-custom-export-class-vs-standard-business-events&quot; aria-label=&quot;comparing custom export class vs standard business events permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Comparing Custom Export Class vs. Standard Business Events&lt;/h3&gt;
&lt;p&gt;While Microsoft provides a seemingly similar concept with &lt;a href=&quot;https://learn.microsoft.com/en-us/dynamics365/fin-ops-core/dev-itpro/business-events/home-page&quot;&gt;Business events&lt;/a&gt; for Dynamics 365 Finance and Operations, there are significant differences when compared to our custom Export class approach. Let&apos;s examine these differences in detail:&lt;/p&gt;
&lt;h4 id=&quot;1-data-creation-timing&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#1-data-creation-timing&quot; aria-label=&quot;1 data creation timing permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;1. Data Creation Timing&lt;/h4&gt;
&lt;p&gt;With Business events, data is captured at the moment the event occurs, creating a fixed event payload. In contrast, Export class gathers data at the time of export execution. This allows for real-time data retrieval, including any updates made after the initial trigger. For example, an export may fail due to incorrect or missing mapping. For External integration, you just need to fix this mapping; it will be automatically applied at the time of the next export.&lt;/p&gt;
&lt;h4 id=&quot;2-event-frequency-and-uniqueness&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#2-event-frequency-and-uniqueness&quot; aria-label=&quot;2 event frequency and uniqueness permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;2. Event Frequency and Uniqueness&lt;/h4&gt;
&lt;p&gt;Business events are generated for each occurrence, potentially creating multiple events for the same document (e.g., two events for two confirmations of the same purchase order). There&apos;s also no guaranteed sequence for event delivery. For documents that can&apos;t be modified after the export(e.g. Invoices), this difference is probably not critical, but in case exporting  documents that can be modified, you need to make sure that the consuming side &lt;a href=&quot;https://learn.microsoft.com/en-us/dynamics365/fin-ops-core/dev-itpro/business-events/home-page#idempotency&quot;&gt;can handle&lt;/a&gt; the message sequence correctly.&lt;/p&gt;
&lt;p&gt;Export class, however, maintains a unique Export log entry per document, updating existing entries for repeat actions on the same document. This ensures the most recent state is always exported.&lt;/p&gt;
&lt;h4 id=&quot;3-response-processing&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#3-response-processing&quot; aria-label=&quot;3 response processing permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;3. Response Processing&lt;/h4&gt;
&lt;p&gt;Business events are generally designed for one-way communication with limited built-in capabilities for processing responses from external systems. Our Export class easily incorporates logic to handle responses, allowing for updating local records based on the external system&apos;s response (e.g., linking local PO with external PO number).&lt;/p&gt;
&lt;h4 id=&quot;4no-logs&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#4no-logs&quot; aria-label=&quot;4no logs permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;4.No logs&lt;/h4&gt;
&lt;p&gt;Business events do not support any logs, except for internal send errors. For example, if the event was sent successfully, you won&apos;t see this. You also can&apos;t find out for the original document - what types of events were sent to it. This is a common integration question, for example, if the external team tells you they don&apos;t receive an event, you have no options to validate it when using Business events. External integration has a complete log, and it contains the Original document and the Reference RecId to the original record, so troubleshooting is quite simple; you can always see what events were generated and sent.&lt;/p&gt;
&lt;h2 id=&quot;setting-up-and-validating-integration&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#setting-up-and-validating-integration&quot; aria-label=&quot;setting up and validating integration permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Setting Up and Validating Integration&lt;/h2&gt;
&lt;p&gt;Let&apos;s walk through the process of setting up and validating our integration solution.&lt;/p&gt;
&lt;h3 id=&quot;configuring-connection-types&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#configuring-connection-types&quot; aria-label=&quot;configuring connection types permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Configuring Connection Types&lt;/h3&gt;
&lt;p&gt;First, we need to set up the connection to our web service. Navigate to the &lt;strong&gt;External integration – Connection types&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;It requires the hostname(will be &lt;a href=&quot;https://purchaseorderapp20240916.azurewebsites.net/api/purchaseorder&quot;&gt;https://purchaseorderapp20240916.azurewebsites.net/api/purchaseorder&lt;/a&gt;) and allows to set a user/password credentials to access this host(in our example, we&apos;re leaving these empty)&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 679px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/da0552d625b1181a8f0386f325666cf5/1b747/ConnectionTypes.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 65.14285714285714%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABdklEQVR42p1T2U7DMBDM/z/wK/wOD6glBy1pfcZO4iPNsOtSQKgIlJVGmzjx7M56XB3FhIdHASEtRu8xDA5nMUBpTVnA0VoICTFG5GXB5XJBzvlXVKN3CPOERBtimCkH5BRLjgRP3+uXGrvdHk3TQCqFlFL5v+R0LVYQAqqzVHg9vEEbhzlmaOvQnyWOvYAZPKZxIqIa+/2V8HQ6lc3eOWhSYa0lBeET1a4zeNoL1P2Mo7qgPUU8txYN5U5kGDuha2u0bQNrNAZrYBQVPB6IvKc1U1Q4d0XFujnWb7gFP7M0RTKF4DnL0gXPcaF9nNd1LbmAZlwtH4S/BRNyJyNJz8sPkpWJ1vJ+w9+EdEAs7/VwoDlrOhQJKQUiHca9+FeHLJmJxtGTjXhWthTaRMjWuREqreCJNOdE1trYIXuypxl2XVc8OE1jARfa3KGh2bHUZUlFauALsLVDNrHSZHZhyfQjnepCxNcruJlwcDMsQWr/dW9Tuot3N4n2D1jceQwAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Connection types&quot;
        title=&quot;&quot;
        src=&quot;/static/da0552d625b1181a8f0386f325666cf5/1b747/ConnectionTypes.png&quot;
        srcset=&quot;/static/da0552d625b1181a8f0386f325666cf5/4edbd/ConnectionTypes.png 175w,
/static/da0552d625b1181a8f0386f325666cf5/13ae7/ConnectionTypes.png 350w,
/static/da0552d625b1181a8f0386f325666cf5/1b747/ConnectionTypes.png 679w&quot;
        sizes=&quot;(max-width: 679px) 100vw, 679px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The system offers several options for storing passwords:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Manual entry: An unencrypted string, suitable for development. It will persist even after database restores.&lt;/li&gt;
&lt;li&gt;Encrypted: A secure option that encrypts the password value.&lt;/li&gt;
&lt;li&gt;Azure Key Vault: Links to the standard D365FO key vault for the most secure password storage.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;defining-outbound-message-types&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#defining-outbound-message-types&quot; aria-label=&quot;defining outbound message types permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Defining Outbound Message Types&lt;/h3&gt;
&lt;p&gt;Next, we&apos;ll configure the parameters for our data export in the &lt;strong&gt;Outbound message types&lt;/strong&gt; form.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 658px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/a1efdc7a5dc98a3d02e437f6aa3e254c/889a4/MessageTypeForm.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 68.57142857142857%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB+0lEQVR42p1UyY6bQBTk/w/5k9xyiXKNRjlbljITA7ax2aGb3WCWSvWziSaLfUhLpW4er+ttBdbWLfHhY4w0y5HrClmuEcQFoiSB0vpmV5pQPGe0FfRRiOJEdj8IaCtRNx3atoOlihrOuUJ/aXHpWnRE2zbo2hoZSb2Dx8sRyrJERdR1JSgYzPi1Le9dLhiGQWAdQo0o1fATZlcMgkT30NWA8+mIzWYD295ht9vBsW28vb7CcRw+/5Ag0zThOhjCG6n16esBX77Z+Pxi42WbYXu8EjOccEQch3D3LlzXgVK5wPOOLNOXc070XQ3bU3jbJxgHlvx9r+CeNOxTgX1Qw8+YGRGrAZoX4ijirjCNI8brVcquKpZcFIKhb5GXA/Ligunaw1rmGb+vRbDME0sqmIkS60w/AyyLPI8MYEqc6Sf+yw3W/BfhyrsIme0eUFb1rwumZ2Y/eh527G3dNLTNd0z/yvDOR3tZNvBjI6WK0+8EDQlMdhkllIi0FAOW6Pte3j8klOmxZ4+yN1I6n30Gy5ESWvo5/CchV0BBHznxNE0l2zTNRJNPCU3TTb9mnqf3GCdEkcnwhCgMeQ7g+2fR5eMeksg4mFLWgayTXrHcJ/7+/VPCotBwXFeI/yQxpRo9vg8ksnlGqNjsIIxkqgbmm12Xz4GYH8Z8D7CunyOtN/OX8YsjAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Outbound message types&quot;
        title=&quot;&quot;
        src=&quot;/static/a1efdc7a5dc98a3d02e437f6aa3e254c/889a4/MessageTypeForm.png&quot;
        srcset=&quot;/static/a1efdc7a5dc98a3d02e437f6aa3e254c/4edbd/MessageTypeForm.png 175w,
/static/a1efdc7a5dc98a3d02e437f6aa3e254c/13ae7/MessageTypeForm.png 350w,
/static/a1efdc7a5dc98a3d02e437f6aa3e254c/889a4/MessageTypeForm.png 658w&quot;
        sizes=&quot;(max-width: 658px) 100vw, 658px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Key settings:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Set &quot;Export type&quot; to &quot;Document on event&quot;&lt;/li&gt;
&lt;li&gt;Select our custom export class&lt;/li&gt;
&lt;li&gt;Specify the connection ID we just created&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;setting-up-integration-parameters&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#setting-up-integration-parameters&quot; aria-label=&quot;setting up integration parameters permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Setting Up Integration Parameters&lt;/h3&gt;
&lt;p&gt;For our integration, we also created the following parameters&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 651px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/6beb1f28d28853477d28fd6606da841f/1ac66/IntegrationParameters.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 61.71428571428571%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAA7EAAAOxAGVKw4bAAABgUlEQVR42p1TiW6cMBTk/z+w3SR7NgvmtvEJGHY6uMkqlbqrKpZGz4A9nnkeslLk2O12OJ9OKMsSVSUSijyHHgbM04hpDP+NrK4b7A8H5PkVoihwfX9HUeS4nM9QSiHGGRNJ53nCwnmcnyNrZIDSBuu6Io3bLZVlWdB1HdVW2A6tmxplVaNtW1x5eN20XPOx58vIjFYQoiBotRTJ5kBlzllYa2HMVg2cd+mQldhqXGKq6R3FfCLbFutBwejhju05kKDve6qqIKXEOI73TbcPF1/rndA9IPRUKKm0pW1jDPs4YeXGsWnQ7d8gfv5A9fKSan88wvJSo3PPCUWtUDV81jqpjbQ3Mwnb/HS5JPVbn43nDbNGrntIGLz/y8qnvZkk1nqoQVO5Tusiv0e2JdLJA0KJEBz+NeaqZCoCfhUd8kpisAv8AhL2zxQ+Jox1zcg0eH19Q8voNIRiGhYlv0c4i5Kxkjge9oxZAc25ZwJi/02FgX+TTxBw+Z8atr7ypqO1+A1d0ZtmXB18yAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Parameters setup&quot;
        title=&quot;&quot;
        src=&quot;/static/6beb1f28d28853477d28fd6606da841f/1ac66/IntegrationParameters.png&quot;
        srcset=&quot;/static/6beb1f28d28853477d28fd6606da841f/4edbd/IntegrationParameters.png 175w,
/static/6beb1f28d28853477d28fd6606da841f/13ae7/IntegrationParameters.png 350w,
/static/6beb1f28d28853477d28fd6606da841f/1ac66/IntegrationParameters.png 651w&quot;
        sizes=&quot;(max-width: 651px) 100vw, 651px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;For our specific integration, we&apos;ve created some additional parameters. You can find these in the integration parameters form:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Vendor Group&lt;/strong&gt;: This defines the filter for exported Purchase Orders.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Export on confirmation&lt;/strong&gt; option: This determines when the actual export (web service call) happens:
&lt;ul&gt;
&lt;li&gt;In the user session immediately after confirmation&lt;/li&gt;
&lt;li&gt;Via a periodic batch job&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;export-scenarios&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#export-scenarios&quot; aria-label=&quot;export scenarios permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Export scenarios&lt;/h2&gt;
&lt;h3 id=&quot;initial-export-of-the-data&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#initial-export-of-the-data&quot; aria-label=&quot;initial export of the data permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Initial Export of the Data&lt;/h3&gt;
&lt;p&gt;Some Purchase Orders (POs) may already exist in the database when setting up the integration. To export these, use the &quot;&lt;strong&gt;Export all&lt;/strong&gt;&quot; button on the &quot;&lt;strong&gt;Outbound message types&lt;/strong&gt;&quot; form. You&apos;ll see a standard query dialog like this:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 558px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/904537ce4b6f089c22f1f14920007253/42a8d/InitialQueryDialog.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 43.99999999999999%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABNklEQVR42q2SfU+DMBDG+f7fTo1uLrI5N1iB0hZa+gbl8cC5GP9ajJc86d01/cE9bRZCgFIdvA9YYp5nzOt6za+6NzLnLKqKwRiD/4isMx4nJlHWHbi0aJWDdjO6YULDBeqmQq97pCndB7Q+omQcXPRgNQG4grERPhK002hFC0tT3Ds2AUcUtUaIIyL5OY6RNP595ERflkMC70c03QTjE3o7f+VuAafr3/2+nPnW/6lssAGt1KgaCUYaCDLYEaq3OBUVjmeGTnuSRcHadX+xxNC5D9oXaoALae1bPyG7tA77YkBeaDxsS2xyjt1RIT9rPO0Ynt9qvL5L7EuDx90Fmz3H9iBwuFi85A3VLY5VwDujy20ImFLCIuccpJQ3/5b3KYQgb+OtVkphmqa1jtT33q/5N2Px8BOxpL0Aw3eUXQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Initial query dialog&quot;
        title=&quot;&quot;
        src=&quot;/static/904537ce4b6f089c22f1f14920007253/42a8d/InitialQueryDialog.png&quot;
        srcset=&quot;/static/904537ce4b6f089c22f1f14920007253/4edbd/InitialQueryDialog.png 175w,
/static/904537ce4b6f089c22f1f14920007253/13ae7/InitialQueryDialog.png 350w,
/static/904537ce4b6f089c22f1f14920007253/42a8d/InitialQueryDialog.png 558w&quot;
        sizes=&quot;(max-width: 558px) 100vw, 558px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;After running the query, all Purchase Orders matching your criteria will be processed. The system will add a record with the PO reference to the Export document log table, setting its status to &lt;strong&gt;To send&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/285fe16e07e976e1c4d16542e52b1ee6/58213/ExportLogInitial.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 40%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABdElEQVR42oWQ2XLkIAxF/f9flrekp9Lr2G7vGw0YDLaxq3MjmKSSt3k4xZUEV0KRMRZ6sliWGVqTNgaKMaj3d8zWws4z5DhiXhy2ff8vUdc2uJxPSJIYjA3YKenIRB0OWMl82zZszsG5FW5dsX7h1p/Y/SLiXKLrOSatYKYpPN42h/35DKc32oidtD9D7Vt/4X7pqB1G9EzQtySU0pBSYqQvCi7oVLSKhVahIYSApRX4Oucchqb3eb8OvxZf80RxbXHLOO7FgIYZ1L3GIFfcywdaZjHaD7QPg6KlJuaJrOK43TvUwxTuJ1mPkmoeH0ev8YSXo8Ix1UiaNVDxDxwTatL+03Flcc1V0KdU4M9twCVT8MO8nlu8XTocCF+LroXFKWZI8oEmWajLDDGRScbQ8RXSAM1gUTQq6CRnuMQN8lrSlAbnvzWuaRfIKjK8lfTlXNIFEQw83jCvRwzCBRPfqOoN5UHGI9LiQfEU8r5BWvJA2Wp8ArSYXdxHomM3AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;ExportLogInitial&quot;
        title=&quot;&quot;
        src=&quot;/static/285fe16e07e976e1c4d16542e52b1ee6/8c557/ExportLogInitial.png&quot;
        srcset=&quot;/static/285fe16e07e976e1c4d16542e52b1ee6/4edbd/ExportLogInitial.png 175w,
/static/285fe16e07e976e1c4d16542e52b1ee6/13ae7/ExportLogInitial.png 350w,
/static/285fe16e07e976e1c4d16542e52b1ee6/8c557/ExportLogInitial.png 700w,
/static/285fe16e07e976e1c4d16542e52b1ee6/58213/ExportLogInitial.png 902w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h3 id=&quot;periodic-batch-export&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#periodic-batch-export&quot; aria-label=&quot;periodic batch export permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Periodic Batch Export&lt;/h3&gt;
&lt;p&gt;The &lt;strong&gt;Export messages from log&lt;/strong&gt; periodic operation in D365FO process all records in the &lt;strong&gt;Export document log&lt;/strong&gt; table with a &lt;strong&gt;Status&lt;/strong&gt; = &lt;strong&gt;To send&lt;/strong&gt;. You can also manually export by selecting records and using the &lt;strong&gt;Export records&lt;/strong&gt; button:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 469px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/50269da3d7d8f7ad239d4fd46fb3a471/5f759/ExportDocumentLogPeriodic.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 66.28571428571429%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABp0lEQVR42o1TCW7jMAz0/z+59ZFEvmXdlo8pySZBuk0XK2AiRSZGQw5Z5G2D1hrWWhhjsCyLwNL5cZdzxv+uYl1X3G43TNOEYRgFfd8LxnFE27ZE7CT4OE6cJ37FF+F2YDYBiyW4hGnx8GlDPvBE2k7E/G+4eFAmK4qQdpSXEY2aMUwGVzVA0wOJgvibj5vskZj5jhHXQ+5esbgNKUYULHM0GR8qwPpEBAnOR0GIK7b9RKYsfEiwLgr4zJnlF+w753yioKqg6xSauqRaXnG5NLL3fQc9T/faHVLLimLqusI8z1Sz870p/KFpGigyZk0JkWSnOx6LCTmmqWsxK8YA75zE/iRkhfQ6v2qkZbTAWvNUwTurblgddYOm2JnUc1u9Lo4r+HXvrGDRTEpkRiOR2pfI9+dvZIdkWHCAGsjdzkD1C67tjIuaiDBSobnYu6T8AP9/h40GJAkhuId2aLLdhkzYqTW+p8GTIljzr2Y8a8g/5ccf9F0rKQfvn0S8eJKqqhKUZSnmcR0ZPJ6s7AchmxFCEOl/l4mVKaVoJAcZTzaPZ19MfEP4Cb6s86MBGAvQAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Export document log periodic&quot;
        title=&quot;&quot;
        src=&quot;/static/50269da3d7d8f7ad239d4fd46fb3a471/5f759/ExportDocumentLogPeriodic.png&quot;
        srcset=&quot;/static/50269da3d7d8f7ad239d4fd46fb3a471/4edbd/ExportDocumentLogPeriodic.png 175w,
/static/50269da3d7d8f7ad239d4fd46fb3a471/13ae7/ExportDocumentLogPeriodic.png 350w,
/static/50269da3d7d8f7ad239d4fd46fb3a471/5f759/ExportDocumentLogPeriodic.png 469w&quot;
        sizes=&quot;(max-width: 469px) 100vw, 469px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;After processing, you should see the exported orders on our site:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/ebc72495f6776c794cbe3ae849d86e00/4971b/ExportedOrders.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 63.42857142857142%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACFElEQVR42oWT2Y4SURCGz9v7AsYbvfLOmJhojA8gJgMOMgJCN8t099AbdNMLvS/Ab9UhEBxntJIvJ32W/1T9p1rsD0fUTYM0L+F4O1jrSGK6AY0h7E0Mk8Z1kCHKWsTELj+RXLGj+ShtIfI8R5okSNIUVd2grJj6QnUeaa3dH4jjs+wJkWYpUhLLixxlWZJAdaGu6ysq5Fkm9/4LMf4xhjpSMOwP8XNwh+7NDfq3t+h0Ouj2euh2u/TdR6/3HcbDCrtdgjCMEEXxk4h3g/f4+OszPow+QXMMeP4WtuvAsiyYpglN0+E4DmwiCAIS3CGO4wsJ20Wc58Xruzd4+/UVXn55geHgG9zJFNF6jYTKkxsJz/Mk680GURhSJpGEL3BdF7ZtY7vdSlGRBgXipQ5tpsHQDDyoCjLaVNLLs6fsy3w+l5muViaKopDz7GtI4jNVxWQygUWi/MDCj6llTAOr6RQ5ZVGTWEG3neNwOEhRFngc3G6cFV/CGadUldC1e/gbD8p4DG2xwGw6ga5rfx0+Ho+Sp+J6Xhi6Dt/3UZQV9dEeAZWxp6yeO/y/EGwmm8tlcfr8CNxz557kMaNS2B/muk95Tf4YdJbLrsgWwWK+72FKHir0IMv75aUVeCMbrygK1JmKxWIpLz2v+d7p3Gg4ohazaJ4au2laNGQuC/P4ONiGKD61Sdu2f3jGWXqUTJIm8mKu5Dfqh9of8cSPrAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Exported orders&quot;
        title=&quot;&quot;
        src=&quot;/static/ebc72495f6776c794cbe3ae849d86e00/8c557/ExportedOrders.png&quot;
        srcset=&quot;/static/ebc72495f6776c794cbe3ae849d86e00/4edbd/ExportedOrders.png 175w,
/static/ebc72495f6776c794cbe3ae849d86e00/13ae7/ExportedOrders.png 350w,
/static/ebc72495f6776c794cbe3ae849d86e00/8c557/ExportedOrders.png 700w,
/static/ebc72495f6776c794cbe3ae849d86e00/4971b/ExportedOrders.png 784w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;Reference&lt;/strong&gt; field will be populated for exported orders in D365FO:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 604px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/efc39306f79cc620487316f10975239f/87254/VendorRef.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 70.85714285714285%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACPUlEQVR42m1TaXMaMRTb///X2nxrSQIhQCHs5TXe+0aVvFmmydQzGt968nty0DYd+hEoyhZ106DhvGs5rmv0fY/MZjCZ5X6JNLvB2BzO5bA3C5fnyAuhQMXzSRQhGIeBGwUXS6hZa3Fzzo+rqkJL8mmaMBJ51eN4jpGTSGsD707TiHEckBpDMQ0CqcjzJUJZFriGIT6uHySrqapA23UM6BAnMW5UVdcVz0ScJ1617kutyQw6joNh6LG2pqlhTOoVSNHaxmH0F6Xqfr+jpzIFmueZ8/nxgnEcERS8HEUJwjBGRHUh1cUR+/CKhCqElDApeyKJl3NSOotEzybRisCYG7b7Mw6nkMQpDu977Pd7ksSfSGD5HJulfu6cRcuXdG2Dvmu/QGuB4aHfm194e9syeog/pyNJD8hI8Pr6gu12i8v5zP4Fz5sNFcdUMmDoO6L97Bd4wobSO1YnSTImN8d9npbKMbd6wsz5/JgPzFP/hWRVN3QLedDQFre8RWIbVpqHeHH0RLPvVVlHGylXsseSs8kXQvlXUFbGn1fwQAaOU0d1jp5rMPnK3X115bOQZo1YiMzKGhmtVfr9mdC4pFdr5lTBtc4nizBHSXVaXDfURK6cGZpWPyZNUz8ePs/IyPpdZVV6xUIg78mgi+sXL6nXE9R08TvWdRlfd2d5cV68GCih2lwjrFgJ/9sYtDoesPv5A29PT8j276iPR0z800HXtQ+Cf/E9gIeKpZ/Ci5Z2Si4XOJo84ydIdzu40wl/AdIRN6oajfA0AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Vendor reference&quot;
        title=&quot;&quot;
        src=&quot;/static/efc39306f79cc620487316f10975239f/87254/VendorRef.png&quot;
        srcset=&quot;/static/efc39306f79cc620487316f10975239f/4edbd/VendorRef.png 175w,
/static/efc39306f79cc620487316f10975239f/13ae7/VendorRef.png 350w,
/static/efc39306f79cc620487316f10975239f/87254/VendorRef.png 604w&quot;
        sizes=&quot;(max-width: 604px) 100vw, 604px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;If you&apos;ve enabled full logging, you can check the exact message sent in the &lt;strong&gt;Export document log&lt;/strong&gt; form:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/8b825e093350939b0ce20252bfd006c6/6bbf7/ExportLogLog.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 54.85714285714286%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABpElEQVR42p2SW4+bMBCF+f8/bF+6l24FbJaEqzGYNAabQMCAOB2TVaqoedla+nQOYzMeycdRSkG3PZTW6PsOteqgVAOtFZq6wbltYc/YWtM0kFJiHA2maXqIkyYR0jRBFIZgGYM8/YYZB4zDZePOm+FWmyxm/Aen4AycczDGUBYF+QLLPN2YjcEyXb39YSZvedTs2vAQoM1SyDhCncSQKdu0oakVS9GXBTTta5ZhrMTmFZ2ddINlsReZOxz36RlvPxK8PIfw3RzJvoT36sL/6WL37qOIOd5fA+zcDCyW8H7F8N8OyAMOoVeIZiaWGw6LaBohkYcZjjlNcJQokwxFlECQ6uqEKuNQlcT5pHDiFdUkhm6AWQAzr3c4lShh17qu+N5aHwA44r8bPl6OOOxxphe+CLE9gOVSln+hC3tx1Q2qdQVHR8nY9Mv3VJ8nepSaGpZRhIo2qjyH4DmOhYVvXpAXOUWKsCooZprC3VPwOwp7p2oKv0ZLyTDnlhpGIQrXBfvwwC3+l+4+NmWe/faR+y7hbVTBJ6r9J0QQELttX9Jg03DBH+pSQl6WiNthAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;ExportLogLog&quot;
        title=&quot;&quot;
        src=&quot;/static/8b825e093350939b0ce20252bfd006c6/8c557/ExportLogLog.png&quot;
        srcset=&quot;/static/8b825e093350939b0ce20252bfd006c6/4edbd/ExportLogLog.png 175w,
/static/8b825e093350939b0ce20252bfd006c6/13ae7/ExportLogLog.png 350w,
/static/8b825e093350939b0ce20252bfd006c6/8c557/ExportLogLog.png 700w,
/static/8b825e093350939b0ce20252bfd006c6/6bbf7/ExportLogLog.png 716w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;After a successful export, the &lt;strong&gt;Export Status&lt;/strong&gt; field for the &lt;strong&gt;Export document log&lt;/strong&gt; table will change to &lt;strong&gt;Sent&lt;/strong&gt;:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 455px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/af5d88957f81f4a23e92dbb9496c5c0e/379c3/ExportLogStatus.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 104.57142857142858%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAVCAYAAABG1c6oAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACYUlEQVR42p1UaXebQAz0//95TdKkic1hFgx4gT24cd9Uko+6qZ9zfNDjsBmNZka76roB0wyU2sO3LZZ5xjD2MP6AWBWoGw1nHXRVodIaTWPQdh3KfYGqrqB1ha7voLIUeVFg5b1DXdeoqxqmOVata4zDiLalJs6io0beOanWe3QdPXu+P77rqYG1hhobrKxp8Pz8hCDY4O31Va5hGCDLMox9L4yXecJhmeTKNU8jDvP1M/8+S62YwQsBPjw+4PHxB6JwgyhY4+n5Jwx15A+mcbgUg92r1dC36EmDlsYYhgFb1s04GrnHRCVsTt0Ph/ljwI50KoucNNSkTQ+VGwJsSb8TKLFiXZuaq5KP7rGlkQ02619Iki2Y7ThwdRd9emIebNai62b9BkcSCduTlv8BWopEkFSIU4001xKVrGxg/YCF/sAsd7sMu3yHNE0QxxFFZS9uLzdAV8Z6vEQWaWFlVNeOlMERjesFcKJMpqkSIKUUcgJPkgR6T6ASKf9OQ2+l877kEFcUcgKZ/uozkGF7+rgsS+x1KYx/H5ab7C6mZJmSUHanIDtrRbuzAcdAu6N5V8bcBGyJIY8SxbH8+brzezevg303NlmaIopCFMXutE72xNRcmH62hOGWIsMuMtg5yB8xuctQkWthQDmjlePw8ruvMvuX4TYmHRNyuRbNzhvyGc1uMozCkHIWX5idiyX4uoYkfkZh5fCyy7zDZ1P4zPvMCfNuZEcjR+RyIEdXELzJzoZ0ryjwzHqZvwioshxpViJROYqSt6KQU/xegO9o2ELtDB0ODYJtg6qijfH22y7/AeWXTsR07AADAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;ExportLogStatus&quot;
        title=&quot;&quot;
        src=&quot;/static/af5d88957f81f4a23e92dbb9496c5c0e/379c3/ExportLogStatus.png&quot;
        srcset=&quot;/static/af5d88957f81f4a23e92dbb9496c5c0e/4edbd/ExportLogStatus.png 175w,
/static/af5d88957f81f4a23e92dbb9496c5c0e/13ae7/ExportLogStatus.png 350w,
/static/af5d88957f81f4a23e92dbb9496c5c0e/379c3/ExportLogStatus.png 455w&quot;
        sizes=&quot;(max-width: 455px) 100vw, 455px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h3 id=&quot;export-from-the-user-session&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#export-from-the-user-session&quot; aria-label=&quot;export from the user session permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Export from the User Session&lt;/h3&gt;
&lt;p&gt;When a user runs a Purchase order confirmation, if any &lt;strong&gt;Export document log&lt;/strong&gt; records were created during this process, the system runs the export immediately after the main operation. The status will be displayed to the user.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 515px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/062a1e72e31a92e2753d6185153a4cc8/fbdcb/ConfirmButton.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 52.57142857142857%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACDElEQVR42l1S127bQBDkVwfI7+Qp35ACJA8KEKvGVrW62GkdeZTFcmzjOYoyjCww2HLL2Ubj+0zg56OJ34sAPyYmfs08jByFgZVjYHeaGGqb8afDKxZTB0+M/fNrTLzqhs42xkeJ0S7A5HBGf+Ohv/Yxpv332cNwL1p/sNHvggQZ1t96sD59xubLVzyvbGxjYC1KrMMKm6iGURQN0qyGd04hwgiqqBBfLsjzHJdOy0jCdX34QQAhI5imhd12j1jHPRdnESKMQjiuCwOUNM2QqxJ1XaMsy5ZI66apUVUllFLUFUraDXMS1cA+J5CXBBXzdO79W0MbJ/MEycp1XZEshmlZkHHcJslYIgzDljxTObI8gyJkJGDZFpIk5RSKU2YoioKETXPrkMEkuWK72zHRxv5wQMakjCO3mnAcGybh+n5bzPMDHE8nwsT1euUkxW3khqRadMu6s0hK7rJ4j2vRBB/cm3T+Pa7XYURs3TwdYVsmHI7guU4L3Y1NvwXf3m3Com91Mec/GJFUcPwrvJeEOoEQEcmYbJ3geU6724K7U93u8ixFQV2om51yTR9hLJcL9P708NB/wGA4gMvOprMp5os5ZvMZfQuj8RhPj49YLJfYbzfUCwxHY6xWq7ZYWah3GNfXC84vAaJQIOK/9Mor664uvG5M6KpCvBBnXlu08SDw2b2HWO+aR9Okd7wBWdc8IQNj574AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Confirm button&quot;
        title=&quot;&quot;
        src=&quot;/static/062a1e72e31a92e2753d6185153a4cc8/fbdcb/ConfirmButton.png&quot;
        srcset=&quot;/static/062a1e72e31a92e2753d6185153a4cc8/4edbd/ConfirmButton.png 175w,
/static/062a1e72e31a92e2753d6185153a4cc8/13ae7/ConfirmButton.png 350w,
/static/062a1e72e31a92e2753d6185153a4cc8/fbdcb/ConfirmButton.png 515w&quot;
        sizes=&quot;(max-width: 515px) 100vw, 515px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;If an error occurs during the export, it will be displayed to the user, but the Confirmation process will not be affected. This allows for real-time feedback while ensuring the main business process isn&apos;t disrupted.&lt;/p&gt;
&lt;h2 id=&quot;handling-export-errors&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#handling-export-errors&quot; aria-label=&quot;handling export errors permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Handling Export Errors&lt;/h2&gt;
&lt;p&gt;If an exception occurs during the export, the &lt;strong&gt;Export document log&lt;/strong&gt; record will remain in the &lt;strong&gt;To send&lt;/strong&gt; status. An additional log will be generated with the workload details and exception text.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/dba48c30ae1d5e5a7a9a956d4f044ea4/84cc5/DocumentLogError.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 57.14285714285714%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB10lEQVR42q2T29KTMBSF8RG81gt9Ap/b+8545TM4joeqpfQv4ZwQQighgcByQ7W1o5dm5puVvZO9yIkgoNZIseNViTA8+ITF6C8dRmev2OGKG245Z4cZ1JyzEaCerx4UPgt+N6X0TvcjlGp912nYYS12VEgG44hxmuBInXVb3lp7NbRkqP5lqLudcYBoLl62Bo0eoIjOTOBxjjxikLnY8ut4e3GzHQGpTaQUHg2FiF9Ipd9XyiNKW5/yHkcmsKroFhw/hQi/MWRRgWMi8Z2Uld1SNhY/TmUsL+7Nsiwvh2F4TbwKtNbgvEYtW7TagJIwxtC2LXqiywvw/R7yTGcrajo3t41Zu219i+9YBHHR4e27D/h6rFDJHvso31aY1wNOmULBJA4fQ5z2MfIwg9AzROtJ/VV/wWmHqhsRTOME7xfM8wxaOumdLfYzJlrN5Eb4yT+M/wVdXrAa/a+2egVtHMNwDlNxDPyO4dVDvOWq6sYtL8QfcyoE6ZfPyBK6xfiJOCN5OoFFR+T0wNc4ow/m7Iz0/IQyTVDQ3FWV4Bt1WUKRWUP9ljEExeGAJMuQpSnSLMGZCmMyYmSYUDGjSTH1GZmK1UQ1qGtBKulFGHoRPQbC0N90qUr8BGAVGrVvlaSkAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Document log errors&quot;
        title=&quot;&quot;
        src=&quot;/static/dba48c30ae1d5e5a7a9a956d4f044ea4/8c557/DocumentLogError.png&quot;
        srcset=&quot;/static/dba48c30ae1d5e5a7a9a956d4f044ea4/4edbd/DocumentLogError.png 175w,
/static/dba48c30ae1d5e5a7a9a956d4f044ea4/13ae7/DocumentLogError.png 350w,
/static/dba48c30ae1d5e5a7a9a956d4f044ea4/8c557/DocumentLogError.png 700w,
/static/dba48c30ae1d5e5a7a9a956d4f044ea4/84cc5/DocumentLogError.png 898w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;For example, if a Purchase order contains a service Item (without ItemId), but our test web service doesn&apos;t accept such data, you&apos;ll see an error logged.&lt;/p&gt;
&lt;p&gt;It&apos;s important to note that the &lt;strong&gt;Export document log&lt;/strong&gt; has only two statuses (&lt;strong&gt;To send&lt;/strong&gt; and &lt;strong&gt;Sent&lt;/strong&gt;); there&apos;s no specific Error status. From a business perspective, it doesn&apos;t matter whether the record wasn&apos;t exported or if the export failed. The key is that the record needs attention. For effective monitoring, set up your alerting system to flag records that stay in the &lt;strong&gt;To send&lt;/strong&gt; status longer than your defined threshold.&lt;/p&gt;
&lt;h2 id=&quot;troubleshooting-and-monitoring&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#troubleshooting-and-monitoring&quot; aria-label=&quot;troubleshooting and monitoring permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Troubleshooting and Monitoring&lt;/h2&gt;
&lt;p&gt;Integration can be complex, and proper tracing to identify issues is vital for the whole process. Let&apos;s explore the different options that the External integration framework provides for troubleshooting and monitoring:&lt;/p&gt;
&lt;h3 id=&quot;tracing-the-call&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#tracing-the-call&quot; aria-label=&quot;tracing the call permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Tracing the call&lt;/h3&gt;
&lt;p&gt;One of the most common issues with service calls is when the Web service doesn&apos;t process the call properly but returns a success code. For example, when we send an update to an existing PO, the update might fail for some reason, but no error code is returned. This results in mismatched data between the systems.&lt;/p&gt;
&lt;p&gt;To trace this error, we need to use the external PO ID to find an export record using &lt;strong&gt;Document ID&lt;/strong&gt; and see the full history of exports.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 687px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/0bb7430311f744a41ea5be2587cc2efd/aec65/DocumentLogTracing.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 75.99999999999999%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACsUlEQVR42n2U246UQBCGiTfG5/HGl/NGH8IL7030FYyJUWOyTjZxXd2Z4Qwz0NAwQDfnU/8Ws6PurMZOvvx/dUN1FTRo+4CteCphe/s5ZBH8PcfWcGDZCy4cz4fr72FaLukOhuXAdncq5gdEcTIlSfJYowHgwaJaU5UrmoTve3MY7MDCEAnnyA4purbB0HcYh/6kHWmLvmvVPI3L/DQMw3lCIfJVsN/BNI3ZcWw4jgMhilOS481HhhPHuG3VsgF5SlifJ6zKcpWXA3JRzU1To+u6I/1yQ9+jHwZQFbf+FHdU4UAbtk0z1fW9CqUUly0lOqTJLEUGKXKUVKEgXyQxks0asaHjYFvIXQeZZULkmZJ0TVOXS4VPTgkfKaUeankuV2E24dpK529mApdV0P0CZiDpMTBsPn/F9Tcbvs0RhRLW6gdujFC5UY0oH6ek+KtCGRb1hFR0KqsGyG5G2So0A1DVPWLLR+JHONDbjz2GlHzVTqruFUTZz3XdvWya5mnbts+JZ5qkNg6ba0hXR/z+HZw3r8EvL1C4JnJLRxX4EJ6NzDFQky93dL2xRu3bwNQDSuHu0ELdUR++WHjx6hMuLi0wluHqxsfGirC2GPZRBcs7QHdTxPkILxAwKN5tdoizAXExTTT/Gy02bHzfeHj78QqGGyKXNXRq84jpgfEcjk+JwwRpXh+V8QJsayGKDoiT4gxN2iZGFgBZgpEzdGGAPgrPGCKGnt2ZI994LrU7UZPzHRQ0eqDopwn9OGJYID+Md5ju+VM8zzP+NbROCsylJMr/oqrzeBTiHClBhxIap4PL6NCmvg/uLUfEQ7pb9Nb/Uk4tLp6Tz4IAZRz/gf4FgtabhN8mdLcbONst6RaesaAf1SW1l3V9c6u0bm/X2Ns2OH3/fO8jps1D2ihYr9HwGD8BSiMyRGlIR7IAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Document log trace&quot;
        title=&quot;&quot;
        src=&quot;/static/0bb7430311f744a41ea5be2587cc2efd/aec65/DocumentLogTracing.png&quot;
        srcset=&quot;/static/0bb7430311f744a41ea5be2587cc2efd/4edbd/DocumentLogTracing.png 175w,
/static/0bb7430311f744a41ea5be2587cc2efd/13ae7/DocumentLogTracing.png 350w,
/static/0bb7430311f744a41ea5be2587cc2efd/aec65/DocumentLogTracing.png 687w&quot;
        sizes=&quot;(max-width: 687px) 100vw, 687px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Using this information, we can determine on which side the error occurred and take steps to fix it.&lt;/p&gt;
&lt;h3 id=&quot;manual-test-form&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#manual-test-form&quot; aria-label=&quot;manual test form permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Manual Test Form&lt;/h3&gt;
&lt;p&gt;Another useful tool for troubleshooting is the &lt;strong&gt;Manual test&lt;/strong&gt; form. This form offers several  options:&lt;/p&gt;
&lt;h4 id=&quot;init-from-document-button&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#init-from-document-button&quot; aria-label=&quot;init from document button permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&quot;Init from document&quot; button&lt;/h4&gt;
&lt;p&gt;This button allows you to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Select a Purchase order number ignoring existing validations.&lt;/li&gt;
&lt;li&gt;See how this document will be represented in the data.&lt;/li&gt;
&lt;li&gt;Display the workload without actually sending it&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;call-create-button&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#call-create-button&quot; aria-label=&quot;call create button permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&quot;Call Create&quot; button&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Take input data (which can be previously generated by the &quot;Init from document&quot; button and then modified by the user)&lt;/li&gt;
&lt;li&gt;Perform a call with this data.&lt;/li&gt;
&lt;li&gt;Display the results&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 627px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/bcd89cf07cbbb4392ea537d1110060f2/e9c9b/TestWebService.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 85.14285714285714%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAARCAYAAADdRIy+AAAACXBIWXMAAA7EAAAOxAGVKw4bAAACAUlEQVR42qVUTW/TQBT0//8ZqIUDBzigllzgQIWAckGiQUnjJI4TxxvbiXe9/nY9zLpJleRQ0rDS6D3v2uN5741tXX2+xUXvJ970fuDVh6+4vP6Oy4/cY7y4Iq6/4XXvFm8//cL7mz9496X/LKyyyFFWLaI4Rc5cKYVEK0glmSfQicYm3kCnGR5a/HNZkjcrKZEYIiU7KBkj1RpZypdkKeMuz1Dkz8MyD4/HNkajIfr9Pu76d7DtEQkTNHWJqixQV4/xFFg6UfB9D9PpGP7Sw5LQJDMk5YkkR4QSjiswtJdYr9ePPSRMqaaEMwgVhO/DdV0sFnO4cxe+8LsYReHLCc0QHGeKwXCAKAzwUFdPh3XFyNLrLRqe7WKz3TMuOSJUCFZBp1IIQVURVkHA8iOEYUjLxIi2uaDybj8IEYQrSLqjyPOD1limZ/7Sx9z1MJ468DyPPZ3B46CcmcvrJSaTCQajezhsyWw+gz2edN5s2xZNUyPfJzRD6RSKAAs+HFCdx0n7gUBMdQZRGEHwnlgqhFRoFMdUp2h6SUEHCj2xoWkTZDRtSvNqnXaTVjS2UbC/zOVuz0SDqqoOCTebmEmJc1fTNIeECb+UsvgfwvqIkLYxk5RK86eQEemLYPp4QCip8PdozUN6qqL88nSURJo3nHKxTygR6/rskqumRZbT5FvCv5K5FpZwEy1OAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Test web service&quot;
        title=&quot;&quot;
        src=&quot;/static/bcd89cf07cbbb4392ea537d1110060f2/e9c9b/TestWebService.png&quot;
        srcset=&quot;/static/bcd89cf07cbbb4392ea537d1110060f2/4edbd/TestWebService.png 175w,
/static/bcd89cf07cbbb4392ea537d1110060f2/13ae7/TestWebService.png 350w,
/static/bcd89cf07cbbb4392ea537d1110060f2/e9c9b/TestWebService.png 627w&quot;
        sizes=&quot;(max-width: 627px) 100vw, 627px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The advantage of this approach is that it allows you to test the webservice without using any external tools like Postman. This can be very helpful in troubleshooting scenarios.&lt;/p&gt;
&lt;h3 id=&quot;monitoring&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#monitoring&quot; aria-label=&quot;monitoring permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Monitoring&lt;/h3&gt;
&lt;p&gt;Monitoring can be done using External Integration workspace that displays statistics for a given period and number of not exported records.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/ee62f604f48c94ea5f5debd9f46c1d44/2bef9/ExternalIntegrationWorkspace.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 45.142857142857146%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB/ElEQVR42m1SPWgUQRTe1voarxGxsBHtBIMSFRWxEJU0IgQttBD/KkWbmB8wiKZQsbIwGlDxBzs7wVYQUQTPSHJJdrO3/7d7M7u3O7O79/l2LncoOPDx3sy873vfPEZzrBZapgHfs+G5FqToAiiAXq7QK+UwV/sqVvcbyKUgTqYghIDWsh38WtKxsuZgedWCafvQWwTTx5rpwXZDOgv6sAIYdLfYtIbgPP5HVLs3/xGbdt/ClkN3sPXwLEbGH2LzwSnUR6dR3z+t9rV9E6iNTKK25zbGb7zA2ZsvCa8wdvUZvv3UldMsS8khCT5Y+IT6gRnsOH4f247MYvTcY+w6NYedJ+aw/dhdnL6+gLFr8zh5+Sn2nnmEz9+bqFaRC5SFHDrrP5kEX3/4Sp2e48LEG9X5ysx7XJx8i0tT73D0/BN8+bGqBMqyP8PqeSIjcuXoP9A4i5ClMTEkeoUgQkbkgoZfUJRKINsorlwM5lXFIpeEnJz2kUsJLYpCuK6LmDMknCOMGNyA8jSH5wdot9s0eA7GmKrzfB9xzJF0JYQsIToRuoGPjOpEGELrMBKhpCJJcheyFMvrDIabouUlMByuohdJ6DbDitnGusPgdXI4QQZ90cDSbxONhg6j0YSWkDNGXTjrqJjRfKrVA4ZxkOOvs8Eq6e8VSULoQsQJ/gB2SXqI4nW22gAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Monitoring&quot;
        title=&quot;&quot;
        src=&quot;/static/ee62f604f48c94ea5f5debd9f46c1d44/8c557/ExternalIntegrationWorkspace.png&quot;
        srcset=&quot;/static/ee62f604f48c94ea5f5debd9f46c1d44/4edbd/ExternalIntegrationWorkspace.png 175w,
/static/ee62f604f48c94ea5f5debd9f46c1d44/13ae7/ExternalIntegrationWorkspace.png 350w,
/static/ee62f604f48c94ea5f5debd9f46c1d44/8c557/ExternalIntegrationWorkspace.png 700w,
/static/ee62f604f48c94ea5f5debd9f46c1d44/2bef9/ExternalIntegrationWorkspace.png 1024w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;This dashboard gives you a quick overview of your integration&apos;s health and performance, allowing you to spot issues early and take action.&lt;/p&gt;
&lt;h2 id=&quot;performance-testing&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#performance-testing&quot; aria-label=&quot;performance testing permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Performance testing&lt;/h2&gt;
&lt;p&gt;The External integration framework provides a simple performance test operation to assess the speed of our integration. Let&apos;s explore how this works and what insights we can gain from it.&lt;/p&gt;
&lt;h3 id=&quot;how-it-works&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#how-it-works&quot; aria-label=&quot;how it works permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;How It Works&lt;/h3&gt;
&lt;p&gt;The performance testing process involves several steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;First, you need to create a set of documents that are ready for export. These will serve as your test data.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Next, run the &lt;strong&gt;Performance test&lt;/strong&gt; operation. This operation allows you to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Specify a standard query filter for the &lt;strong&gt;Export document log&lt;/strong&gt; table (this means you can create multiple clients if needed)&lt;/li&gt;
&lt;li&gt;Run processing of these records in a loop for a specified period (set by the &lt;strong&gt;Duration&lt;/strong&gt; parameter)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The test can be run in two modes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Reusing the same connections to export documents&lt;/li&gt;
&lt;li&gt;Creating a new connection (instance of HttpClient class) for every export line&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Here&apos;s what the &lt;strong&gt;Performance test&lt;/strong&gt; operation form looks like:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 491px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/7fb00e91e23708353b9b2d7c2f7b71a2/13566/PerformanceTest.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 77.14285714285715%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB1klEQVR42p1U7XarIBDs+79jE1NrEkX8RBDFTGeJmjbpj3vLOXs4ybLD7MziW920UKrA9XpFURTQWnNXKMsyhlIKTdPgX9btdsPbOI6w1mEYBhjTx30wBvJ/13VIkgRZlqFt25iz1sI5F3PzPG9QEWxZFgIy2ROoJLOu73/cOE1TZFxXdQQIIfAyC+ssWdfw3sdz8v/oRpTsJjI0vYFiezVbk2SYQ9wnFghQVWmcz2ecLxdeUEW2Uiz5G1kFMp15eU7ZCOjQtA0BFbXLo57Pa5o8CiX6lpGZtP3bKvL8Drgsd0aiiWM7osez2HJGtJrnKZ59zS8b4AhdamTnS9RRWuu6ftdGDn6Prfh7iNbWDshztuz9CDcG5NpT5JkF96KXELAtXvLLg6EANnWN5HTC6TNFTrGXFfR/1w4oA304HAmaIE1Ttp/RBPVXQM8500g/TvggS3F5iANu/gYoLnd9yxmsUFZ8aiWfYX7ZR+NXPZ8iBJmOkaasLbe9g9IGupboUeguDuoiLjN2U0T8sEXYQwZbOl1ddvDTgs5MMHbms5r4+2GIuDd6Hwtkj+B4sHtpWQb1czWi5iswq3bbYcMPxfvhHYfjEUeaJl+gqqo4uxW1Hn6ACuAXVfePnJPy6pUAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Performance test operation&quot;
        title=&quot;&quot;
        src=&quot;/static/7fb00e91e23708353b9b2d7c2f7b71a2/13566/PerformanceTest.png&quot;
        srcset=&quot;/static/7fb00e91e23708353b9b2d7c2f7b71a2/4edbd/PerformanceTest.png 175w,
/static/7fb00e91e23708353b9b2d7c2f7b71a2/13ae7/PerformanceTest.png 350w,
/static/7fb00e91e23708353b9b2d7c2f7b71a2/13566/PerformanceTest.png 491w&quot;
        sizes=&quot;(max-width: 491px) 100vw, 491px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;For our webservice, I ran the performance test for 60 seconds and got the following results:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;When creating a new connection for every line: 350 exports/minute&lt;/li&gt;
&lt;li&gt;When reusing the same connection (cached): 700 exports/minute&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These results highlight an important point: creating a new connection is a complex operation. It can be even more time-consuming if authentication is involved.&lt;/p&gt;
&lt;h2 id=&quot;resources-for-this-blog-post&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#resources-for-this-blog-post&quot; aria-label=&quot;resources for this blog post permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Resources for This Blog Post&lt;/h2&gt;
&lt;p&gt;All resources used in this blog are available on &lt;a href=&quot;https://github.com/TrudAX/XppTools/tree/master/DEVTutorial/DEVExternalIntegrationSamples&quot;&gt;GitHub&lt;/a&gt;. Let&apos;s take a look at what&apos;s included and how you can use these resources for your own integration projects.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 423px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/54b06777d0da723b04cd01acf70fce99/f687d/ProjectStructure.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 74.28571428571428%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACUUlEQVR42oVTaW/aQBTk//+TKE0vNW1Jm0rth0iNlLtgbLO+DZTLXoNPjunsgiLUUuXD03tvvTvMvDe0zn+EaF/FeH9p4t2lgZPzW5x+esQrxtuv6szE6cd7nHy447cbvLnosH/A2ecnvG4/4az9i3cfdP5+l6DVcxKMZg1unzxcXRv4eWPi+taCCBMEwyX8wQJulMKLJbxI6l5lJ0z35xnrRNfRuERrLksslhUKOYVpdNEXPlw3gFzk2GyB1XqLNYtmtWUN1n/Fdh+smxXQGs8LFNUadbPFxZdvuL/vQDgR7D6B/QGECOF6MfxgyDxAGI9R1FtUDVDyjaoPozUhYJKVWKYzhGEEwxSYTDMyrJHIAilD56yA5L00q5grZirLG5QEOQzNsCZV9Yt9x4dh2AwBoydg2h7rPkzLRa/nkGGkz1SvzsfTxY7pIaBiqA4rNupBr0cAkwCmo2Wb+2zZPjw/hkP5w9EMk5lEtcJxhg2HrVg6GpAMyUYxtGwXnY6JLll3u0KDK4YKqD4C9sxQzSOXtIHw+FjA5iOLsmwRYDCa6+9qjvM0x3S+4BI3R8GeAct6g6KoYLk7Znp+BFTRdwJuO9abVmBKzf/ADhhWZJhQoq1nJReVjmVeI6NHd+yWR7d6nKGSQC8qmWpejhvT4AG9N2IdYZ7ke2ablwGfbcPGo3kFgWyy1HJZW/ssnJCbzfTdF2eoJOVyBtvqo0N/qeGncrcsZeJE5oxSjyEv1y9L1j7Uxg4oMYQfjiCYg+g3ZQ90xMMpfP4VR5P0HzMfAv4BLXdjx6pJ11UAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Project structure&quot;
        title=&quot;&quot;
        src=&quot;/static/54b06777d0da723b04cd01acf70fce99/f687d/ProjectStructure.png&quot;
        srcset=&quot;/static/54b06777d0da723b04cd01acf70fce99/4edbd/ProjectStructure.png 175w,
/static/54b06777d0da723b04cd01acf70fce99/13ae7/ProjectStructure.png 350w,
/static/54b06777d0da723b04cd01acf70fce99/f687d/ProjectStructure.png 423w&quot;
        sizes=&quot;(max-width: 423px) 100vw, 423px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;To implement your own D365FO integration with a webservice, you&apos;ll need to create two main classes:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;A class similar to &lt;a href=&quot;https://github.com/TrudAX/XppTools/blob/master/DEVTutorial/DEVExternalIntegrationSamples/AxClass/DEVIntegTutorialExportPurchLoad.xml&quot;&gt;DEVIntegTutorialExportPurchLoad&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;This class handles the interaction with the custom Webservice(if we use Azure service bus or File share, it is not needed)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;A class similar to &lt;a href=&quot;https://github.com/TrudAX/XppTools/blob/master/DEVTutorial/DEVExternalIntegrationSamples/AxClass/DEVIntegTutorialExportPurchOrder.xml&quot;&gt;DEVIntegTutorialExportPurchOrder&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;This class defines the export document structure.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Additionally, you should create a form for manual testing of these classes, similar to &lt;a href=&quot;https://github.com/TrudAX/XppTools/blob/master/DEVTutorial/DEVExternalIntegrationSamples/AxForm/DEVIntegTutorialTestWebCall.xml&quot;&gt;DEVIntegTutorialTestWebCall&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Once these components are in place, the External integration framework will handle all other aspects of the integration process.&lt;/p&gt;
&lt;h3 id=&quot;sample-web-app&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#sample-web-app&quot; aria-label=&quot;sample web app permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Sample Web App&lt;/h3&gt;
&lt;p&gt;For testing purposes, I&apos;ve set up a sample web app. At the time of publishing this post, it is deployed at the following address: &lt;a href=&quot;https://purchaseorderapp20240916.azurewebsites.net/&quot;&gt;https://purchaseorderapp20240916.azurewebsites.net/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The source code for this test web service is also available on [GitHub] (&lt;a href=&quot;https://github.com/TrudAX/TestWebService_PurchaseOrderApp&quot;&gt;https://github.com/TrudAX/TestWebService_PurchaseOrderApp&lt;/a&gt;)&lt;/p&gt;
&lt;h2 id=&quot;summary&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#summary&quot; aria-label=&quot;summary permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Summary&lt;/h2&gt;
&lt;p&gt;In this post, I have described how to implement event-based exports from Dynamics 365 Finance and Operations to Web Service using the &lt;strong&gt;External Integration&lt;/strong&gt; framework. We discussed the following key topics:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How to design such integration&lt;/li&gt;
&lt;li&gt;Sample implementations of how to call a web service and how to create a document class&lt;/li&gt;
&lt;li&gt;How to monitor typical issues with such integration&lt;/li&gt;
&lt;li&gt;How to perform performance testing&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I hope you find this information useful. As always, if you see any improvements or suggestions or have questions about this work, don&apos;t hesitate to contact me.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Implement Periodic Data Export from D365FO to SFTP]]></title><description><![CDATA[This blog post describes how to implement various scenarios for periodic data export from D365FO to a file and uploading it to SFTP server.]]></description><link>https://denistrunin.com/integration-outboundsftp/</link><guid isPermaLink="false">https://denistrunin.com/integration-outboundsftp/</guid><pubDate>Fri, 12 Jul 2024 22:12:03 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;External integration&lt;/strong&gt; is a &lt;a href=&quot;https://github.com/TrudAX/XppTools?tab=readme-ov-file#devexternalintegration-submodel&quot;&gt;framework&lt;/a&gt; designed for inbound and outbound integrations in D365FO. It supports several channels: Azure file share, SFTP, Azure service bus, and provides comprehensive features for logging, error handling, and troubleshooting.&lt;/p&gt;
&lt;p&gt;In this blog post, I will describe how to implement periodic data export from D365FO to a file and upload it to an SFTP server.&lt;/p&gt;
&lt;h2 id=&quot;sftp-server-setup&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#sftp-server-setup&quot; aria-label=&quot;sftp server setup permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;SFTP Server Setup&lt;/h2&gt;
&lt;p&gt;A few years ago, Microsoft did not support SFTP hosting, claiming it was obsolete in the cloud world. However, SFTP remains quite popular among clients and eventually, SFTP support was included in the Azure storage service.&lt;/p&gt;
&lt;p&gt;To use Azure storage via an SFTP endpoint, you must first create a storage account and enable SFTP access. More information can be found here: &lt;a href=&quot;https://learn.microsoft.com/en-us/azure/storage/blobs/secure-file-transfer-protocol-support&quot;&gt;SSH File Transfer Protocol (SFTP) support for Azure Blob Storage&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 580px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/f8b69a486f07a7e6449ed54766cd0e4c/b6272/SFTPSetup.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 129.14285714285714%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAaCAYAAAC3g3x9AAAACXBIWXMAAA7EAAAOxAGVKw4bAAADT0lEQVR42q1VS48OQRTtlZUf4ScI8WPY2Nnbi70IIpNIxHIWMsTKekiEREjIjGAwgpnv1e9n9bu/457qrp6HkRF0clO3q6vv89xT1rnbWzhx5T1OXfuEMytfcfr2Ns6ubOPk1Q+4/HiKO89muL4+wY0nU9x6OsNNkX6d4oasK89t3H3pj2J9mifYtBt88Wq8mZZ4O6uwMa/w0a2xG3fYTTtMRH6EDb6H9bFiJXEM117Ank0QBb7oNpzFHI49Rxx4CD0H7mKGuqrwJ4+VpCnCMMRisUAcR6JHcB0H8/kcQRDA8304roO2aceflvsMLA+JlWUZ2rZF13WoqhJlWWide3Vdo2ka/V4UxSjL5VLOlcjzfPiv0ud43oqiCDRaycuOHWB76kIVJZTsxVKOvMjR1A1SyUQppc/SIPUkSbRjOqFROrG4qUOXQ5TDunnvs2i1zqjMd6Mb0SmzMawXjUdSz0yioQHztJKOvbDh+55Elo2loRjdrJbK1BjF/3h0hLHU0fd8EQ+uS3F1rf7aYJoy1Uiny9QDgUqu1N8ZZDdZO9dzEYhBYjKIEnhBrHU6ik2N4wQhHQ77REgYhH0Pwn7VBomnKOo3Yv6kakQiVcOudmNnD0o76vu/a4O6jmKIEaQU6TK9N0Ont5wSL370JeiO6Z3F6AzOtEhURH1V1WPnq3aJvO4MKAm+36JCmqJ0ympY/xU+FtNjwR1hGRJCsw/Qvzyc++kU+fo61MbGXsQHuizwIMKzoTmEUK5k6NtuZJWdsMK7QAji4Rq81VXEnz+j+Q1OdQ052BxwDnchxEDu62ezP/TFqfH6W4YylbEkywiRFLIyOzpnUHkuxJFmvcHjRo+dVaqAJ1iNpDy2cCedUxiMYZpSghlSFroSw6QqJZ6oc69u6tEZMXZUzY5MeT9l7VHXHoV5cqfsOpKWSjQ+4yjW7B7FnCxfv3Ni+E0iTLV3Ys8II6tlNRTWDTg9yJXG+WE+lK4WwsiapQfJi742BkJJ0SFIK815bJq5Cvom5sN7r+saHtUUPT2sm0SQFS1CMag0M/XsZK4E6hwKDghJxtrcjXBhbYJLjya4+GCC8/d3cO9VMKba07zcG9KswA+0IZaI9KaZR2rnya1IZmJZfgJYM9QkN9tNdQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;SFTP Setup Azure&quot;
        title=&quot;&quot;
        src=&quot;/static/f8b69a486f07a7e6449ed54766cd0e4c/b6272/SFTPSetup.png&quot;
        srcset=&quot;/static/f8b69a486f07a7e6449ed54766cd0e4c/4edbd/SFTPSetup.png 175w,
/static/f8b69a486f07a7e6449ed54766cd0e4c/13ae7/SFTPSetup.png 350w,
/static/f8b69a486f07a7e6449ed54766cd0e4c/b6272/SFTPSetup.png 580w&quot;
        sizes=&quot;(max-width: 580px) 100vw, 580px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Then, create an SFTP user:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/e9fdd51ccda8f15fedd4fd056259ec3d/b30aa/SFPTSetup2.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 21.714285714285715%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAYAAACOXx+WAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAlElEQVR42o1OWw7DMAjL/W+6blohL5oH8ViyVf0sigUyxLZ7ccJzeyCEgN47VNUwVh/Wu57cnXJEO2KM6K2hGtgHEDP4Cu/tJkGqYpjJH8BY78K5bWdL56d6M8FDBJIzskFs7roS1lrnfgmt0t/uOrvNR0hKk/wm9EnmR2ZCNr4UMzgKYoh4m3ku7RRIc1+mCREZGB+Z1zl9qTqmJgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;SFTP User creation&quot;
        title=&quot;&quot;
        src=&quot;/static/e9fdd51ccda8f15fedd4fd056259ec3d/8c557/SFPTSetup2.png&quot;
        srcset=&quot;/static/e9fdd51ccda8f15fedd4fd056259ec3d/4edbd/SFPTSetup2.png 175w,
/static/e9fdd51ccda8f15fedd4fd056259ec3d/13ae7/SFPTSetup2.png 350w,
/static/e9fdd51ccda8f15fedd4fd056259ec3d/8c557/SFPTSetup2.png 700w,
/static/e9fdd51ccda8f15fedd4fd056259ec3d/e996b/SFPTSetup2.png 1050w,
/static/e9fdd51ccda8f15fedd4fd056259ec3d/2cefc/SFPTSetup2.png 1400w,
/static/e9fdd51ccda8f15fedd4fd056259ec3d/b30aa/SFPTSetup2.png 1405w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Please note that SFTP access incurs additional charges of about $10 per day compared to Azure file storage. Alternatives such as &lt;a href=&quot;https://files.com&quot;&gt;files.com&lt;/a&gt; offer additional features, including more granular access control.&lt;/p&gt;
&lt;h2 id=&quot;client-library-for-sftp-connection&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#client-library-for-sftp-connection&quot; aria-label=&quot;client library for sftp connection permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Client Library for SFTP Connection&lt;/h2&gt;
&lt;p&gt;Several .NET libraries are available for working with SFTP. One of the most popular is the open-source &lt;a href=&quot;https://github.com/sshnet/SSH.NET&quot;&gt;SSH.NET&lt;/a&gt;. It adds a reference &lt;strong&gt;Renci.SshNet.dll&lt;/strong&gt; that can be used in X++.&lt;/p&gt;
&lt;p&gt;For user interface operations, I recommend using &lt;a href=&quot;https://filezilla-project.org/&quot;&gt;FileZilla&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/83a1da3fc97fa8497c8dbad624fa4b69/d4c13/FileZilla.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 41.142857142857146%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABbElEQVR42o1R226CQBTk//+rD31QaSouAuIuu7CwEJBLRUSdniWxadM+dJJJCIG5HSfZMahMQyiNgAtwpRAdYmRphqIw6LoWbVvjNs+weDweC+/3O554vrN0YiHAuMIqlHgJEryJCK63hSBRKSVUmkCIPaTgyPOCTAqUZYmiquHzDOyYIiPjU9OgITruZoNcazBvh8Dfw9/tEAUhDtEBURhCUGpjSmj6Jk1TGPq5IlEdxvBjCXZIoIsKfd9Rmw7OerXGdLmAUXVLb+st4koqcj1hmib8gq13u+EvOK7roqkb7P0Ae+bDJ8okWeqVxlA6g34YMI4jzufzwudz2w2UrF+SjeMFFzJ3wjBCnknIowelMhKvcb1eF9p0llbgO62Y4EfEoUsz0PHItKU5BtrWOZ0aPCjq2GyRKU6u/Y8L/oWZLt71A+azRuy/ItUGN5ptprRfgrVhdJB3cJ78S7AfPmjLCZVmKPJyaWQ3/ARhX1yfe11SPwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;FileZilla&quot;
        title=&quot;&quot;
        src=&quot;/static/83a1da3fc97fa8497c8dbad624fa4b69/8c557/FileZilla.png&quot;
        srcset=&quot;/static/83a1da3fc97fa8497c8dbad624fa4b69/4edbd/FileZilla.png 175w,
/static/83a1da3fc97fa8497c8dbad624fa4b69/13ae7/FileZilla.png 350w,
/static/83a1da3fc97fa8497c8dbad624fa4b69/8c557/FileZilla.png 700w,
/static/83a1da3fc97fa8497c8dbad624fa4b69/d4c13/FileZilla.png 825w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;system-setup&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#system-setup&quot; aria-label=&quot;system setup permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;System Setup&lt;/h2&gt;
&lt;p&gt;Before exploring different integration scenarios, let&apos;s discuss common setup options.&lt;/p&gt;
&lt;h3 id=&quot;connection-types&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#connection-types&quot; aria-label=&quot;connection types permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Connection types&lt;/h3&gt;
&lt;p&gt;The first form to setup an SFTP connection is &lt;strong&gt;External integration – Connection types&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;It requires the hostname and user/password credentials to access this host.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 659px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/2502318108b65c028dd95db51ea598c4/6db71/ConnectionTypes.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 75.42857142857143%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABsElEQVR42p1UCW7bMBDU/7/Qj/QhQdE6beVDdnRb4k2K0nTIJEiBBolrAQOCS+5gZrmr4tvR4cvXCVIqaOMglcE4ae4lxusVSmsscQPwhhhXIr6LYhhn1L2AUjqTSpWgM5EgqeJ+GHqU+xJVdULbtoxJOGvgnYX3Do7rKwopZyg5wRiNEHxetU6kEtYZxgK6rsFu9wO7xx3K8jfEPCMuAfblbiJfmJtQPPzs8L0c8OuicBkjDo3BwyMJTjPK2qCdIoa+Q3U6YhwGKDFjZilGqj4c9lTcYOLeJFd0VFi/YlmBEAG3PCOwZinmGbNh5UWBcRxxJabpSmUmwztHpQuVBQTvM4p1ZeYH37ZurKVA1/e0RyJr38627R98TshLgjbPlwuuVJdqPAtBco33cm9SKEnQNA1fe6DliY8istptu4MwnafWUaxZUued//D+bYSs4bmqqLJGzxfXuQ9tbuT/t0xbQkgcqxr74xl1O8CwFRKWeFcNScgJ2p9bTtRMopWtBCgbX0byLssSdfNEpSJPRZoQw/Uuy+ncMjnVLBG9wuT1Of43PiVMf5Y09IE/gVvwBwJEkt62xfHzAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Connection types&quot;
        title=&quot;&quot;
        src=&quot;/static/2502318108b65c028dd95db51ea598c4/6db71/ConnectionTypes.png&quot;
        srcset=&quot;/static/2502318108b65c028dd95db51ea598c4/4edbd/ConnectionTypes.png 175w,
/static/2502318108b65c028dd95db51ea598c4/13ae7/ConnectionTypes.png 350w,
/static/2502318108b65c028dd95db51ea598c4/6db71/ConnectionTypes.png 659w&quot;
        sizes=&quot;(max-width: 659px) 100vw, 659px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The password can be stored in several ways:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Manual entry - An unencrypted string suitable for development testing. It will remain after DB restores.&lt;/li&gt;
&lt;li&gt;Encrypted - An encrypted value.&lt;/li&gt;
&lt;li&gt;Azure Key Vault - A link to the standard D365FO key vault that stores the password.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;outbound-message-types&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#outbound-message-types&quot; aria-label=&quot;outbound message types permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Outbound message types&lt;/h3&gt;
&lt;p&gt;In Outbound message types, we set parameters for our data export.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/02b36bdf8ed7809abfa58840e5fc9bd2/1ff84/MessageTypeForm.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 73.71428571428572%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABtUlEQVR42pVS7U7jMBDM+z8NEi9wPw6JQ3e/UCmcuFbXpPluTL5sx3Y67Do00IMWztJoNytndmbXwcW3e1x+f8SvhxBXt39xvdjgZhnhxzKc4t0Uv4ogzCSSysA5B6ktuq5BniZonir0lHNUsgP2DsA4xTMIfi4LLNY1fscWD8mIKH3C/XKB1WqF9XpF8Q/yPKNGHfJSQCuJQauTCNZxg0wY5MISHCrRIk1jDMPgVVtrYY1GLxUKISmnOtVOIeAf+ez3ex8VdSnKHYyxVBthrEOUFBjM671zeEeolUYYxRCiQtPW6NWAbdaQHU1q3Xzv1AnMC+HhWGMgZQ+lFCTNi21H0YYQochzT/w1wpfOrLgidXVdezKGEAJN00D2vW94qH+EmXC2rNlyiN2uJDXTYoqy8HXvwNrzM/yXkC1twhBJknhVhhSlaYqEwKr5+by9f9Lyq0KFktXRVsdx9NhuY3qLOc1W+u//W4qlGY1utsAErLRtW8qnOR0afYT371Cxwt08ZJ4Z184t4mgpvLVjQomQZsgk3JEvZVn2qdXZsnP2qGBodmyRiTlnhX3f0XPSfkGfET4DOsCM9JX5BiQAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Outbound message types&quot;
        title=&quot;&quot;
        src=&quot;/static/02b36bdf8ed7809abfa58840e5fc9bd2/8c557/MessageTypeForm.png&quot;
        srcset=&quot;/static/02b36bdf8ed7809abfa58840e5fc9bd2/4edbd/MessageTypeForm.png 175w,
/static/02b36bdf8ed7809abfa58840e5fc9bd2/13ae7/MessageTypeForm.png 350w,
/static/02b36bdf8ed7809abfa58840e5fc9bd2/8c557/MessageTypeForm.png 700w,
/static/02b36bdf8ed7809abfa58840e5fc9bd2/1ff84/MessageTypeForm.png 1040w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Source group&lt;/strong&gt;
Here, we specify a link to the connection type and a folder on the SFTP server for data export.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Processing group&lt;/strong&gt;
Contains a link to the class that performs the export. The class is a standard RunBase class (extended from &lt;strong&gt;DEVIntegExportBulkBase&lt;/strong&gt;) that can define custom parameters and utilizes helper functions from the base class.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;File parameters&lt;/strong&gt;
Often, exports require creating a file name that includes a &lt;strong&gt;date&lt;/strong&gt; component. This setting enables specifying a name template using the &apos;%d&apos; parameter. &lt;strong&gt;Date format(%d)&lt;/strong&gt; defines how this symbol is converted into a date (e.g., you can include date-time or use just date). The format rules are defined by the .NET DateTime.ToString &lt;a href=&quot;https://learn.microsoft.com/en-us/dotnet/api/system.datetime.tostring?view=net-7.0#system-datetime-tostring(system-string)&quot;&gt;format parameter&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Delimiter&lt;/strong&gt; defines a CSV-type delimiter.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Advanced Group&lt;/strong&gt;
The advanced group defines used log types and a Company range validation. The exports run in the current company, and some exports may be logically related only to certain companies. The &lt;strong&gt;Company range&lt;/strong&gt; allows specifying a list of companies eligible for export.&lt;/p&gt;
&lt;h2 id=&quot;export-scenarios&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#export-scenarios&quot; aria-label=&quot;export scenarios permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Export scenarios&lt;/h2&gt;
&lt;p&gt;Let&apos;s describe the most typical scenarios that can be used to export data from D365FO.&lt;/p&gt;
&lt;h3 id=&quot;export-store-onhand-data-no-code-scenario&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#export-store-onhand-data-no-code-scenario&quot; aria-label=&quot;export store onhand data no code scenario permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Export Store Onhand Data (no-code scenario)&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Business scenario&lt;/strong&gt;: &lt;em&gt;Our company has a store, and we want to export daily onhand data from this store to our website. We need to include ItemId, Warehourse, and AvailiablePhysical value.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The External integration module contains a &lt;strong&gt;&lt;a href=&quot;https://github.com/TrudAX/XppTools/blob/master/DEVTutorial/DEVExternalIntegration/AxClass/DEVIntegExportBulkSQL.xml&quot;&gt;DEVIntegExportBulkSQL&lt;/a&gt;&lt;/strong&gt; class that allows exporting the result of a custom SQL string. This basic task can be done without writing any code.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;sql&quot;&gt;&lt;pre class=&quot;language-sql&quot;&gt;&lt;code class=&quot;language-sql&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;SELECT&lt;/span&gt; ITEMID&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;availPhysical&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; Qty&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; InventLocationId &lt;span class=&quot;token keyword&quot;&gt;FROM&lt;/span&gt; INVENTSUM
&lt;span class=&quot;token keyword&quot;&gt;WHERE&lt;/span&gt; CLOSEDQTY &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;AND&lt;/span&gt; DATAAREAID &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;USMF&apos;&lt;/span&gt; 
&lt;span class=&quot;token keyword&quot;&gt;GROUP&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;BY&lt;/span&gt; ITEMID&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; InventLocationId
&lt;span class=&quot;token keyword&quot;&gt;HAVING&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;availPhysical&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/440827c4e8ad6ea69eb52bae1771301a/76a99/OnhandSQLRun.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 53.14285714285714%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABoElEQVR42oVSTUvDQBDt//8PHlQQhNoK4sHSXsRLKwjePPZSRZtsNtkk+5k8Z8amtoo4MLDZyXvz3syOTi5nOJ8ucDqZ42xKOVlgPF/i9v4J1/MVxndLyavZChc3D3h8fkGKAcYYNE2DrutwGCNV93Lo+h6Jit5a1Os1HAFCSuj7/gjgvIMuSyJr4X0Qwhij/Mc52ioDZQJ0HVHoEm+vG2w3G2Tbd+R5Dtu2sNahpUYxeFG1zTU+Mg3rIhEm1HX9TZiVAXnVITcdTGOlGElZJFucfYqoGyJqvZy5ga5a5EWNIMo6dOyElHKOjuw4R4S7uVA35zwMfQ/BAEtKy7KCD1HuWmpQ0gi89wgh/CT0Mh8GBbZng6hhW9yELTFwsMdhTCWuwu7+iDCRBQZIN7LraQFFoVBVlagfCEXtntBIbb/lQ0LeFqtzu26RLLAlJuEaz2oAD8+lKApkWSYKf1lmRblStISvOTIRn3l2KSWx7omQgUwsdVKotZbGbP0HoYdSBVk0e5CiBoZ+HFQOlv+KI0KWzZbT7kGzGlmSO7j7h/AT0xdUIMpR69wAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Run onhand SQL export&quot;
        title=&quot;&quot;
        src=&quot;/static/440827c4e8ad6ea69eb52bae1771301a/8c557/OnhandSQLRun.png&quot;
        srcset=&quot;/static/440827c4e8ad6ea69eb52bae1771301a/4edbd/OnhandSQLRun.png 175w,
/static/440827c4e8ad6ea69eb52bae1771301a/13ae7/OnhandSQLRun.png 350w,
/static/440827c4e8ad6ea69eb52bae1771301a/8c557/OnhandSQLRun.png 700w,
/static/440827c4e8ad6ea69eb52bae1771301a/e996b/OnhandSQLRun.png 1050w,
/static/440827c4e8ad6ea69eb52bae1771301a/76a99/OnhandSQLRun.png 1117w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Then we can setup a standard daily batch job that generates a file in our output folder.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 446px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/6fcf79ddce92efc44078656bcf0a6f09/6244b/OnhandSQLResult.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 84%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAARCAYAAADdRIy+AAAACXBIWXMAAA7EAAAOxAGVKw4bAAACUElEQVR42p1U2XLbMAzU/39RH/rUid1OfcmxK/nQZeqwdcu65WsLUombdiZtXM1gQFIkiF0sKKmKguVijuVSwW63g77VsNlsYeg6TNPClsYarTmOi6ZpUNf1X01yXQ+m+gmRryNOjsjzI47HI9q2Rdu06Lhvue9wOp3+aVJZ1rS5RJfJcMw5DE3Hfn/A9XrD/3wUsBCDrgnRxl+gLFeQpzMoioqqqsW/2+32YbsHbOsQMftMfOnEn4E0zdB13eMZcniBHyIIfMShhzhOkCSJ4DHPc+HfWpZlwodBAN/3EYUhDofD/Yy0Z2s4O1Nk1MPrIV6v19+g8Dm3y+WCG/ng4MPz9kgpkGmYKIkeAdm0viFLPRRFhSSOKXCKNEsp05jWMzHPsr7qb6vJA7cko6oswWkrikJQJD2bDBZzwCzSIFWYMQbXdWGZpqi2Y9uwHeeXlNpG6JFbRhdzuDvLEjqtqgpSThsLGnC+SvL8pjwv6Nay55Hmf/LJxzxrcabs977ul3hkPYjAbAab2UKHNmXl0rphGH2WtO5QlmmawCK+OIqu62Gfz+e78blk088ojKjSgbAoDHDY+6KaMRHOyY+juC8MHbi8HH5XNoz619A1LFUVm9UKmy31rqZhK/rXoX42RaYeZfoqctzeF7sIKMszTGWZiqJBVVcYfh3i+3hM0Gyq6PlFLtePCZvzpSo/8DQYiA6xqGLD4QCT6ZReH1sEe6hTeMAFPV8jymizXkMneIPBE8aTiZDCwwE5T2vi7nmxBIfP+RuPRpjN5zRnD786PwGxHxB4IYg0xAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Onhand SQL result&quot;
        title=&quot;&quot;
        src=&quot;/static/6fcf79ddce92efc44078656bcf0a6f09/6244b/OnhandSQLResult.png&quot;
        srcset=&quot;/static/6fcf79ddce92efc44078656bcf0a6f09/4edbd/OnhandSQLResult.png 175w,
/static/6fcf79ddce92efc44078656bcf0a6f09/13ae7/OnhandSQLResult.png 350w,
/static/6fcf79ddce92efc44078656bcf0a6f09/6244b/OnhandSQLResult.png 446w&quot;
        sizes=&quot;(max-width: 446px) 100vw, 446px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h3 id=&quot;export-customers-no-code-with-data-entity&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#export-customers-no-code-with-data-entity&quot; aria-label=&quot;export customers no code with data entity permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Export customers (no-code with data entity)&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Business scenario&lt;/strong&gt;: &lt;em&gt;In our D365FO ERP, we maintain clients and want to implement daily export to the external system. We want to export the Client Id, Name, and E-mail.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;This task is similar to the previous one, but we will fetch the data using a standard data entity.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;sql&quot;&gt;&lt;pre class=&quot;language-sql&quot;&gt;&lt;code class=&quot;language-sql&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;CUSTOMERACCOUNT&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ORGANIZATIONNAME&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; PRIMARYCONTACTEMAIL &lt;span class=&quot;token keyword&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;CUSTCUSTOMERV3ENTITY&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;WHERE&lt;/span&gt; DATAAREAID &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;USMF&apos;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Message type setup is the following:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 650px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/6be1529e0a5f7f98ead52af1f036e96f/a6d36/CustUSMF.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 81.14285714285715%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAYAAAAWGF8bAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACXElEQVR42oVU226bQBT0/7/3M/oD/YFWqiylVeO0TbgYMF7A3JfbAp7OWcd5iGJ3pdEiLrNn5sxh8+iW+PT5L5pGo+t6NK1GUWpUVYW2bVCVJVqted1i6Ht0ukOR55gmA2MWzPNMmNd9xqZtKuSnBIlS6DvNjzqLkdj7Hna7HYJgjzRJkKojkkRZKBXb98w0vmEaB2y+PWXYPu3x/TGAk/TwlYFznKDyCfEhxO8/T3CcF5L78FzHHuBy9z0PmlULSa8bW4yQbr5sC/zwNLZug4egw89gwIM/wI1HVhXj+eWZxAdo3VJuS2tq9JS+UJ5VMmh8/XXC/pBhMSSs2hnduEKPC9phJoxF10/WP/FSPFrXlfvFM2OM9VDuGzPBzCuWZbHY4MYSgixLEB9jrOczzq+QJaSnTHw8YiaJ3Jf3Zd/IKx9BTivKGklWoCgKK3McxwumBTuvtt1/v25XSMI8LxGrlL41r2QTpU4knOFEtKOubbWTucRGqrxLWNcVDvEBSiKTprZS8W8mVBwxTiFtyZBmJ2a4s89uEspH0smPlnzoS4yIhIdJLssit9XfJBQymY6achvuZVVa2eKtEPYDp4axqahCLJEK7xKKZDk1puToECHn9bpKR1frl5DIgdfOy7Jdvkd4YlMcP7Sd7plNxg0cX1Y4w/VchFH0pkKq+09TZuRlC2ev4Ecp8mpArWfoYbGEYRgxAco27Mh9JOHdplwlB1FI2TEjlGMYBjsdE2c2CALel+AfeXCB7JShYYxuN4WEMnYSleuUXKdhoZeKVZVldfmtDaOddflZ/AM0m9LMj+J6egAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Customers export setup&quot;
        title=&quot;&quot;
        src=&quot;/static/6be1529e0a5f7f98ead52af1f036e96f/a6d36/CustUSMF.png&quot;
        srcset=&quot;/static/6be1529e0a5f7f98ead52af1f036e96f/4edbd/CustUSMF.png 175w,
/static/6be1529e0a5f7f98ead52af1f036e96f/13ae7/CustUSMF.png 350w,
/static/6be1529e0a5f7f98ead52af1f036e96f/a6d36/CustUSMF.png 650w&quot;
        sizes=&quot;(max-width: 650px) 100vw, 650px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The result will be a file with customers:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 596px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/aa9584bf8aa06ffb9f350357b0ba0e32/699b7/CustUSMFResult.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 68%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACHUlEQVR42p1Ua4/aQAzc//+z+qWVKpUrlEDeAZKQNwEC5EGYjheo7iROrbqSZXvj9XrG3qjv377gbTKB43owTRPmcqm1RUnTFGVZoiiKfxKJV1XmoykNZHSyLMMwDPjfdbvdoLphxNjGqLY/YMxNxHGMcRxfBr+XV3s64XC9YewrZKuvsC2PlWbou/6vlXy2VBjGxJ+jaQ44n89amqb5KKcTiixHkqRItomm5ng8krMEccTz+Z3DKIqgivgXTqeWMK+aP5FXkLu2RXNsdCLREiN2vdvhfGmJqtO+mjsmXMeFbVuwLBue58HzPbRM0Pf9H5GLjocDwvUGgR+grncIo1DHb1l1XdeoqgpqHSfc2GKb3LWGRfvAw3LjU8Tf8UD6iNvtaGeptvM818lKwlYR8efkR2YoeYyO+BKwZcdPpzOuV6Gjpx60LXDfVy66e/hKyg3DCOFmQ1JjnTgKQ1RlhSMbcrlc7gfIUde1Wgsdn3VayctYUizTgu/7cBwHi8UCruvAMBb0bcwNA9PpVL8g13Mw53fpsKARmDllv9/jwouUHHSZyPVc3k4IhPSEIvb14Utlsiewn75UqrV86+/ToXx2yWfXVqsAJXkrSHBd7zkOtW6OVFISvrzplBXJvFVVeaeGcye+cC+NkSrVz7cJn5yhfwqWbWM2m5ECC+v1mpessKGWTkbkWSZBkiRJxicacdRsBIGPFWOCINDJfwMxtSc/xyiq2QAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Customers export results&quot;
        title=&quot;&quot;
        src=&quot;/static/aa9584bf8aa06ffb9f350357b0ba0e32/699b7/CustUSMFResult.png&quot;
        srcset=&quot;/static/aa9584bf8aa06ffb9f350357b0ba0e32/4edbd/CustUSMFResult.png 175w,
/static/aa9584bf8aa06ffb9f350357b0ba0e32/13ae7/CustUSMFResult.png 350w,
/static/aa9584bf8aa06ffb9f350357b0ba0e32/699b7/CustUSMFResult.png 596w&quot;
        sizes=&quot;(max-width: 596px) 100vw, 596px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The examples above are great for prototyping, but &quot;real world&quot; export scenarios will likely be more complex than using a single &lt;strong&gt;SELECT&lt;/strong&gt; statement, so you may need to write X++ code. &lt;em&gt;(One possible improvement is integrating the module with Data management and ER engines. If you have some working code that you can share, please ping me.)&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&quot;x-export-implementation-concept&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#x-export-implementation-concept&quot; aria-label=&quot;x export implementation concept permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;X++ Export Implementation concept&lt;/h3&gt;
&lt;p&gt;The External Integration framework provides the following development concept: We can&apos;t predict how complex our exports will be. They may export to different sources (like SFTP, Azure storage, Service Bus, Web service), export data to one file or multiple files, require different parameters, etc. To cover all possible scenarios, we can use a standard &lt;strong&gt;RunBaseBatch&lt;/strong&gt; class.&lt;/p&gt;
&lt;p&gt;However, export classes will have some common methods. So, I created a base &lt;strong&gt;&lt;a href=&quot;https://github.com/TrudAX/XppTools/blob/master/DEVTutorial/DEVExternalIntegration/AxClass/DEVIntegExportBulkBase.xml&quot;&gt;DEVIntegExportBulkBase&lt;/a&gt;&lt;/strong&gt; (that extends RunBaseBatch) to store these common properties and methods (like variables to store the number of export records, methods to create logs, write data to a file, etc.). The Export class should extend it.&lt;/p&gt;
&lt;h3 id=&quot;export-onhand-data-simple-x-procedure&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#export-onhand-data-simple-x-procedure&quot; aria-label=&quot;export onhand data simple x procedure permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Export onhand data (simple X++ procedure)&lt;/h3&gt;
&lt;p&gt;Let&apos;s start with a simple case where you need to write X++ code that generates the export data.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Business scenario&lt;/strong&gt;: We want to export all companies&apos; inventory onhand data to SFTP. Our export should be a CSV file containing the following fields: &apos;Company&apos;, &apos;ItemId&apos;, &apos;InventLocationId&apos;, &apos;LastUpdDatePhysical&apos;, &apos;AvailPhysical&apos;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The following &lt;a href=&quot;https://github.com/TrudAX/XppTools/blob/master/DEVTutorial/DEVExternalIntegrationSamples/AxClass/DEVIntegTutorialExportBulkInventOnhand.xml&quot;&gt;class&lt;/a&gt; solves this task:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;DEVIntegTutorialExportBulkInventOnhand&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;extends&lt;/span&gt; DEVIntegExportBulkBase
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;exportData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;container&lt;/span&gt;  lineData&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;InventSum&lt;/span&gt;  inventSum&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;initCSVStream&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        lineData &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&apos;Company&apos;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &apos;ItemId&apos;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &apos;InventLocationId&apos;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &apos;LastUpdDatePhysical&apos;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &apos;AvailPhysical&apos;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;writeHeaderLine&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;lineData&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;select&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;crosscompany&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;AvailPhysical&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;maxof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LastUpdDatePhysical&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; inventSum
            &lt;span class=&quot;token keyword&quot;&gt;group&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;by&lt;/span&gt; ItemId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; InventLocationId
            &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;inventSum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;AvailPhysical 
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            lineData &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token attribute&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;inventSum&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;DataAreaId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;inventSum&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ItemId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;inventSum&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;InventLocationId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;inventSum&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;LastUpdDatePhysical&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;inventSum&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;AvailPhysical&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;writeDataLine&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;lineData&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sendFileToStorage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;str&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getExportDescription&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Tutorial export Onhand to CSV&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The class is quite simple, but it contains the following key parts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A business definition for the export&lt;/li&gt;
&lt;li&gt;An export flow&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For example, if you want to create a file per company instead of one file, you can easily modify it. The &lt;strong&gt;External Integration&lt;/strong&gt; framework will handle all related processes.&lt;/p&gt;
&lt;p&gt;After we setup this class, we get the following file as a result:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/abe76da5b99eac9a800fc607e18fb76d/2e195/SimpleOnhandXpp.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 85.14285714285714%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAARCAYAAADdRIy+AAAACXBIWXMAAA7EAAAOxAGVKw4bAAACd0lEQVR42o1U6W7TQBjM+z8Jr8EPJJAoiFKaxM7m8LWxncS3HZ/DfJtSCG0KkUa2N7uz8813zOJThXfvEyRpjqqq+CyRZxmKokCapijLElVdoybSLEXb9eiIvu/Qd0TfX2GW8vAxLVA3jSEshKAq4XseLMuG7/sItMZ+v0cQBAjDCC33Dl2LgaRde77C7MP3EHePPj7PQ9hBC7Uf4MSDIVivFRzXMaRqpbDb7biuqbBlFCnJ93wXouYZs08PIe6tED/WCVZ+A6VbOGGLJEkQxyGapsY4DshIkJ4SWpGjpZLkdEIUhU+ht8+YdW2LF79pMgryPL98jqNZG/lsGG5DP6dxMmvy3594nRATE5JB06+OCqZpNGTD0NMCl4lLn+6dXpy8qTDLC4TRwWS55R4hFMSHGCWTdj6fjR0D7fgnodwsm7MsN2FXVf2bMI5xPB55YY6MUQz9fxDKwY41Jkp/eSeenXmJ6znQ2jcJiZjlsixMBKJYcDtk+qRZIoEOjBoh1NqD6xNuAM/X9NNnKbnYbrbYrDfY7pzbIRckCaPIdMcwDEbsMdYInTn23haZVoiDLULXRujvaMUBOy94o2xI6Loe9sx0bcpkxNKycP/lIxYPX2ER8/s7rB6/wXccWhDhcDi8TSgtJwkQQvFRqTUW1go7x4VHNbatYNnKlJLv+YyquB2y9HVTN0aZhCxQaoXlckm/1vBIsrJttuSK5B4CPzAD5Q2Fl0kjxTz0FyilqMoyBFI+kgybA0T6XpCzLW8oHE2JtOfmapIImShcM6MuFdpUuJgv4NIC+ZZx9zohw/yb7EJoc6RZcJgEmToOy2RDlfppvMko/AnzOhd0o1GWxAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Simple onhand setup&quot;
        title=&quot;&quot;
        src=&quot;/static/abe76da5b99eac9a800fc607e18fb76d/8c557/SimpleOnhandXpp.png&quot;
        srcset=&quot;/static/abe76da5b99eac9a800fc607e18fb76d/4edbd/SimpleOnhandXpp.png 175w,
/static/abe76da5b99eac9a800fc607e18fb76d/13ae7/SimpleOnhandXpp.png 350w,
/static/abe76da5b99eac9a800fc607e18fb76d/8c557/SimpleOnhandXpp.png 700w,
/static/abe76da5b99eac9a800fc607e18fb76d/2e195/SimpleOnhandXpp.png 782w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h3 id=&quot;export-onhand-and-price-data-x-based-on-a-query&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#export-onhand-and-price-data-x-based-on-a-query&quot; aria-label=&quot;export onhand and price data x based on a query permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Export onhand and price data (X++ based on a query)&lt;/h3&gt;
&lt;p&gt;Let&apos;s consider an export scenario with more advanced logic.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Business scenario&lt;/strong&gt;: We want to implement a periodic export to SFTP of onhand data for one of our customers from their main Warehouse for a set of Items (the default should be the &apos;Audio&apos; Item group, but it should be configurable). The export should be a CSV file that contains the following fields: &apos;ItemId&apos;, &apos;InventLocationId&apos;, &apos;AvailPhysical&apos;, &apos;Price&apos;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;To do this, we need to create a &lt;a href=&quot;https://github.com/TrudAX/XppTools/blob/master/DEVTutorial/DEVExternalIntegrationSamples/AxClass/DEVIntegTutorialExportBulkOnhandPricesQuery.xml&quot;&gt;class&lt;/a&gt; that extends &lt;strong&gt;DEVIntegExportBulkBase&lt;/strong&gt;. The code for this class contains the following blocks:&lt;/p&gt;
&lt;p&gt;A method that defines the initial query and settings, providing default values(that can be overridden by the user):&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;DEVIntegTutorialExportBulkOnhandPricesQuery&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;extends&lt;/span&gt; DEVIntegExportBulkBase
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;CustTable&lt;/span&gt;           custTable&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;Query&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;exportQueryInit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;Query&lt;/span&gt;                 query&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;QueryBuildDataSource&lt;/span&gt;  qBDS&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        query   &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;Query&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        qBDS &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; query&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addDataSource&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;tablenum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;InventTable&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        qBDS &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; qBDS&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addDataSource&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;tablenum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;InventItemGroupItem&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        qBDS&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;relations&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        qBDS&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addRange&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;FieldNum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;InventItemGroupItem&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ItemGroupId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&apos;Audio&apos;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; query&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;DEVIntegMessageTypeTableOutbound&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;initDefaultParameters&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;DEVIntegMessageTypeTableOutbound&lt;/span&gt;    _messageTypeTableOutbound&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;DEVIntegMessageTypeTableOutbound&lt;/span&gt;  tableOutbound &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;_messageTypeTableOutbound&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        tableOutbound&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;FileNameParameterD   &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &apos;yyyyMMdd_HHmm&apos;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        tableOutbound&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;FileName             &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &apos;OnhandPrices_&lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt;d&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;csv&apos;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        tableOutbound&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;FileColumnDelimiter  &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token char&quot;&gt;&apos;|&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; tableOutbound&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A main export logic that initialises the file and uses the stored query to process export records:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;exportData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;container&lt;/span&gt;               lineData&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;InventTable&lt;/span&gt;             inventTable&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;Query&lt;/span&gt;                   query&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;QueryRun&lt;/span&gt;                qr&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;//init parameters&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;DEVIntegParametersPerCompany&lt;/span&gt; integParametersPerCompany &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; DEVIntegParametersPerCompany&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    DEV&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;validateCursorField&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;integParametersPerCompany&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fieldNum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;DEVIntegParametersPerCompany&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ProductExportCustomer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    custTable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; CustTable&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;integParametersPerCompany&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ProductExportCustomer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;initCSVStream&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    lineData &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&apos;ItemId&apos;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &apos;InventLocationId&apos;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &apos;AvailPhysical&apos;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &apos;Price&apos;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;writeHeaderLine&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;lineData&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    query   &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;exportQueryGet&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    qr &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;QueryRun&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;query&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;qr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        inventTable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; qr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;TableNum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;InventTable&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;itemRecord&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;inventTable&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sendFileToStorage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And a method that calculates the exported values:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;itemRecord&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;InventTable&lt;/span&gt; _inventTable&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;InventDim&lt;/span&gt;       inventDimFind&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;Price&lt;/span&gt;           price&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;InventSum&lt;/span&gt;       inventSum&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    inventDimFind &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    inventDimFind&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;InventLocationId  &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;   custTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;InventLocation&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    inventDimFind&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;InventSiteId      &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;   custTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;InventSiteId&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    inventDimFind   &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;   inventDim&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findOrCreate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;inventDimFind&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token class-name&quot;&gt;PriceDiscParameters&lt;/span&gt; parameters &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; PriceDiscParameters&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;construct&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    parameters&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parmModuleType&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token named-parameter punctuation&quot;&gt;ModuleInventPurchSales&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;Sales&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    parameters&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parmItemId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;_inventtable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ItemId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    parameters&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parmInventDim&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;inventDimFind&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    parameters&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parmUnitID&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;_inventtable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;inventTableModuleSales&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;UnitId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    parameters&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parmPriceDiscDate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token named-parameter punctuation&quot;&gt;DEV&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;systemdateget&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    parameters&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parmQty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    parameters&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parmAccountNum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;custTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;AccountNum&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    parameters&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parmCurrencyCode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;custTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Currency&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;PriceDisc&lt;/span&gt;       priceDisc &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; PriceDisc&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;newFromPriceDiscParameters&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;parameters&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;priceDisc&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findPrice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;custTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;PriceGroup&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        price       &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; CurrencyExchangeHelper&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;amount&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;priceDisc&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;price&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;exportBulkStatus &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; DEVIntegExportBulkStatus&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;Warning&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;warning&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;strFmt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Price is not found for %1 Item&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _inventtable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ItemId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setExportStatus&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token named-parameter punctuation&quot;&gt;DEVIntegExportBulkStatus&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;Warning&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;select&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;AvailPhysical&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; inventSum
        &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;inventSum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ItemId           &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; _inventTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ItemId &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;
        inventSum&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Closed           &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;
        inventSum&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;InventSiteId     &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; custTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;InventSiteId &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;
        inventSum&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;InventLocationId &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; custTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;InventLocation&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;writeDataLine&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;token attribute&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;_inventTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ItemId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;custTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;InventLocation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;inventSum&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;AvailPhysical&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;price&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The settings for this class will be the following:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/0c0e90f065c7f0dc379dd3e4dacdce12/99072/PricesQuery.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 86.85714285714286%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAARCAYAAADdRIy+AAAACXBIWXMAAA7EAAAOxAGVKw4bAAACSUlEQVR42o1UzY7TMBjsAQ7wDHvYV+DAoyFegAfgymvsiQsSxz1UQiB6KWrVNo0T5//HcRw7yfDZTbtd7UaqpZEjp57OjCdesFjgx68cXSvQNA2qqoYQFbIsR1GWEI1A27a0XqGVLbTuoLtOg4bW+tOCBj2+XZyHF6TYeQzHMENeKWSEvKiwWq2wXq+x2x+w2Wyw3W7hHY9EptApORGqE+Fy+UT4/ZHh5/KAx78xfm8l/uwMvFDA8/bY7/coigJBGMBnPuI4gahLel9q1RNjLx3h8powSgVqaSDawc21pFlI2hyRVYVxGKw1KKWgyHpHClVnnMK+f8Wy0e7ds2FziuLYZTcQ4RlRFFEchX2eCPuXhPqUL8YJdnRdRxY5HUzmSKVsTmu+7yIgtW6TlK9YnlPIOXeo69qRGXJpCYMgRJIkbpOS6jZCuzYMJ73jODpYy75/JHhEGuhhHKhe4kaFpIhHHCxgzjZl5WBJ7WyMmc9wjpAxhpAsN1JeDuVK7XnT7YQ2Pz8InEJ7KKTq2U+mOD5PhO8IbyzmFZJdWx1Bn6PtoCW06q4Jb1Zoy5ulqTtZTDYvB0bEZpJL1r/SdE/4SPhgMVubLK9QVtQ/PaDIC0Q2AqoNj2KwMKIYbOn7F3tnFfIoQ1lKunGaqX8Bfd8Hd3GUtYJsDf2ZjeGpWvOElNnm3xqH/Q6MuhcSGXXOvatFC542SIoWLK5qQsBTweNM8qzSfIawhU9XlbVpL4mYOpnn+aXo1D+XoenMl4dvD++DPL9PmuauGce7/43Jg+sxTyVPAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Prices query&quot;
        title=&quot;&quot;
        src=&quot;/static/0c0e90f065c7f0dc379dd3e4dacdce12/8c557/PricesQuery.png&quot;
        srcset=&quot;/static/0c0e90f065c7f0dc379dd3e4dacdce12/4edbd/PricesQuery.png 175w,
/static/0c0e90f065c7f0dc379dd3e4dacdce12/13ae7/PricesQuery.png 350w,
/static/0c0e90f065c7f0dc379dd3e4dacdce12/8c557/PricesQuery.png 700w,
/static/0c0e90f065c7f0dc379dd3e4dacdce12/99072/PricesQuery.png 842w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The resulting file will look like this:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 403px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/2b4c7751f03dfec9c7b7eb6413ffc444/045fd/PricesQueryResults.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 41.714285714285715%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABKElEQVR42pWRW2+CQBCF+f8/qUkbY2otIgJKTUp3gb2h3LRGaI0Png6r79VNJnPmYb89Z9YZTd4QTV8wf31C9D5C7I3hT54RuiMsZ2NE1PnKw6c7xWZToaoaW9tthbpur7qsUJY16qqFk2YSyRdH/MEw8ximboIgEvDmDMvYUGmsqIdLiTDgCBYMUZTB9xMsaA5DuhtLBD7Dem3gGKWQZSlEnkEqDaUkOdlQFTgcDvjpe3Rdj3uPo6REmqZgnEEIAUmzMYbACk3TEKzD8Xi8HyhvQM45BOlhLorCQpu2tS73++/HgdYh6Vzk0FrDFIYcS6u1Nuj7a+zL5fJPZLvDDIwxggkLGdzZ2FphWElJv3g+nx90yJiFDQ8U9CmDs91uZ3f4ezrdHfkPZYNYaavZBawAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Prices query results&quot;
        title=&quot;&quot;
        src=&quot;/static/2b4c7751f03dfec9c7b7eb6413ffc444/045fd/PricesQueryResults.png&quot;
        srcset=&quot;/static/2b4c7751f03dfec9c7b7eb6413ffc444/4edbd/PricesQueryResults.png 175w,
/static/2b4c7751f03dfec9c7b7eb6413ffc444/13ae7/PricesQueryResults.png 350w,
/static/2b4c7751f03dfec9c7b7eb6413ffc444/045fd/PricesQueryResults.png 403w&quot;
        sizes=&quot;(max-width: 403px) 100vw, 403px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;As in the previous example, a developer writes only export business logic related to the export.&lt;/p&gt;
&lt;h4 id=&quot;warning-message-status&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#warning-message-status&quot; aria-label=&quot;warning message status permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Warning message status&lt;/h4&gt;
&lt;p&gt;This class also contains a concept called a &lt;strong&gt;Warning&lt;/strong&gt; status. An export may finish successfully or may have an exception during file generation (Error state). But sometimes, you need to log an event where the exported data has issues but still wants to perform the export. For example, in our case, we can&apos;t find a price for some exported items. It is not a critical error, but we need to notify a user about this; they may adjust the query to exclude these items or notify another department to enter prices. To cover this scenario, the export class may mark the status as &lt;strong&gt;Warning,&lt;/strong&gt; and the user may set a standard alert for it.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/af53b2cd9df197caf343962d8836d2f6/705cc/WarningImage.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 24.571428571428573%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAYAAABFA8wzAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAA50lEQVR42m2Q227EIAxE8/+/VvWtD31ZabMNIRDIpZAQrlNDu1JV1dJojsfIEu6kVBBCQKmZpDCTvPcI4bfCPxz+vCH5C90wMDA2Qs6aFl2I0SOjNE/hQiaPwSHV/MmUP7PKra+cEzo+W3wIi0mfYMRinNG/vELLFXzeMYoFq7nAyCe1YbMeQn+2bFI71GKhN4eFMv72jk4uBrd+gtQGcjmw7Q78wWHPhAeTuN0ZNuN/eMRuAwzNzBHB5YZ+ELiT9Hpgp11djLF9NaXYVEpBzhm1At3SubP19T7uPNu8VvVScoVvR2nZFzJegPsfhedTAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Warning image&quot;
        title=&quot;&quot;
        src=&quot;/static/af53b2cd9df197caf343962d8836d2f6/8c557/WarningImage.png&quot;
        srcset=&quot;/static/af53b2cd9df197caf343962d8836d2f6/4edbd/WarningImage.png 175w,
/static/af53b2cd9df197caf343962d8836d2f6/13ae7/WarningImage.png 350w,
/static/af53b2cd9df197caf343962d8836d2f6/8c557/WarningImage.png 700w,
/static/af53b2cd9df197caf343962d8836d2f6/e996b/WarningImage.png 1050w,
/static/af53b2cd9df197caf343962d8836d2f6/705cc/WarningImage.png 1071w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;Skipped&lt;/strong&gt; lines counter serves the same purpose. If we need to skip some lines and notify a user about this, we can increase the &lt;strong&gt;Skipped&lt;/strong&gt; counter and see it in the log.&lt;/p&gt;
&lt;h3 id=&quot;export-invoices-to-the-edi-provider-incremental-x-procedure&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#export-invoices-to-the-edi-provider-incremental-x-procedure&quot; aria-label=&quot;export invoices to the edi provider incremental x procedure permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Export invoices to the EDI provider (incremental X++ procedure)&lt;/h3&gt;
&lt;p&gt;Let&apos;s describe a scenario where we need an incremental export.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Business scenario&lt;/strong&gt;: Our company wants to export customer invoices to an external EDI system. The export runs daily and should include all invoices for this day. The export file should contain information about customer invoices, lines, and charges.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;To start this task, you will receive an EDI specification document and need to determine how it will be mapped to D365FO data.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 651px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/9f8eaa199f24bee74a580c98446f3c40/1ac66/TypicalEDIStructure.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 33.142857142857146%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAAA7EAAAOxAGVKw4bAAABnklEQVR42iWSS5OaUBCF+f//IYvMWIlVmSyyziKjkVHwAaggD5X4YETeKmHcfWnJouvU7a76+px7rzIb64xUleiwZ2HNGPR7OMsFvrsikNp4Hmvfw185hJu1qPQCX8prNZB5kSXU14rbpUR51eb80haohodmefQ0i6HpsQwO7Xlo+qhyHsxcDG/H9lQSHHPW7wXuPiU8FTh/zthhjC2qdLUTnbeIZzWi09/yop/49NOlq4Z80yKefh94Hhz4LPrU2/AyOdPpBfzQpdcL+a5HdPWYr8L5MnpHKcsLeZ5TlhWrldgvSyaTKa+9PvE5pbo85gVVVeE4K5IkQ59pjDSN6BhhWHOCYI3neux2e5RKQP+BJZv1hqKQCLaNZZj4XkCape3sUb7vk6UZxmKGYZoCPKIL2DQsWeYQReKwaT6o/9Y0TUO4DVt1ljZvA5XpeIorm+M45n6/EwjwYWBhyz0Ph+RZThiGAookwYXmo0GpbzUXiXW73Vrg9XoV+y5zS7bajkRM2nld13iPF5X4C2fOeDwhTVKOEnsvP+QcJy3jH14280QFkb+pAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Typical EDI structure&quot;
        title=&quot;&quot;
        src=&quot;/static/9f8eaa199f24bee74a580c98446f3c40/1ac66/TypicalEDIStructure.png&quot;
        srcset=&quot;/static/9f8eaa199f24bee74a580c98446f3c40/4edbd/TypicalEDIStructure.png 175w,
/static/9f8eaa199f24bee74a580c98446f3c40/13ae7/TypicalEDIStructure.png 350w,
/static/9f8eaa199f24bee74a580c98446f3c40/1ac66/TypicalEDIStructure.png 651w&quot;
        sizes=&quot;(max-width: 651px) 100vw, 651px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;From practical experience, the first question to ask is how the EDI line data is defined. In the best scenario, it may match what you have in invoice lines, but in more complex cases, they can be defined on a more granular level (like related inventory transactions) or on a more summary level (e.g., lines grouped by Item number). Such requirements may even create quite complex system modifications to support such line splits.&lt;/p&gt;
&lt;p&gt;The next decision is how to track incremental updates. A typical mistake that I sometimes see on projects is using the &lt;strong&gt;CreatedDateTime&lt;/strong&gt; field for this. The idea is to export all data up to the current time, save this time, and next time process all records starting from this time. The problem with this approach is that it doesn&apos;t consider existing transactions. The SQL transaction may start at 1 pm, create an invoice at 1:05, and finish at 2 pm. If the export runs at 1:30, it will not see a 1:05 uncommitted transaction, and the invoice will not be exported. So, it is better to avoid such architecture.&lt;/p&gt;
&lt;p&gt;To implement incremental tracking, I propose the following: Add 2 fields, &lt;strong&gt;IsExported&lt;/strong&gt; and &lt;strong&gt;ExportedDateTime&lt;/strong&gt;, to the invoices and update these fields after the export. It may not sound technically perfect (for example, &lt;a href=&quot;https://www.linkedin.com/pulse/d365-fscm-recurring-integrations-francisco-zanon/&quot;&gt;DMF&lt;/a&gt; may use SQL change tracking, so you don&apos;t need to add any fields), but it is very simple to troubleshoot, and it provides full visibility to a user. They can just open an invoice and see its status and when it was exported.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/22883a466d4c5dacd58231df5fe911a1/27b7a/EDIInvoiceForm.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 49.71428571428571%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABwElEQVR42mVSyY6cMBTk/z8otySnSH3KIbMkmszSSwADNga8AMam8h5iWp3Mkwq8vLXKme4HdL2BsR7Oj7CO/s4hLxoczyVeXt9wvpwhRIm2VVBSQsoGTV2j7zosYUaYpyuyL99rHB4k7o4jXsoFT3nAn9pCqQZVLVBVFToKVK3cklaV2FAUBZ1rpBgRl+WK7NOhwf1xwuMl4v4U8OMYcKpHmKHHOE1YVyCltIGWV1vpgs8iJ7xBdvcs8fO5xEUMkH1ArQP0MKFVCqUQRIHDuie0NKp4e4Wm7iIViynS+b/I+l7D2oFrXqsv1Po8Ezf0X8Ky7dmevh3w6/NXmMcHLMPw3ipuLVOqhTEGIQQKjBs4GVdj3/fR2HoSTvYWM4/HFPyXbE+okOc5Kew3BwYnH8dx5yjt4ySEadyEYHUtNcGFP3DYaY2J+Nj7376slhk6eMdBE7wP5DOTSBHTHOHHmQpH8qQuE1Oy7wmZblsIehrO2et43GGlLH6fFITyhAknYdGahKKh53Vp6d6hdytKaXHKW3Q2oXOJR5bQNMYtHywCK53XBoOPFBhR0NqOKwYKMn6lddr2UnsUVQchDRrt8RcBvQLvj4GqdAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;EDI Invoice form&quot;
        title=&quot;&quot;
        src=&quot;/static/22883a466d4c5dacd58231df5fe911a1/8c557/EDIInvoiceForm.png&quot;
        srcset=&quot;/static/22883a466d4c5dacd58231df5fe911a1/4edbd/EDIInvoiceForm.png 175w,
/static/22883a466d4c5dacd58231df5fe911a1/13ae7/EDIInvoiceForm.png 350w,
/static/22883a466d4c5dacd58231df5fe911a1/8c557/EDIInvoiceForm.png 700w,
/static/22883a466d4c5dacd58231df5fe911a1/27b7a/EDIInvoiceForm.png 804w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;So when the export runs in the Incremental mode, it just takes all records that are not exported. Another advantage of this approach is there can be a situation when we need to reexport some data (for example, the export may contain errors, or we need to add additional information to the export). With these status fields, it is quite easy to implement.&lt;/p&gt;
&lt;p&gt;The main &lt;strong&gt;&lt;a href=&quot;https://github.com/TrudAX/XppTools/blob/master/DEVTutorial/DEVExternalIntegrationSamples/AxClass/DEVIntegTutorialExportBulkCustInvEDIInc.xml&quot;&gt;exportData&lt;/a&gt;&lt;/strong&gt; method:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;exportType &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; DEVIntegExportBulkIncrementalType&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;Incremental&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    qbds&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addRange&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;FieldNum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;CustInvoiceJour&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; DEVTutorialIntegEDIIsSend&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;queryValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token named-parameter punctuation&quot;&gt;NoYes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;No&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
qr &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;QueryRun&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;query&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;qr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    custinvoicejour &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; qr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;TableNum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;CustInvoiceJour&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;exportRecord&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;custInvoiceJour&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    tmpExportRecordsMark&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;RefRecId &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; custInvoiceJour&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;RecId&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    tmpExportRecordsMark&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;insert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sendFileToStorageNotEmpty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt; isTestRun&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    ttsbegin&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;                  
    custInvoiceJour &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    update_recordset custInvoiceJour
        &lt;span class=&quot;token class-name&quot;&gt;setting&lt;/span&gt; DEVTutorialIntegEDISendDateTime &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; exportStartDateTime&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                DEVTutorialIntegEDIIsSend &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
    exists &lt;span class=&quot;token keyword&quot;&gt;join&lt;/span&gt; tmpExportRecordsMark
        &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;tmpExportRecordsMark&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;RefRecId &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; custInvoiceJour&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;RecId&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ttscommit&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And method that translates invoice to EDI format:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token range operator&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;token range operator&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;token range operator&quot;&gt;..&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;select&lt;/span&gt; custinvoicetrans
    order &lt;span class=&quot;token keyword&quot;&gt;by&lt;/span&gt; LineNum&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; itemid   
    &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;custinvoicetrans&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;InvoiceId &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; _custinvoicejour&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;InvoiceId &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;
          custinvoicetrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;SalesId   &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; _custinvoicejour&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;SalesId
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    linecounter&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    totalQty &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt;  custinvoicetrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Qty&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token class-name&quot;&gt;InventDim&lt;/span&gt;       inventDim &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; custinvoicetrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;inventDim&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;custInvoiceTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;SumLineDiscMST &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; custInvoiceTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Qty&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        realPrice       &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;   &lt;span class=&quot;token function&quot;&gt;decRound&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;custInvoiceTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;SalesPrice &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;custInvoiceTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;SumLineDiscMST&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;custInvoiceTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Qty&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        realPriceStr    &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;   &lt;span class=&quot;token function&quot;&gt;num2str&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;realPrice&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        realPriceStr   &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;   &lt;span class=&quot;token function&quot;&gt;num2Str&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;custinvoicetrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;SalesPrice&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;InventItemBarcode&lt;/span&gt; inventItemBarcode &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; inventItemBarcode&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findItemId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;custInvoiceTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ItemId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &apos;EAN&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;13&lt;/span&gt;&apos;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    barCodeStr &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; inventItemBarcode&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ItemBarCode&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt; barCodeStr&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        barCodeStr  &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;  custinvoicetrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ItemId &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token char&quot;&gt;&apos;-&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; inventDim&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;InventColorId &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token char&quot;&gt;&apos;-&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; inventDim&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;InventSizeId&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    lastlinenum &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; custinvoicetrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;LineNum&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;writeDataLine&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;D&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;num2str&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;custinvoicetrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;LineNum&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        salesTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;PurchOrderFormNum&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        barCodeStr&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        custinvoicetrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;itemName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;num2str&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;custinvoicetrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Qty&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        custinvoicetrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;SalesUnit&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;num2str&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;custInvoiceTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;SalesPrice&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;num2str&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;custInvoiceTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;DiscPercent&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        realPriceStr&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        _custInvoiceJour&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;InclTax &lt;span class=&quot;token punctuation&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Y&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token range operator&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;token range operator&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;token range operator&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;        &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As a result, you will get a file similar to this one:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/587cf644278f971357af9d5722064dd1/17a7a/EDIInvoiceResult.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 16.571428571428573%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAADCAYAAACTWi8uAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAoUlEQVR42kWMyw6DMAwE+f9fA1RKqShSIORJUIDQA0fYuomqHkZrj+zNmnuJtirwvFW45znqokT3aPCqW4zjDM4nSodp2uHcO6a1P0IkuZRZ3w8YhYQ2DlIYcKEgpEHXMfRsIKfo2EEpQw8zlmXFum7wfqF5i3i/Rv+dM8YYxMhhjYFWGkpKKhEwWlOBRQgb9n2nDDiOA9d1ESfOM5H2v/sA08zeegGD5XcAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;EDI file results&quot;
        title=&quot;&quot;
        src=&quot;/static/587cf644278f971357af9d5722064dd1/8c557/EDIInvoiceResult.png&quot;
        srcset=&quot;/static/587cf644278f971357af9d5722064dd1/4edbd/EDIInvoiceResult.png 175w,
/static/587cf644278f971357af9d5722064dd1/13ae7/EDIInvoiceResult.png 350w,
/static/587cf644278f971357af9d5722064dd1/8c557/EDIInvoiceResult.png 700w,
/static/587cf644278f971357af9d5722064dd1/17a7a/EDIInvoiceResult.png 753w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Below are the dialog and parameters set up for this export. By default, we export invoices from US-005 customers incrementally, but the user can export All invoices for a period or an individual invoice if needed.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/2fb366d226770878aaa50d6331293358/48ca3/IncrementalEDIDialog.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 67.42857142857143%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAIAAAAmMtkJAAAACXBIWXMAAAsTAAALEwEAmpwYAAABVUlEQVR42n1S2U7EMAzs/38h4gmEkHZR0xyOnWNzME3YpV0JRlFkux577HQxlCWWWkspVZiN0cKePYkwgr133N57a12MsdZ6G2i14iwvb9t1SxddvkzRxm5aWWeVWq21KUXnHKoYSzjMHhQRIWeHXRfLWVIJqeJICDmn3tsQsneAiwuFmBkqWgM5+Jh53cLr6wK/34EPLHK3ZRLQgVkM9FgHW236/eNTK52JTmToJPIpJQRDDBg1xJgT0vyqiQWiOlSodfVEtbVfMowyALVwY4ogYxDsCRIgfqowxkBIznmf+dg5huDGVhHENwyOg7mBmYAYEe0PUyvcExlSnSPcs/kEUh9k2Eop3NM9d05T4W0WfhCgZU6EKtfrZdsU0uA+kyO2tSvGOn6AWhhnPNsJ7biwQU4Sb6W03tqR/JD9hKenStCD/sfgceb/yPifyO8o55n/In8Daej55FOyBjMAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;IncrementalEDIDialog&quot;
        title=&quot;&quot;
        src=&quot;/static/2fb366d226770878aaa50d6331293358/8c557/IncrementalEDIDialog.png&quot;
        srcset=&quot;/static/2fb366d226770878aaa50d6331293358/4edbd/IncrementalEDIDialog.png 175w,
/static/2fb366d226770878aaa50d6331293358/13ae7/IncrementalEDIDialog.png 350w,
/static/2fb366d226770878aaa50d6331293358/8c557/IncrementalEDIDialog.png 700w,
/static/2fb366d226770878aaa50d6331293358/e996b/IncrementalEDIDialog.png 1050w,
/static/2fb366d226770878aaa50d6331293358/48ca3/IncrementalEDIDialog.png 1084w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;troubleshooting-and-monitoring&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#troubleshooting-and-monitoring&quot; aria-label=&quot;troubleshooting and monitoring permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Troubleshooting and monitoring&lt;/h2&gt;
&lt;p&gt;Let&apos;s discuss how we can support our periodic exports.&lt;/p&gt;
&lt;h3 id=&quot;test-run-parameter&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#test-run-parameter&quot; aria-label=&quot;test run parameter permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Test run parameter&lt;/h3&gt;
&lt;p&gt;One of the parameters of the base export class is a &lt;strong&gt;Test run&lt;/strong&gt; checkbox. When running with this parameter, the export sends a file to a user&apos;s browser instead of SFTP. For incremental export, it also will not update the &quot;Last exported date&quot; field, so it will not break the export sequence. This is very handy when checking what will be exported without putting anything on SFTP. Also, developers may develop exports without needing to have a connection to SFTP.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 679px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/ab1b50d358f367f0fcd122acb2d70228/1b747/RecentDownloadFile.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 36.57142857142857%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAAA7EAAAOxAGVKw4bAAABmUlEQVR42k2Qu47TQBSG/U5AjYQoKOiQKNAi6GhAoqZBQuIReA0kJErodouVViABWYKTOHHs2JvxzPiSja/xfpwMDSN9OmdmzuU/xzN2R7rNHVeqFAq2Svwsd1bpgswc33M2V4ZE4japETRxkrFRlnQWov0FqdrirdYb+VREydYRi/8/yVUmiYpqtyPPLdYYdJahMuXsAHTfvxF9PUPXI97t+yfcEW7dE/vgOU9evuPpq/ecCI9fvOXhszfcffSaL6cXknqD1v8KFkWBtZYiz8mriuOZTAM8fxawDBZ8Pov48HFBuF4zX8ZM5xG/JGAWhEz9ACOJTddQFqVTWtcNwzA4uq6TXiNt2+ExDtwcepnfsIyU9Bk4DJ1jFHopEoUrUZaRqYw0SUmSRO6auqnp+96pa9vW4V1XhezKcv4jYh7K3mxLpGsiUxPrFm0rpr8v8f0/rFYr1mFIECwd88UCK2q7tqGR4q3gNfuSWWj4dBpz4Wt+blomccdlNDBZH9iaPVqlVGXp2O+vGceDNPAxss/DcWQp2Het4y/hEfuLWEC/twAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Recent download file&quot;
        title=&quot;&quot;
        src=&quot;/static/ab1b50d358f367f0fcd122acb2d70228/1b747/RecentDownloadFile.png&quot;
        srcset=&quot;/static/ab1b50d358f367f0fcd122acb2d70228/4edbd/RecentDownloadFile.png 175w,
/static/ab1b50d358f367f0fcd122acb2d70228/13ae7/RecentDownloadFile.png 350w,
/static/ab1b50d358f367f0fcd122acb2d70228/1b747/RecentDownloadFile.png 679w&quot;
        sizes=&quot;(max-width: 679px) 100vw, 679px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h3 id=&quot;export-log&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#export-log&quot; aria-label=&quot;export log permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Export Log&lt;/h3&gt;
&lt;p&gt;The export log allows one to view how many lines were exported and the time it took to perform the export. For failed jobs, we can setup a standard D365FO alert.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/5923033766da46702df013b7919d0a1b/d5bfb/ExportLog2.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 22.285714285714285%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAYAAACOXx+WAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAvklEQVR42j1Piw7CIBDb/3+kuukUxsZbGTCoB5mSNFfaHqHDbZww3WcwLhDjjiMRckSOAYVmQyatzZ/eMj+/5897m8PMDR5cg60er8VCSAe+GmgbwIXGstnOmVDYyGu8ZYzbsZy5xtWpD4v0WHWAcgl8e8P4TA86+L1iegpcxhek3THOAteJwbwz4YALBQ8mu3+7865rnzAkqumd7XVTpIqlIIQP2nGkG61wHBnOGlijUWv9w3v6sZIdtZa++wViUTOADIUaQwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Export log&quot;
        title=&quot;&quot;
        src=&quot;/static/5923033766da46702df013b7919d0a1b/8c557/ExportLog2.png&quot;
        srcset=&quot;/static/5923033766da46702df013b7919d0a1b/4edbd/ExportLog2.png 175w,
/static/5923033766da46702df013b7919d0a1b/13ae7/ExportLog2.png 350w,
/static/5923033766da46702df013b7919d0a1b/8c557/ExportLog2.png 700w,
/static/5923033766da46702df013b7919d0a1b/e996b/ExportLog2.png 1050w,
/static/5923033766da46702df013b7919d0a1b/d5bfb/ExportLog2.png 1072w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h3 id=&quot;test-connection&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#test-connection&quot; aria-label=&quot;test connection permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Test connection&lt;/h3&gt;
&lt;p&gt;The &lt;strong&gt;Test connection&lt;/strong&gt; button tries to connect to the specified SFTP folder and list files in it. So you can check the connection before running the export.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 466px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/75582bbc27479ed6d4b1abb4d4b7d7ee/fc1a1/TestConnection.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 62.857142857142854%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACWklEQVR42mVTyW7bMBTU//aL+gMNmh7bWw+5NEAApyiQyIaVpLYWy9oXSiIlkpKnj0TsJi2BESXqbTPv0dFqxoePBT7dMEycgY8SbTugH3pUrUKS5RgYnRcF+qIEyxLwsoDo6H/TYBQCXd+j7TokRx+O1hpf7xr8eu4gBoZhoGBk3PcdGOOoybBYu/CvP2N3fY3dF8LVFRrPwzCNkONofcQowNoKjhADJlFhlgO0nMhAQEkCGWs52u+R4IcBVvf3eHhY4+nlGdEhRkkV51R5SRVneUHMGJynsIW3z3EoBJJmxLEW7xDTec0kOefYbNZwXReet8V26+Hl+YUSPMJ9fMCP2ztEIVH+dhviZrXDymuwPkisYwN1gRtphLkkGVoUFLRpa1RVaasyO+sYmprO6Hsk+s73nxXu3BSrbYPtYcYmmrEOFTahtnADjSCTVh8/DGlvKThpTRobucwekRxhEGK/+w3HPzL89hMEcQ3/UCGriGKnULaTRdFMaDoBwXukSUKNaiGnCaaZyzJjnrWtTAgOTs1xGFEIA9/yN7vJPmuFt8s4G4eMRojTmJh1Op0ueLucnqKmaWazSKXAObdjMC/LBUpJS8+nhGmS2iALnZ8xz/Pl3eF8oA6SwEbYqrLBjIMxOkNJSQPMacgL5GWJlgbdOL9d50odRtMe+EQ5iuDv98hpnv5dmiSYiEFWT3STFLR6D6OppKSvlHtLw1A2lchJvqOznCkTk/gYU5UZjU9JgbTVdn7FuWLHPKzjacFpOf2njw1obhDdnJSacohjq/kxia1EVuf5b8A/wpXb46MzIZYAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Test connection&quot;
        title=&quot;&quot;
        src=&quot;/static/75582bbc27479ed6d4b1abb4d4b7d7ee/fc1a1/TestConnection.png&quot;
        srcset=&quot;/static/75582bbc27479ed6d4b1abb4d4b7d7ee/4edbd/TestConnection.png 175w,
/static/75582bbc27479ed6d4b1abb4d4b7d7ee/13ae7/TestConnection.png 350w,
/static/75582bbc27479ed6d4b1abb4d4b7d7ee/fc1a1/TestConnection.png 466w&quot;
        sizes=&quot;(max-width: 466px) 100vw, 466px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;summary&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#summary&quot; aria-label=&quot;summary permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Summary&lt;/h2&gt;
&lt;p&gt;In this post, I have described different types of periodic exports to file from Dynamics 365 Finance and Operations based on the &lt;strong&gt;External Integration&lt;/strong&gt; framework. We discussed the following exports:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Simple SQL query export&lt;/li&gt;
&lt;li&gt;Export based on custom X++ code and query settings&lt;/li&gt;
&lt;li&gt;Incremental X++ export&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All used classes can be found on &lt;a href=&quot;https://github.com/TrudAX/XppTools/tree/master/DEVTutorial/DEVExternalIntegrationSamples&quot;&gt;GitHub&lt;/a&gt; and can be used as a starting point for your own integrations.&lt;/p&gt;
&lt;p&gt;I hope you find this information useful. As always, if you see any improvements, suggestions, or have questions about this work, don&apos;t hesitate to contact me.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Step-by-Step Guide: Creating D365FO Build and Deploy Pipelines]]></title><description><![CDATA[Learn how to set up DevOps-hosted Build and Deploy pipelines for Dynamics 365 for Finance and Operations in this detailed guide]]></description><link>https://denistrunin.com/d365fo-buildrelease/</link><guid isPermaLink="false">https://denistrunin.com/d365fo-buildrelease/</guid><pubDate>Fri, 08 Sep 2023 22:12:03 GMT</pubDate><content:encoded>&lt;h2 id=&quot;setup-azure-build-pipeline&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#setup-azure-build-pipeline&quot; aria-label=&quot;setup azure build pipeline permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Setup Azure Build Pipeline&lt;/h2&gt;
&lt;p&gt;This guide will walk through the standard procedures for setting up a D365FO Azure-hosted build pipeline.&lt;/p&gt;
&lt;h3 id=&quot;references&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#references&quot; aria-label=&quot;references permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;References&lt;/h3&gt;
&lt;p&gt;Before we begin, please refer to the following documentation for context:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://learn.microsoft.com/en-us/dynamics365/fin-ops-core/dev-itpro/dev-tools/hosted-build-automation&quot;&gt;Build automation that uses Microsoft-hosted agents and Azure Pipelines&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/dynamics365/fin-ops-core/dev-itpro/dev-tools/pipeline-asset-upload&quot;&gt;Upload assets by using Azure Pipelines&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://learn.microsoft.com/en-us/dynamics365/fin-ops-core/dev-itpro/dev-tools/pipeline-lcs-connection&quot;&gt;Create a Dynamics Lifecycle Services connection in Azure pipelines&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;procedure-detail&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#procedure-detail&quot; aria-label=&quot;procedure detail permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Procedure detail&lt;/h2&gt;
&lt;h3 id=&quot;pre-checks&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#pre-checks&quot; aria-label=&quot;pre checks permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Pre-checks&lt;/h3&gt;
&lt;p&gt;Before diving into the setup, perform a few essential pre-checks:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Install the «Dynamics 365 Finance and Operations Tools» extension&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/887ae32b1abcd7a1e5d1f77a73e524bf/3534c/PreCheckExtension.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 62.28571428571429%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAA7EAAAOxAGVKw4bAAABQ0lEQVR42p2RW0/DMAyF9///HQ/wBnRCNM2arGlza3rZwfYu0kCIUUtWUyX+fHy8U36BDguUX+HHGdNcsK4rxjJiWRaUUlCmIuecs9ydTqdfcxfSCB8TQsoIIUpRSgnTNBF8+gH4K3Ztq/H+9opa1ZKtaaGaBn3v0B40QowCZYXr+gCQR/LeE6DHQF8ubghojj2UcXI3DAOpD8jj+BiQCwqNyGceS2uNp5dnfDbq1iiS0kS28Lt5ns+WfMuVPcw5wRgjj66hdYPmw8JZVsYKe2nKKQ0GT1YExBQxkmquZUtkKazKWiMKbsBDg/qtg3fpAuvhnBOYJP1zI7aBVfMiGSgjs9Su684dLsC6rmWELUFAUni0dwAGlrIRyCO35KG1VjbKoZSSBW0Gsj9s7hXCwM0j84arqhKIp+2xymq/v9v6f4BfOQ6qgDbPPccAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Extensions&quot;
        title=&quot;&quot;
        src=&quot;/static/887ae32b1abcd7a1e5d1f77a73e524bf/8c557/PreCheckExtension.png&quot;
        srcset=&quot;/static/887ae32b1abcd7a1e5d1f77a73e524bf/4edbd/PreCheckExtension.png 175w,
/static/887ae32b1abcd7a1e5d1f77a73e524bf/13ae7/PreCheckExtension.png 350w,
/static/887ae32b1abcd7a1e5d1f77a73e524bf/8c557/PreCheckExtension.png 700w,
/static/887ae32b1abcd7a1e5d1f77a73e524bf/3534c/PreCheckExtension.png 808w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Create personal access token (az)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Navigate to DevOps &gt; User Settings &gt; Personal Access Tokens.
Scopes: Full Access, Expiration – 1 year (maximum)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Create a service account user with no MFA and &lt;a href=&quot;https://learn.microsoft.com/en-us/dynamics365/fin-ops-core/dev-itpro/dev-tools/pipeline-lcs-connection&quot;&gt;Application&lt;/a&gt; registration&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;creating-the-build-pipeline&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#creating-the-build-pipeline&quot; aria-label=&quot;creating the build pipeline permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Creating the Build Pipeline&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Download the 4 NuGet files to your local PC&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 562px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/407cd0b3d812458e15b383ec6bd31374/6e88f/LCSDownload.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 65.71428571428571%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACc0lEQVR42qVSO2/UQBj0r0QpeEgkApQKipAmgZwERKAkFQoJEqSEHqFAAQUN4pmOikS5p332eu31a71+3DDrCwgkqLjT+Lu19pvvm5lzrq5sYWX3PVb3PuBK7znOXV7BwtIqFhZv4vy1NVxcvvVPXFhex+L1DSzd6PG8hkuE09s6wM6zL3j68hu2Dt5g/d5D9B7sY+P+Hm5v7v6GR3/BLu5s7+Pu9mP27GFz5wmcqtLQWYhcCWRKom1q/M/H8QMB15tCyAilMdBFgVIXCPh+OBwTI4QhB+Y5sixDnuVEhoJnC13M8fPspEmCNE1JolGWGoakbduwOYdSqqu2IcvLDmk2r3VlYOz9M9hzZUo4UkpMXBf+dArf97lJgaZpeKmEjAuorEaa112NUyKpqaTBbNZyeIWqqhCSQ3Mhu4AjRIDBcMjtyrkJsxlmbctpBlIZBJFBxCpiA5Ua5LpCXdfdUIuWd5NEoSBhmqRw4kjCdT0IemandRfZYLi+JQzjObEltL91WTO45g/CWMXI6X2ikrmHVnYUx78m21pbKTGhavhR3VUR19BWbvfF2ROQ0Ty0OIroYSgwGg1JGnabWbl80I8Mx6cKJ8MU3/sJjgcJxlM2qQKGzSWT1qmtBXwR0tscgSChxzA8P0RWGJrd0oumm3p0NMKLdxO8/ixx+EngFXH4UeDtV4HJYIpg4sMd066BwOmJi3FYYuBS8tiT+M6XfU9BqAZTSZlMUwc+pJ/RCnonNUSoqUIjkiWKzGBm1VgP6Z0Y9BmWnkuOGIrHv43nuV1aNuWWKOjrtO/DG3GLYYgJ4REhF9BRDBPPUREyCLqU7d/mB11RsUx8AneEAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;LCS download&quot;
        title=&quot;&quot;
        src=&quot;/static/407cd0b3d812458e15b383ec6bd31374/6e88f/LCSDownload.png&quot;
        srcset=&quot;/static/407cd0b3d812458e15b383ec6bd31374/4edbd/LCSDownload.png 175w,
/static/407cd0b3d812458e15b383ec6bd31374/13ae7/LCSDownload.png 350w,
/static/407cd0b3d812458e15b383ec6bd31374/6e88f/LCSDownload.png 562w&quot;
        sizes=&quot;(max-width: 562px) 100vw, 562px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Log in to DevOps &gt; Your Project &gt; Artifacts &gt; Create Feed&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 350px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/1aed2edc7d11554bdfe36502ab4ea328/13ae7/CreateFeed.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 121.14285714285715%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAYCAYAAAD6S912AAAACXBIWXMAAA7EAAAOxAGVKw4bAAACX0lEQVR42qVV6dLaMAzk/Z+mr9H/0OkMUxqukJA7jhNCjq3WwcGUfvQ7MrMjyzZrWVqLRZ7nWK/XWK1W2Gw2Zkwsl0vUdQ1+4zji1Xe9XtG2LS6XCxYk/O158HZbnE4BfP9k7Ha7RVGUqKoKWmtoIa/EKvGrSqxSaJoGPGoYBowC+otKFsahl8n+FskodhAzmHkXdg5m/WadjzdapIWCFyn4WY1Y90gqgb6hHpAKJn+ys2/WepxVB90Od8IgVVh5MX7+WOMQ5kibUUi7O+kLZEK4z644FZ0h1JoRxtlEolrEQsQo/weXNJLfNJ0TYZmkUqULmlqbxH7lmwijBJUMwiBEWZam/E1zEXs1MjCQubpuUMt8398PHR3MhHGm8H3fIssykcsJYRgiiiLEcTz7xPF4xG63M/t4COVE/bk6nSIsRU/daBzqjZuN7vSktb6f5EStEfRd+0SYJJGcJAWRqHzfN9ERjGi/389psC+BoICtz7ElNoRaV7NjwehsRF3XPYFkvC6jpH0gLOTKrZzEPDFnQRCYSLloI3Ej5DwtiTjmAQ9V9kTM5oH/FYV98LQW7rW5h5ZRPhAmuXpXR3m3DtkcijxDkiTSXYoZnzlg0mFe4tuqRJKmJn/n89nkkpWm5ghqMpV1ztFyj9Xg80uRoiRq0p5bZTtm3lwdWvzrBoaQ4mX/s5WzibdjN+nvurJSFYbx7aJ8JJdzhE1VmGeGWzu3+CixIcykY/9KOpPow+FgCmObgRU6nyCL477fNwn5F7COu7kp2PdpGwTBzmKL9Sqn96L0LfjvZ9sWST8r7D9nnE3gQun36gAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Create feed&quot;
        title=&quot;&quot;
        src=&quot;/static/1aed2edc7d11554bdfe36502ab4ea328/13ae7/CreateFeed.png&quot;
        srcset=&quot;/static/1aed2edc7d11554bdfe36502ab4ea328/4edbd/CreateFeed.png 175w,
/static/1aed2edc7d11554bdfe36502ab4ea328/13ae7/CreateFeed.png 350w&quot;
        sizes=&quot;(max-width: 350px) 100vw, 350px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Click the &lt;strong&gt;Connect to Feed&lt;/strong&gt; button and select NuGet.exe&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 623px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/8eec2168e190ee144b68619de2ca7a14/6114d/NugetFeed.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 69.14285714285714%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACiUlEQVR42m1Uy27UQBD0l3HmyIlvQHwA4oi4wIWHxIlDJM4RSAiJQwQHkLiE8FAEElGS3bD2ru31az32zHjGr6J7liW7ESOV7Gl7qrur2vaapoExBsMwwFqLvu/Bsa7r3B4j3OJ9VVVQSqFtWwd+vsE49A6e1hp5nmGxWCBJEiyXS2gizLIMZSVRlgI1E0mJlg5ysm1Ya6C1wY9FjS9+BY+DWZoiCiMUReGglMYyjjCZL3FyfoHzyQTzMEZNcS6AO2I0jYGla1lr3DuIcOtVwBUq2Na6tsZxdOC2oyhCR20pvT5Q1gqFkETYUKW77bZ0vmsNWiL30nAFUVSOaHvFVGFjLFViIWXtWlZKko41qppQkRR0lRQvhYBh/ckHz58kSMKcyteUbZ2Z22FNeT8M64r/h67vnJkNyTAPApIthHf46xyn0ykCP0BMhrApcRxjNps5wS/bai/d3brfgIuw1I2Xx1Rytm6Bg5yZXwgpG+9XqxU5nkPSuDid/0oybmm+kYuvnhTklqIM5PbQD/8ecJUci6MYYZwizQrqgORJMkpQoJbKJUtTitGULOn9mvT1ZLlCZ3ddHkkXJuSRytMYssphlICuVrC6gpYl+lY73RWPkdN9/YF4ehZAkm79rsk0NjGNh8FPX+BwqvDtt8X3GQ3w3ODYbxyEYPfJaXKbJ6DIcyJ0097i6mLCoTO4+8bi+vMeN1+0eHkkcDzN8fm0wNFZQe2nyDNG4u59MtZriL2uSvpW+x3CkAhBhLf3Da4963Fjr8Od1xpP3ks8Jjx6J/HgQOEh4f5bhb1PFc4CqrAnR7t2/VO4WmFP07//1eLxhw5PCR9PFOZJhVm8gYC/FLiIBLKihCgL/AFvdye+NekekAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;NuGetFeed&quot;
        title=&quot;&quot;
        src=&quot;/static/8eec2168e190ee144b68619de2ca7a14/6114d/NugetFeed.png&quot;
        srcset=&quot;/static/8eec2168e190ee144b68619de2ca7a14/4edbd/NugetFeed.png 175w,
/static/8eec2168e190ee144b68619de2ca7a14/13ae7/NugetFeed.png 350w,
/static/8eec2168e190ee144b68619de2ca7a14/6114d/NugetFeed.png 623w&quot;
        sizes=&quot;(max-width: 623px) 100vw, 623px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Copy the selected text and paste it into the &lt;strong&gt;nuget.config&lt;/strong&gt; file in the same directory as the previous packages.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Click the &lt;strong&gt;Get the Tools&lt;/strong&gt; button and download the latest version of &lt;strong&gt;nuget.exe&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a new file named &lt;strong&gt;packages.config&lt;/strong&gt; and add the following content (ensure correct version numbers):&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;xml&quot;&gt;&lt;pre class=&quot;language-xml&quot;&gt;&lt;code class=&quot;language-xml&quot;&gt;&lt;span class=&quot;token prolog&quot;&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;packages&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;    
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;package&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;microsoft.dynamics.ax.application1.devalm.buildxpp&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;10.0.2177.37&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;targetFramework&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;net40&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;package&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;microsoft.dynamics.ax.application2.devalm.buildxpp&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;10.0.2177.37&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;targetFramework&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;net40&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;package&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;microsoft.dynamics.ax.applicationsuite.devalm.buildxpp&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;10.0.2177.37&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;targetFramework&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;net40&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;package&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;microsoft.dynamics.ax.platform.compilerpackage&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;7.0.7521.60&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;targetFramework&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;net40&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;package&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;microsoft.dynamics.ax.platform.devalm.buildxpp&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;7.0.7521.60&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;targetFramework&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;net40&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;packages&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Obtain the version number from the package files(there should be 2 different versions, 2 for Applications and 2 for Platform).&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 624px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/3ca2bfe6f58d5140ce2111caa1cbba2b/39c09/VersionNumber.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 41.142857142857146%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABdklEQVR42n2RW07DMBBFs/81sADWgEDiE/GDKrVQiiilbfxI4rxp877ccRWE+MCSNbI9vnPuTLA/vCFJUkRRhDhKEMcxz5cYx5dorUXiHLIsQ1XXcE7yY2ilUVUViqLkH4e2bRFkdsGkFv+uaULf976oCBZ5DqUUxnHCxOdxHDEMA9MmBDp8YaLD+XTCwE991/nPnUQm9mWJRmuvK4Q1BSfea2OQ8ixuhGxewXqnsd++42P3CUOCyFhaj2AoYm0Ex1iTqGk7T5ZzC42Ia74dw9AXkbuOIME4Dt7SFwkVqxpaUaFCGGof87xgz9i/NEXNfpUkFmt/l9iWHcxPTXPGlqQ7kmoVokg4CKtwPB5hrEFW5DidzxQsSJd7QqGVAnX95cW85d8VLK0+r5ZYvB1wszR42JiLfZnyfg+z3cLQhdLKT71pGt8/6flMHcyo0gPpxWa9wt3jEle3L7i+X2DFAq+bDdZPTzgwJi7x03apQ1VWP2TzUL4BgwVhYivIJm4AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Version number&quot;
        title=&quot;&quot;
        src=&quot;/static/3ca2bfe6f58d5140ce2111caa1cbba2b/39c09/VersionNumber.png&quot;
        srcset=&quot;/static/3ca2bfe6f58d5140ce2111caa1cbba2b/4edbd/VersionNumber.png 175w,
/static/3ca2bfe6f58d5140ce2111caa1cbba2b/13ae7/VersionNumber.png 350w,
/static/3ca2bfe6f58d5140ce2111caa1cbba2b/39c09/VersionNumber.png 624w&quot;
        sizes=&quot;(max-width: 624px) 100vw, 624px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Open the command line and run the following command for each NuGet file:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cmd&quot;&gt;&lt;pre class=&quot;language-cmd&quot;&gt;&lt;code class=&quot;language-cmd&quot;&gt;nuget.exe push -Source &amp;quot;Dynamics365FO&amp;quot; -ApiKey az C:\AAA\Build\Microsoft.Dynamics.AX.Application1.DevALM.BuildXpp.nupkg
nuget.exe push -Source &amp;quot;Dynamics365FO&amp;quot; -ApiKey az C:\AAA\Build\Microsoft.Dynamics.AX.Application2.DevALM.BuildXpp.nupkg
nuget.exe push -Source &amp;quot;Dynamics365FO&amp;quot; -ApiKey az C:\AAA\Build\Microsoft.Dynamics.AX.ApplicationSuite.DevALM.BuildXpp.nupkg
nuget.exe push -Source &amp;quot;Dynamics365FO&amp;quot; -ApiKey az C:\AAA\Build\Microsoft.Dynamics.AX.Platform.CompilerPackage.nupkg
nuget.exe push -Source &amp;quot;Dynamics365FO&amp;quot; -ApiKey az C:\AAA\Build\Microsoft.Dynamics.AX.Platform.DevALM.BuildXpp.nupkg&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When prompted, use: Username = az; Password = token value&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a new solution with an empty project for each package you want to build. No need to include nested packages. Copy &lt;strong&gt;nuget.config&lt;/strong&gt; and &lt;strong&gt;packages.config&lt;/strong&gt; to the solution folder.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 353px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/a8da0001a7cce8b2455a5c5e4d8400dc/6c115/AzureProject.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 88.57142857142857%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAYAAABb0P4QAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACqElEQVR42pVU2XLaQBDk//8nLld8BRtcxIDQgYTuAyEQQgJDOHShzkhgJ9jYTh56R8dW78x0z9ZuOz6+XYl4YHw8dH00eiEeuYhigHv6d/dzhHpnQv8D+jarYpMt4xQNeu4qMRg1eUXturvEza2HetvG5b2Oi7pOBD6+Ny1c3Cm4rGu4abmodyfVAT/aE1w1jWrvdctBT88hWAB/RC0IIiyeV0hCFYE/Rr+vQFU0OLYHRTFgD8dIsz2yHKBQIS9RHGKSFieobeI94mSPcFug19dgmUOY9ggDWYc78iFwIhx3UhFsdjm2tP9v7JLiBLVyybMCYQy0WBm27UA3bIiSClW1iHQCVaPoBVVGaX7AW6JXwuWvGNFyB82LwAgynp46YHoCWF5Ct8uiQ2C5Ph4aLWimA28ygzueYU3Zxul74tp0toDozqHZY5iUWbvNgCGCNpGqqkEHMODovTyEofLLAxqtDlbr5DxhQuVm2aHJujWBppkQRRnSwICimrCdEZVYHETJj4LsPyk5jJZQxwtwkoHBQEGPsjGpNF4QIUk6epSZJJsnQmzOiPGnh6sdgmWCBfXSo95YpHBfVCCTIIbpwrJGCOfrDwneEZZWWG1SRIs1OEFFu8NSpioE8qNIxDwJtVht/53Qn0bghyFEbQiXTMxzEnTdhkawKbu+MCBPWmc9d5bwRRTSBIbjE5EFnizTp/4pigmLRMn2RSVaOQnb+AvCcL6CRqII1HiFbPL4+ASVspNJZZneJUkBK0hgWRHBbImElP4s29r8eQ0v2sAPV9U0lPPL8WWZBnQaQ8NwMKa2uKMpnmkAznnvhLDckFIpZC2ahBEU8qFZElH/bLogXM9H1RbaEJclf9XDctkeURo4PRo4O85smhUfXgQfEr7g7U3yP0QvhL8BFAFHeafG3EsAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Project&quot;
        title=&quot;&quot;
        src=&quot;/static/a8da0001a7cce8b2455a5c5e4d8400dc/6c115/AzureProject.png&quot;
        srcset=&quot;/static/a8da0001a7cce8b2455a5c5e4d8400dc/4edbd/AzureProject.png 175w,
/static/a8da0001a7cce8b2455a5c5e4d8400dc/13ae7/AzureProject.png 350w,
/static/a8da0001a7cce8b2455a5c5e4d8400dc/6c115/AzureProject.png 353w&quot;
        sizes=&quot;(max-width: 353px) 100vw, 353px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Download the sample pipeline from the following GitHub account:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/microsoft/Dynamics365-Xpp-Samples-Tools&quot;&gt;https://github.com/microsoft/Dynamics365-Xpp-Samples-Tools&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;(Note: Some users reported issue with wrong task ID, not used now - &lt;a href=&quot;https://github.com/microsoft/Dynamics365-Xpp-Samples-Tools/pull/2/files&quot;&gt;https://github.com/microsoft/Dynamics365-Xpp-Samples-Tools/pull/2/files&lt;/a&gt; )&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Open a &lt;strong&gt;PowerShell&lt;/strong&gt; prompt and run the following commands to create a new pipeline:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;powershell&quot;&gt;&lt;pre class=&quot;language-powershell&quot;&gt;&lt;code class=&quot;language-powershell&quot;&gt;cd C:\Users\Admin05ec84c604\Downloads\Dynamics365-Xpp-Samples-Tools-master\CI-CD\Pipeline-Samples

&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;xpp-classic-ci-&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ps1 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This will create a new build pipeline.&lt;/p&gt;
&lt;h3 id=&quot;adjusting-the-build-pipeline-parameters&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#adjusting-the-build-pipeline-parameters&quot; aria-label=&quot;adjusting the build pipeline parameters permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Adjusting the Build Pipeline Parameters&lt;/h3&gt;
&lt;p&gt;Open the created pipeline and make the following adjustments:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Click &lt;strong&gt;Get sources&lt;/strong&gt; and specify the full path to the source code.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 626px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/1126c35782963017078fe3ea9e00f0f2/af590/SourcePath.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 52%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABm0lEQVR42n1S2W7jMAzU///LfkSLfe1DgSLpQ9cx2hw+JVmHLcuWZ0mlAZqiqICBKYoaD4cSIcyIcUEIAePosSwreG3bhtu6iwmJ9pza8nfDPM+EQHcXCCaKMcJ7j8GYnGTSlDZCyrhdXCm3rgsxUS4t1zzulzDOE9mYC5l4iax4pv36SbiyFFKVco2yAUe9oBnip95vhFWnca562GmBD+mKOcGFleIrODaEQNaUfcKfpxF//0V0g0drZ7JqzJ1xt+JQWezLGm8niaK2ONQO7334ER8yYKJLry/PqOoGr8U7ikuP3X4PpTUORQFhKdAEbo09ufn2HWwBe8sDKMsSvR5Qnht02mZlgYZirYV46xyOrYLRCsNgso+3yf4EPn98fEDTttjtdlBK370E0bae5BrIvs9K2YvfFhNGqpmnCSupTSyA7zCoE6Fqj67WkErCkELnHJznyTt4fgGEr+/Q0rmmn9fkl7qcMUqJSSmEXsKTalFXHdqmh7GGWtaEIUNSkaRiRd+vhIFUBZqquVzQHj/QnU5wXQdPsFWF/0AFBhFxQPYjAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Source path&quot;
        title=&quot;&quot;
        src=&quot;/static/1126c35782963017078fe3ea9e00f0f2/af590/SourcePath.png&quot;
        srcset=&quot;/static/1126c35782963017078fe3ea9e00f0f2/4edbd/SourcePath.png 175w,
/static/1126c35782963017078fe3ea9e00f0f2/13ae7/SourcePath.png 350w,
/static/1126c35782963017078fe3ea9e00f0f2/af590/SourcePath.png 626w&quot;
        sizes=&quot;(max-width: 626px) 100vw, 626px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Update the path to the build Solution with empty projects:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/38d3b1ca92eefbf9842fbe9698064501/33a7b/SolutionPath.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 41.142857142857146%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABQUlEQVR42n2SiU7DMBBE/f/fB0IUEKgS0DaxY69vx86wTiJUqopIT94c3szMWsylYJ4LnHNYluUPrd3c7+t/l5DaQBuDkAJ88CshBsScYZ1FTHGtY+Q1ZWSuW2srvXlt24/rjlA0YZgGGG9gIzeY411SScgprU5688LOuuJYKtMQcoXLDYJIw1paX260GyoaW5mMhvee45l/1d2zLw4y4DwqGM2NyWLhj3GdZds26UlzNHpVmHNCyYXZIugkVt9XoVTCZZAY5Ajqg+HN19RdhSaDUUpGYeLcydoV0yGC9TwDjkK8fAQ8HhWevic8nw1eB4eXi8WBeZMen2HBuwMejgOUISjykMZBu8CNPKvm2nO2EyFxjuLrPOLElpV1PBxWoQkXpXGSE0ZjkeYFmUX2Z4ZPA9Gmrta6R9JWJ4XzLUT4Abckbes0CG6zAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Solution path&quot;
        title=&quot;&quot;
        src=&quot;/static/38d3b1ca92eefbf9842fbe9698064501/8c557/SolutionPath.png&quot;
        srcset=&quot;/static/38d3b1ca92eefbf9842fbe9698064501/4edbd/SolutionPath.png 175w,
/static/38d3b1ca92eefbf9842fbe9698064501/13ae7/SolutionPath.png 350w,
/static/38d3b1ca92eefbf9842fbe9698064501/8c557/SolutionPath.png 700w,
/static/38d3b1ca92eefbf9842fbe9698064501/e996b/SolutionPath.png 1050w,
/static/38d3b1ca92eefbf9842fbe9698064501/33a7b/SolutionPath.png 1119w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Update the &lt;strong&gt;NugetConfigsPath&lt;/strong&gt; path on the &lt;strong&gt;Variables&lt;/strong&gt; tab to: &lt;em&gt;$(Build.SourcesDirectory)\Projects\AzureBuild&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Optionally, enable the &lt;strong&gt;Licenses Load&lt;/strong&gt; task:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;$(Build.SourcesDirectory)\Licences*.txt&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 644px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/fd3651548c9d428697b36c8c089d1342/78274/Licence.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 50.857142857142854%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABhElEQVR42oWSYY+kIAyG/f//75L9cFln3JkBEbCAooL6XtHdvbnL5K7JE0hT2rctlTEWbavQ2x7UE7z3GIbhJeM4Ii0LFmZdVxTb9x3PVgV3Jlm37YQDX5FzZlZM8wzH8XNJzL6UEzZOuvHbQvVTj3i0HYJz8MxX5d/2p4JAPeT9hk5KtOIBJQTIGERWX5RXNzWhfnRohILQBDdlDMuO8My88bmBfARdG3R1DXO5fOObBttnJ5VoAu7CQKgOnSXo3sMUyJ93CpjShjnvfK4YeM49qyPFc5ctbFGoNWJkhTMrNNLCk8PIjngMP2AMAYHnFDz72fdscZpgrIXl1sssPccSj8o5f5zV1RRV5eGImStklp1SYjLPJB33ssiDknCMMKyoLLK0+bWM76Vc9QJtHX8ZgynGw/kvKwUix5UF/P1ljm+jRcSHsLgIjfqu0EgDRSP6mEFxPZlWWD67sPy3YPXe9PhRS7w1Cm/XFu+SUEuHByUIlw8kc6OMWp0dFGWv1JWEvwCKzgW0EiAhQwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Licence&quot;
        title=&quot;&quot;
        src=&quot;/static/fd3651548c9d428697b36c8c089d1342/78274/Licence.png&quot;
        srcset=&quot;/static/fd3651548c9d428697b36c8c089d1342/4edbd/Licence.png 175w,
/static/fd3651548c9d428697b36c8c089d1342/13ae7/Licence.png 350w,
/static/fd3651548c9d428697b36c8c089d1342/78274/Licence.png 644w&quot;
        sizes=&quot;(max-width: 644px) 100vw, 644px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Run the pipeline and verify that everything is working as expected.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;updating-the-build-pipeline-to-a-new-version&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#updating-the-build-pipeline-to-a-new-version&quot; aria-label=&quot;updating the build pipeline to a new version permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Updating the Build Pipeline to a new version&lt;/h2&gt;
&lt;p&gt;If you need to update a Build Pipeline to a new version follow these steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Execute steps 1-6 from the Create pipeline process&lt;/li&gt;
&lt;li&gt;Copy &lt;strong&gt;nuget.config&lt;/strong&gt; and &lt;strong&gt;packages.config&lt;/strong&gt; files to the AxBuild solution folder(replace existing files).&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;creating-a-new-release-pipeline&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#creating-a-new-release-pipeline&quot; aria-label=&quot;creating a new release pipeline permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Creating a New Release Pipeline&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Open &lt;strong&gt;Pipeline &gt; Releases&lt;/strong&gt; and create a new pipeline based on the Empty job.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/36bc6f72498769bf22a5677e3afcbada/35a31/ReleasePipeline.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 40.57142857142858%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABQElEQVR42k2Si7KDIAxE/f8P7W1rVZSHgIG9m2idOhOFYJazgaEeBw6RMziutUI4FjnQWsPvI00sd4bc+VYK0Ds6x0MuFT5llCqMihgjfPAWad+tuPduhQc30fziFrwnB18ayuKwv162nqgxqEiphxV1FhtFP0VUTGltjaEOmgZztXUUYZ5jXBsaof5YSsaed1Q5hQotZOaq9JtO352bPX3Ce/Moe0JKEYGOMmv7BTEowd2XjpvsnPdTSnNKScufA/ij4LosWLcNbqV17xEpriCD2iAIIoUzi+RLREHnA95rgNsr1pghNWMUFQyIfmM/AwJDBVNKVjeInjJFfgWNkvMpJDwoOMaCOfH02etXcnjMIwkdpmnCQtJ5mY1U4Sh4Nv1r/XsARnldBVvXK8TJ6J+Ytg9KLmYz58zbkOyrPfwHa7hzCk4XntwAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Release pipeline&quot;
        title=&quot;&quot;
        src=&quot;/static/36bc6f72498769bf22a5677e3afcbada/8c557/ReleasePipeline.png&quot;
        srcset=&quot;/static/36bc6f72498769bf22a5677e3afcbada/4edbd/ReleasePipeline.png 175w,
/static/36bc6f72498769bf22a5677e3afcbada/13ae7/ReleasePipeline.png 350w,
/static/36bc6f72498769bf22a5677e3afcbada/8c557/ReleasePipeline.png 700w,
/static/36bc6f72498769bf22a5677e3afcbada/35a31/ReleasePipeline.png 1028w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Add a new artifact&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 614px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/37dd16ab6ee305ca5c3505fef6445a84/e9131/AddReleaseArrifact.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 64%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABj0lEQVR42p1Ty27CQAzM/x/6B/2aHnroB6D2gigqCQRBSLLv3Uw9SxMCVGqFpcnDscdje1M47+F8RBA4a2EMYTKGYcCt0RdCgNYafd/nuLkVxjp0SsMKmXNOAk0OJrwUiyldJSR59xLHWCtIN98LF1JO4gdWv6jiM/3D5CcYF0XhqlZYbFrYACG3OYMCCgZYke0lKKZzgtF8j3fqaLl4jHgve7x+7NC7hHpbIcaU2y9Y1fsAzpIkkwohF/GCIWMUnlv2DvvOYX2w6EzI3Uwts+LXvsXmaLBXHgNVSbbSFvVJobURnaiwLswIPZQsxP/McD6SgjM6tlqSNZrdAUPwOZGbtLKwIO2Bs4znQhyCWa/RErI4jitIgTQS8hLFEUS2XSzglsvxfEy3+ekhoW1b9Mcjuq7LhWOMF4Xj2coVOPAQ8JuN259aViq3TLJ528VNFv6ykfB0OqFpmit194T/MBKyzbqusfpc5b+Fagmt1aOEHk2nUG5rVFWVUW42qMrqMcIohE8vezy/Hc6+2aS+AbIp/UbRU4MTAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;New artifact&quot;
        title=&quot;&quot;
        src=&quot;/static/37dd16ab6ee305ca5c3505fef6445a84/e9131/AddReleaseArrifact.png&quot;
        srcset=&quot;/static/37dd16ab6ee305ca5c3505fef6445a84/4edbd/AddReleaseArrifact.png 175w,
/static/37dd16ab6ee305ca5c3505fef6445a84/13ae7/AddReleaseArrifact.png 350w,
/static/37dd16ab6ee305ca5c3505fef6445a84/e9131/AddReleaseArrifact.png 614w&quot;
        sizes=&quot;(max-width: 614px) 100vw, 614px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Add the &lt;strong&gt;Install MSAL.PS to enable authentication&lt;/strong&gt; task.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Add the &lt;strong&gt;Dynamics Lifecycle Services (LCS) Asset Upload&lt;/strong&gt; task.&lt;/p&gt;
&lt;p&gt;In this task create a new Connection:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;UserId&lt;/strong&gt;: &lt;a href=&quot;mailto:svc_Dev_LCS@xxx.onmicrosoft.com&quot;&gt;svc_Dev_LCS@xxx.onmicrosoft.com&lt;/a&gt; (service account, no MFA)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://learn.microsoft.com/en-us/dynamics365/fin-ops-core/dev-itpro/dev-tools/pipeline-lcs-connection&quot;&gt;Application&lt;/a&gt; (Client) ID&lt;/strong&gt;: 2eb122fa-a3d0-4a15-b2ff-a8b0339xxxxx&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 276px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/876a513639ca4338d0cbfc6bcdfe4c5b/f2d11/LCSConnection.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 193.71428571428572%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAnCAYAAAAPZ2gOAAAACXBIWXMAAA7EAAAOxAGVKw4bAAADPklEQVR42qWWe27aQBDG9zDtBaueoT1Gz9BeoX8kahQhpQ8FlYbwCi+DwQ8w2Ga6vw1DNgQSk1j6NOvxejzzzWNtlsulZFkmRVHIarVyWK/XDqx5xh6ev3Sxx9TrdTk7O5Pr62up1WpyeXkp6K6uruTi4sLdn5+fS6/Xcy9tNpujBufzuRg2tNsdSdN056F6pd6rfrFY7MD9ocvMZjNpNBrWaFtub2+l0+lIt9uVVqvl1ugBumazudNPJpPdh3wYuMrzfMeZcoh3yiUeEQG6JEncHiIry/IJTBzH7mt4qnI6nToEQeB0fLDq5ULu9/vu5fF47KQaGgwGMhqNnFd+BM/BeXh3d+dexjBrJFlVHUarGHMGwzCU4XDoXkLiHTo8JGyVqoNP5fYQTBRFOy+Q1NJbLoObWnNVuuFFg4QDX3BHaZB6DO+DTKs8BhcyGYQfQibLFC5FTDFDAbySHP0oScSwcvbEoJaNZhXDCozxEcA9CdMEwb3WLFJ1RnsUT+FxvwPwZl9q+PtUuGmjbYV8bpJUTgq1RbiE7ffva+E8JH5klSy+aBBCId0nmuIGrPUeWSUCs193fin4xIMqHDsOtebwVIcD+kMjn/tDha9wvUy96QjTQeGPMuoTPR/T+egXtn+oOQ4Z6Wwm27pW0DXoeMYRgXG6BV5V4hQgsUYTgdSHmhQSRSfoWo9b/wDDiH8UG0LjkNIePdQJel8pKcqBbn5rt7gsayJ0ysCTHpXHTrdjcBxCuH9u+Ic761NgFpZQHUEr0g8FFqyX/EGcCLNIE0njuUUkaRJJPJ9JPLO9bfXbUj4J5l8/lJ/NofxujaTem8qv26H8seu//ZkM4kL6UX4STHueS2lt55vHWFtlZhenwjSCTOKskPnyMaKsfBVMuChknOQOwVbuY18fpMVRmMgmIBgOJLFJeUjCGwo7tb3o/3mF26F6/wcW2rXta1urU35Ftn9lRVEKDaV4GG3WYGFrjoKkwOln4K85wIA/WegIvdbFRiZJIVBXYjBa5tKdpla5klGcVQ4tL+9d+/JjJu8+3cj7zzdS69nCjhZraQeJQ2tsPcry3ZA4NK1VV27l95uFfPg6lI/fRtIK1/If4W/LscLTFZcAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;LCS connection&quot;
        title=&quot;&quot;
        src=&quot;/static/876a513639ca4338d0cbfc6bcdfe4c5b/f2d11/LCSConnection.png&quot;
        srcset=&quot;/static/876a513639ca4338d0cbfc6bcdfe4c5b/4edbd/LCSConnection.png 175w,
/static/876a513639ca4338d0cbfc6bcdfe4c5b/f2d11/LCSConnection.png 276w&quot;
        sizes=&quot;(max-width: 276px) 100vw, 276px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Project ID&lt;/strong&gt;:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 494px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/d2e5ddf7bfe545928623cb7317c4e2a8/d72d4/ProjectId.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 45.142857142857146%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABm0lEQVR42qWSy08TURSH7wZWPsCCCxMWCBg3Loxu1ESK+o+hodESUeMGH6h/im50584KzDCdMsy0dmzp0Hncaet8npmFFnSlN/lyHrnn3nN/56pYp4xGI5I4Jk4Svnc6+L5f2E63SxAE9OOIbq1G68N7/E8fGWlNBkI2ZjN+ZBnq867H1x2LXcPC2LOpbZvi19mzGhimjd1w8Vo+tim5LztY2wb7jofjto5xIHjNNurMhRtMlK4yu7TC9MVlZpbucHruFpPnrzMxe41JobS4wtRCmZnL9yhdulvE0wvLQplzi2XOzt/m1NxNOewKqrKxReXJFtVnb1l//o6HT9/wYP0lq9XNgvvVF1Q2XrMmVB6/+u2PsSb5nNVHm6jhICUOjwj7AUdBj1TH/M9SXRHfMAyseh3TNLEsqxjQv6KisE8UhRJEhdUy6UGqj5HqnD/zf0O1299wHIem59LYb5DHuQyDNCnI/VAurcsLPNel2fSK/a57gCc1uc2xbZve4SEqSWJ6ot1wOPylQyb/aZy8w5OdaKkbSNf6ROc/AVtyaY3IsVQMAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;ProjectId&quot;
        title=&quot;&quot;
        src=&quot;/static/d2e5ddf7bfe545928623cb7317c4e2a8/d72d4/ProjectId.png&quot;
        srcset=&quot;/static/d2e5ddf7bfe545928623cb7317c4e2a8/4edbd/ProjectId.png 175w,
/static/d2e5ddf7bfe545928623cb7317c4e2a8/13ae7/ProjectId.png 350w,
/static/d2e5ddf7bfe545928623cb7317c4e2a8/d72d4/ProjectId.png 494w&quot;
        sizes=&quot;(max-width: 494px) 100vw, 494px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;File to upload:&lt;/strong&gt;  Select a file and replace its name:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;$(System.DefaultWorkingDirectory)/_X++ (Main)/drop/AXDeployableRuntime_22.04.07.1.zip&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;with&lt;/p&gt;
&lt;p&gt;&lt;em&gt;$(System.DefaultWorkingDirectory)/X++ (Main)/drop/AXDeployableRuntime$(Build.BuildNumber).zip&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Reference name&lt;/strong&gt;: Upload&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;LCS Asset name&lt;/strong&gt;: AppRelease$(Build.BuildNumber)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;LCS Asset Description:&lt;/strong&gt; $(Release.ReleaseDescription)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Add the &lt;strong&gt;Dynamics Lifecycle Services (LCS) Asset Deployment&lt;/strong&gt; task&lt;/p&gt;
&lt;p&gt;Specify &lt;strong&gt;LCS File Asset Id&lt;/strong&gt;: $(Upload.FileAssetId)&lt;/p&gt;
&lt;p&gt;Untick &lt;strong&gt;Wait for Completion&lt;/strong&gt; to prevent timeouts.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/78c46e5df865fc649994fca7926f5662/b12f7/LCSDeploy.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 57.14285714285714%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABkklEQVR42p2SW2/UMBCF8///GbSCB56Qqi2gVVmS2Invlzg+nZmkC6JPEOmT7fXsmTPjGVKpsCEh0+qcg7EG1lrCyJn377+Ofe+odUMthfb7/WawxsD4AJfKEVCrsG2bnHn9LQM0+nNKZCBnNLpLZUOWmH4I6kXDBY/Wd/ROmXnFsba93VemNEpAsPN1XSVxocp8jPApotSCwbBDs2I7XR3OKlprZ1aiH3CZ/DuLJRLh2E6O9xM2NFidodSCWSsorTErhZWS+BgkiAU48ADicCUDIQQx8Xb/JjpcbxHfxhXPo8LlF3Gb8X02eDEB18Xhp41YqEW6AnPaYGOGpuTzPItTrtBSC8QtO/xy8Xi4THh4nvBIfHi6CZ9+aELh83XFV1J8sh0fXxJuJsLRBIhL76mH5f6I4nByAaPzGP0JZePzFCImen1GpSyMMdE0ZHK2gKcjUh/l9f8subSEshMtC3XP5z69ozL0ko5mU0olp4F6zd9dMG0J/0KuWcS4f56qKedg/7dgoZnVSmOaJ3mY/JfgK/wPVfmMFokBAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;LCS Deploy&quot;
        title=&quot;&quot;
        src=&quot;/static/78c46e5df865fc649994fca7926f5662/8c557/LCSDeploy.png&quot;
        srcset=&quot;/static/78c46e5df865fc649994fca7926f5662/4edbd/LCSDeploy.png 175w,
/static/78c46e5df865fc649994fca7926f5662/13ae7/LCSDeploy.png 350w,
/static/78c46e5df865fc649994fca7926f5662/8c557/LCSDeploy.png 700w,
/static/78c46e5df865fc649994fca7926f5662/b12f7/LCSDeploy.png 1020w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;summary&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#summary&quot; aria-label=&quot;summary permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Summary&lt;/h2&gt;
&lt;p&gt;This post provides a detailed guide for setting up Dynamics 365 Finance and Operations &lt;strong&gt;Build&lt;/strong&gt; and &lt;strong&gt;Release&lt;/strong&gt; pipelines. I intend to keep this guide up-to-date, so please report any issues you encounter.&lt;/p&gt;
&lt;p&gt;Hope you find this guide useful. Stay updated by following me on &lt;a href=&quot;https://www.linkedin.com/in/denis-trunin-3b73a213/&quot;&gt;LinkedIn&lt;/a&gt; or &lt;a href=&quot;https://twitter.com/TruninDenis&quot;&gt;twitter&lt;/a&gt; .&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Batch Job errors in D365FO: How they can ruin the performance and how to fix them]]></title><description><![CDATA[The blog post describes how D365FO batch framework handle errors and what kind of problems it may cause]]></description><link>https://denistrunin.com/performance-d365batch/</link><guid isPermaLink="false">https://denistrunin.com/performance-d365batch/</guid><pubDate>Thu, 25 May 2023 22:12:03 GMT</pubDate><content:encoded>&lt;p&gt;In the current version of Dynamics 365 for Finance and Operation, Microsoft introduced an updated batch job processing logic with several main changes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;No dedicated AOS services&lt;/li&gt;
&lt;li&gt;Batch retries concept&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;D365FO batch jobs run in the cloud, and sometimes due to this, they may fail. For example, the batch job may be moved to a different batch server, or the SQL database may be migrated to another pool. In both cases, the execution fails with a system error. To handle these cases, Microsoft has introduced the Batch Retryable feature.&lt;/p&gt;
&lt;p&gt;The concept is not complex and is explained in this presentation, &lt;a href=&quot;https://community.dynamics.com/365/dynamics-365-fasttrack/b/techtalks/posts/introduction-to-the-batchretryable-feature-august-2-2021&quot;&gt;Introduction to the BatchRetryable Feature&lt;/a&gt;. However, it may be very confusing when you see it in real life. In this post, I will demonstrate the concept with a sample class and discuss its potential impact on real-life batch processing scenarios.
)&lt;/p&gt;
&lt;h2 id=&quot;exploring-with-a-simple-test-class&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#exploring-with-a-simple-test-class&quot; aria-label=&quot;exploring with a simple test class permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Exploring with a Simple Test Class&lt;/h2&gt;
&lt;p&gt;I recently posted a question on my &lt;a href=&quot;https://www.linkedin.com/posts/denis-trunin-3b73a213_working-on-a-new-blog-post-regarding-d365fo-activity-7048833802206412800-QMlR?utm_source=share&amp;#x26;utm_medium=member_desktop&quot;&gt;LinkedIn page&lt;/a&gt; (many thanks to all who responded), and the results were intriguing:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 540px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/ae0b21054cc496f36098e3e8b1f77e6b/07484/Poll.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 84.57142857142857%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAARCAYAAADdRIy+AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB2ElEQVR42p1U2W7iQBD0/38Ryb4mTzyGlwQExgf4xPi+XdvVxAhFWuHNSO3pnqOmu6bGxvV6xel0gud5aufzGbZtq89x3/fBNXEcIwxDRFGENE3VT5JE5+fxqqpgcJIAnLhcLrp59rmQMds0TYvMIGpZlmjb9p+LxnFUW9IMLnRdF47j3Mtlz5gZMlOWk+f5ckBupgVBoIBzTB4JRGMViwD7vtfFj0Ya6rpG13UoikJ5ZDxz+djP7c4hMyR/wzCgaRrwABpjjj/6NB4y288xBeSG9XqNzWaj5ZJPmmVZOB5NlY5tW0LBbZyxaZp3akjLbrdTn8kZPJ2LgsBHpyc2kmmNRvy8GZHVA4ZxWsTfrWT51G2HvGqQFiWyokaaV8jKFnHRI8p7tMNzQGangOT2y0nwYUb4OIRw0glOBu3dTPwUyJrngHxJvAODqJ4fYm8ecfJ8yVZKlP296Lgbb/2SiiktXtANUIR82O/hCrEc/E2jvBRQCocjN7bbbrH9/EQiqSvBclmYpsWA/FHcMwz4vOQnEWcZWtGTAv5nhvP/wOgE2V2t4P15hfOywvXtDZXoMnt/Rysa+9bDU8D5ZRmtOJZ5FnGKFi0RqnDpHQ7I5V33389taaNs/gJGyCaGFKqePwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Poll execution time&quot;
        title=&quot;&quot;
        src=&quot;/static/ae0b21054cc496f36098e3e8b1f77e6b/07484/Poll.png&quot;
        srcset=&quot;/static/ae0b21054cc496f36098e3e8b1f77e6b/4edbd/Poll.png 175w,
/static/ae0b21054cc496f36098e3e8b1f77e6b/13ae7/Poll.png 350w,
/static/ae0b21054cc496f36098e3e8b1f77e6b/07484/Poll.png 540w&quot;
        sizes=&quot;(max-width: 540px) 100vw, 540px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Only 4% answered correctly: the correct time would be 500 seconds. Feel free to download the &lt;a href=&quot;https://github.com/TrudAX/XppTools/blob/master/DEVTools/DEVBatchControlUtil/AxClass/DEVBatchControlTestClass.xml&quot;&gt;sample class&lt;/a&gt; and play with it.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/35a1d1bc5c83f460c996458874730848/f0551/ExecDuration.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 40.57142857142858%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABUUlEQVR42pWRyVIDMQxE5/+/DU4UhKSA7JnV+z6epJE9cIdDV1uW/WTJTdtesdu+43jc43Q8gLEJSgooJSDJjdGYU/yzGik5+r4D55xgDCEEpBSQ54Qlz9X/BdRSQk4c3lmSQ4oBMfgVROsSZzpY4l949TnW/Bzjmv9REwiihISxBpFeFguQ3HmLTC+835e6Z72jPYc5J3hyT0WXJdczjgqEouip5StD+9njvGvBTwzjvsXwdcNps68uL1P1M8VF06FDd76hu1Bu5DCdwPD8isvTG+UGNMl4GG7AegYnLYJyMExBDAxTO9AlASs0WDdWqUlAU0diYuDjhKA91PYD3csGyVLLpSXvPQT9aKR5xJTgaAySZlv2bJltWPNKKfp1U6W0qvE801geDyga2bIsK7D8bAEkAqYCpAJa63qhwEt+hWlYa6tKvijnjDuBDK0L8Bs44GY3o0I5swAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Execution duration&quot;
        title=&quot;&quot;
        src=&quot;/static/35a1d1bc5c83f460c996458874730848/8c557/ExecDuration.png&quot;
        srcset=&quot;/static/35a1d1bc5c83f460c996458874730848/4edbd/ExecDuration.png 175w,
/static/35a1d1bc5c83f460c996458874730848/13ae7/ExecDuration.png 350w,
/static/35a1d1bc5c83f460c996458874730848/8c557/ExecDuration.png 700w,
/static/35a1d1bc5c83f460c996458874730848/f0551/ExecDuration.png 862w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Let’s discuss why this happens.&lt;/p&gt;
&lt;p&gt;When a batch job starts and encounters an error after 60 seconds, the batch framework checks the number of retries. If this is less than the max retries (5), it executes the batch job again. This cycle(with some queue waits) extends the total execution time to about 500 seconds.&lt;/p&gt;
&lt;p&gt;It then raises an interesting question: how many errors do you see in the Batch job execution history for this long-running batch job?&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 305px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/7df8c9fd78dc9d55c1c5cb86bc02ec17/a3e09/ExecLog.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 78.28571428571428%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAYAAAAWGF8bAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACSUlEQVR42pVSa0/jMBDM//9L6L7y4SQoFFWUNs07zqNxnNhxkubRuXVaqkOgg7O0Wj/HszNrsSTB3d0v2I6D1dMaj6sneC7NH5/xQHF/fw9eKZhxPp/x3bD6U48kyZAfj/CDALu9DV6WyPIcMWNgLIHuevx0WF9tGiLzX2zemZk8z/Mynyh/RdhSSmLz+or94QCHSnWpdC/w4XgeDjTfbN/ghT4OdLYl9rv9HiGLsd3t0Gj9SQoCrLF+WePhaYXHlw1Wz2vEpKu5NAwDxnHENE1LPv21NvGVppYpoe97dBRt26LtOozXy+bsPcz6Q8zn253zVYabhgZQKoWqqBdjHN9DlqVkSgKWMsRpBpbldOaReSl8P4BtO0iTFGEUIIzZrfQF8J3FNM0YqCTjvDlMswSu6yPJMnikqet6S9kXCSZ6M93efnJ5GD9ronWDkpfQrYaUEkKIxd1v28b8FuYKpexwPOYQtaDHJSpREahGnhfIOV90/lEfGmZZZpicUPACoiqpuTly0q1RDaq6pk9qKnf8GeA89Cjf3qALfmPHiyNUq5YPTBtxLj5o9W9AKrncHaCPArKsIItLKFGjKSUq2teiwdhSH3ZkyjWWNVW17NF8HucL4KA0kt8r1AG5artgQYTIC+HbAdytA/8QIPZcRH6E0AmQRAwJ3XndbBG5EfqGerfpMZAHltGlEC1UytFe2SheXxhSbrhEIxT6ukFXa8rtkk20VYOTNGDEUvUk3QRLErodV6ilQhTESEmzkEVL74VxjNNpwP+MP4S1z/NB+2wWAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Execution log&quot;
        title=&quot;&quot;
        src=&quot;/static/7df8c9fd78dc9d55c1c5cb86bc02ec17/a3e09/ExecLog.png&quot;
        srcset=&quot;/static/7df8c9fd78dc9d55c1c5cb86bc02ec17/4edbd/ExecLog.png 175w,
/static/7df8c9fd78dc9d55c1c5cb86bc02ec17/a3e09/ExecLog.png 305w&quot;
        sizes=&quot;(max-width: 305px) 100vw, 305px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;And the answer is more surprising - you don’t see any errors generated during execution and only see one final error(instead of 5) at the end.&lt;/p&gt;
&lt;h2 id=&quot;a-real-life-scenario&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#a-real-life-scenario&quot; aria-label=&quot;a real life scenario permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;A Real-life scenario&lt;/h2&gt;
&lt;p&gt;Now, let&apos;s explore how this behaviour can affect real-life batch job execution in D365FO.&lt;/p&gt;
&lt;h3 id=&quot;batch-job-stuck-in-executing-status&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#batch-job-stuck-in-executing-status&quot; aria-label=&quot;batch job stuck in executing status permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Batch job stuck in Executing status&lt;/h3&gt;
&lt;p&gt;This is a performance problem. Imagine you have a critical bath job that should be completed within 1 hour. For example, you do some order reservations at 6 am and at 8 am your warehouse starts processing these reserved orders. You did all the performance testing (and verified that it always takes 1 hour) and have 1 hour between 7 am and 8 am as a buffer time. But someday, you notice that the job is still executing at 7 am and continues to execute at 8 am, which is when the problems begin. It keeps executing at 9 am, involving management in the troubleshooting process.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 503px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/e685d2cd2de2fd726e26c0a5993f43fb/a4078/Timeline.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 30.857142857142854%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABuklEQVR42jWQ3U9SARiH+UNat64u+rhoEzdv5MZh08qLbOaise7khrbmWm62so+bnLSotcgosyQESbnQOafZTo10s9kpjojA4VDAYXZCknYCnuC4nu25+L0X737va6pWq2SzWTRNo0EjFwoFwwa1Ws2wQalUQlVVKpUK/9F1nXwuR7lcNrIpl8sjSZskUknkzHfkZIp4PMF2IkFaUVAyCnK6rpJBisUQRZGUnCYhK6Tq863tJOLXKFFJMoqZirtFVj8t8m1hiCXhHcJHod7iC+LaGiPX7xF47Ob+rRFcw6NMvfARXQkzMWjnyVA/dwf6Gb7qYMV7g19qDv1vBdPvYoF4dJmQy8nDSyeJTD9gKxJEWH5Px3ErNks3jtM2etovMHj5JlMeF07zAUZtbdzubsXd18yEs4uimt8/WfuRxDvQy7VzVtxXLnKnx8wrRyfzoRDnzZ3YWk/RZeml5aiVM+12nj9ycfbYQZoPNXGi6TB9LUewd1jY3dn/uWlP+8lq+A0f5mfZEJaIzAXYWAgixzaZ9s0QmJwhODnLy2d+5sKLrK9/xj/u5e3rcTyeMcaeegn5feh/9oyF/wDDgHi2El+dywAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Timeline&quot;
        title=&quot;&quot;
        src=&quot;/static/e685d2cd2de2fd726e26c0a5993f43fb/a4078/Timeline.png&quot;
        srcset=&quot;/static/e685d2cd2de2fd726e26c0a5993f43fb/4edbd/Timeline.png 175w,
/static/e685d2cd2de2fd726e26c0a5993f43fb/13ae7/Timeline.png 350w,
/static/e685d2cd2de2fd726e26c0a5993f43fb/a4078/Timeline.png 503w&quot;
        sizes=&quot;(max-width: 503px) 100vw, 503px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The root cause of this issue could be a simple error, such as a new unit of measure without a conversion setup. When the batch job encounters this error, the batch framework retries the job five times. The confusing part is that you don&apos;t see any errors in the log. Even if you ask Microsoft to check the top queries or server load, they won&apos;t find any unusual values.&lt;/p&gt;
&lt;p&gt;To troubleshoot this issue, check the number of retries. If the number exceeds one, cancel the current execution, run it without batch mode, and investigate the error.&lt;/p&gt;
&lt;h3 id=&quot;email-send-procedure&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#email-send-procedure&quot; aria-label=&quot;email send procedure permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Email send procedure&lt;/h3&gt;
&lt;p&gt;Another scenario involves a batch job that sends reports as emails to customers. This job runs daily to execute the report. However, due to a problem with one email, some customers might receive five copies on a certain day while others receive none.&lt;/p&gt;
&lt;p&gt;Fixing this behaviour may be complex. In one of our projects, we implemented an email send log to track what was sent and what was not, providing better visibility and control.&lt;/p&gt;
&lt;h3 id=&quot;the-opposite-case---process-waves-procedure&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#the-opposite-case---process-waves-procedure&quot; aria-label=&quot;the opposite case   process waves procedure permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;The opposite case - process waves procedure&lt;/h3&gt;
&lt;p&gt;Some developers are aware of this behaviour and try to avoid it (by using catch-all logic). For example, let’s review the process wave logic:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Some activities (e.g. running Release to warehouse from the user interface) automatically create multiple batch jobs to process waves.&lt;/li&gt;
&lt;li&gt;Each batch job runs wave processing, which includes the picking step, where the system tries to find available on-hand inventory.&lt;/li&gt;
&lt;li&gt;Since we have parallel jobs, they might select the same on-hand data, resulting in the error &quot;Not available on-hand&quot; for some jobs(which is a typical and expected situation).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The problem exists in WHSPostEngine::post(waveTable); method.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/b1e547dfbec245fe5541ee8c2dd354ac/98314/WHSPostEngine.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 63.42857142857142%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACYElEQVR42o2T22vUQBTGA+Ifr1hUtLaK2toHLb4U65VqqYL0wULfKpTWWnUvSXaTzDW3SfL5TXa3BUVwyOFMMpnffOcywaftJzjc3cDR500cf3mN9c0PePx0F2vP9nB/4z1W1newtrmH9ecf+b6D26tvcPfhS9x5sI2l5S3cXH2B5UevsHRvCzf4Hpz9nCCvW0jrkNoGRdOhaoGyqjivUXQtSueQG4OyrqCrGros6UsU/ru10ErCaIUizxGc/Ai5WKFtGkxsjtDkUJWDyQuMowhCaYJq5GXVgy3nPYh7bFH0EEtoyUMaMoLj8zFkWcOP04mhSR5QEKTw9egI49EIURxjlEwRJikkITmBiutSUhmVa63hatczgpPzEKaaAYU0lG5QU40fXdui67qZn9s/Bn/rGm9UGELMAZVrYErNHGmqVlTK/BQaKpdQvacqK3ufmhTCCmQ2Q1EXF+TgfDg1RdOf3FWUPU1TZFpiYhQSmqIJkVE9N9OngmGzCEJlyGTWGsuQrT7k/lu0lSBMxLCcRdKZsmGOKihfReZFMz9N24FPH3rLkH3ivc3nzVzYtYCD/kownmbDYg6sG4eIFYtZwYmvslSIqGaYJAjDCOF4jBGLFIZh7+Mo6oFCiOtz4NU5kBKoQ3NZn35D+u4tsoMDZPv7ELQqy+C8IlZ3odT7hULn3KXCIYF2kUM2dcQcRoNfSKgiHgwQn32HoMKMUCqBI8OxeA3N1fXfwNGFQgL5k2S40jcw8yh9Hu2sz3zfeW+Mnvn+m1yEfAkcxOnQUBmvSpezHS1zV/Fa/c/wffdnUX4DNwO7M5te3P8AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;WHSPostEngine&quot;
        title=&quot;&quot;
        src=&quot;/static/b1e547dfbec245fe5541ee8c2dd354ac/8c557/WHSPostEngine.png&quot;
        srcset=&quot;/static/b1e547dfbec245fe5541ee8c2dd354ac/4edbd/WHSPostEngine.png 175w,
/static/b1e547dfbec245fe5541ee8c2dd354ac/13ae7/WHSPostEngine.png 350w,
/static/b1e547dfbec245fe5541ee8c2dd354ac/8c557/WHSPostEngine.png 700w,
/static/b1e547dfbec245fe5541ee8c2dd354ac/98314/WHSPostEngine.png 817w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;In this method, a try/catch block catches all errors and marks the batch job as &quot;Processed&quot; even if the processing failed.&lt;/p&gt;
&lt;p&gt;In this case, a retry feature may be helpful, as the second run may find free items without affecting parallel jobs, but it is not used here.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#conclusion&quot; aria-label=&quot;conclusion permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;The current implementation of D365FO batch jobs error handling is very confusing. The main problems are the default retry count of 5 (which would be more reasonable to set to 2 or 3) and that no log is saved for failed runs. Also, it would be great if the framework provided some default behaviour instead of developers having to write boilerplate code to set up retry logic.&lt;/p&gt;
&lt;p&gt;I hope the examples presented in this blog post have helped you better understand the batch job process and its potential challenges. If you have any questions or want to share your D365FO batch job cases, please feel free to contact me.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Improve the speed for BACPAC database restore from Tier2 to Tier1]]></title><description><![CDATA[The blog post tests various options for. restoring BACPAC files on local SQL Server.]]></description><link>https://denistrunin.com/performance-restoretier2/</link><guid isPermaLink="false">https://denistrunin.com/performance-restoretier2/</guid><pubDate>Wed, 01 Feb 2023 22:12:03 GMT</pubDate><content:encoded>&lt;p&gt;Accurate data on D365FO DEV VMs can be vital for the development process, especially during the Go-Live and Support phases. One of the issues is that development VMs use &lt;strong&gt;SQL Server&lt;/strong&gt; and UAT/PROD environments use  &lt;strong&gt;SQL Azure&lt;/strong&gt; as a database. So to get a copy of the data, you need to convert &lt;strong&gt;SQL Azure&lt;/strong&gt; BACPAC file to a standard &lt;strong&gt;SQL server&lt;/strong&gt; format(you can use &lt;a href=&quot;https://learn.microsoft.com/en-us/dynamics365/fin-ops-core/dev-itpro/database/dbmovement-scenario-debugdiag&quot;&gt;debugger on Tier2&lt;/a&gt;, but it may be not convenient in some situations).&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://learn.microsoft.com/en-us/azure/azure-sql/database/database-export?view=azuresql&quot;&gt;&lt;strong&gt;SQL BACPAC&lt;/strong&gt;&lt;/a&gt; is a zip file that contains table data in text format. If you change the .backpac extension to .zip and open it in the archive tool, you will see something like that:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 593px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/0036b7d774f947701121f69a534aae66/0b5b1/ZipFileStructure.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 33.142857142857146%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAAA7EAAAOxAGVKw4bAAABSUlEQVR42nWR627CMAyF+/5vtsEYbNDSrfcbpSRNm/QCiHLmpPBn0yxZdpTonM+OpbiHKEqQJpRpRjVFovssQ57liMIISZzSmwjetwd2YlBKQUpFtUPbSozj2WTbtLA4r9H3PUTTQAiBYRwxTROm24Qbpekpec3RSonr5UpGZJYXKMsjoiA04ufzBUc6W4uXV3x8brHd7fC2WIIxDh33+92kDk3kOA6J1uYsaoaQyMtjiTiOkUSxAdJhBUGATI/2GEmP8RR8xjAMCImkadtZUNRmPVVVmVrkOdGrWXDzvobrfmHvutisN7QT9Yew6zrsnT3qWjwIOQI/QF4UxigOY3Ax31nhg1Cj+76P7h9CfS/VbCZlQ1QHnNiJKu3yUJJpPwuulivY5G7TjtZEq3/tN6Gkz3BsG42Y98RYRWQRsjyD5/kIiZY/6H8AoqYPfZyVVFUAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Backpac&quot;
        title=&quot;&quot;
        src=&quot;/static/0036b7d774f947701121f69a534aae66/0b5b1/ZipFileStructure.png&quot;
        srcset=&quot;/static/0036b7d774f947701121f69a534aae66/4edbd/ZipFileStructure.png 175w,
/static/0036b7d774f947701121f69a534aae66/13ae7/ZipFileStructure.png 350w,
/static/0036b7d774f947701121f69a534aae66/0b5b1/ZipFileStructure.png 593w&quot;
        sizes=&quot;(max-width: 593px) 100vw, 593px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;So the BACPAC restore procedure creates all tables in the database and populates the data in these tables.&lt;/p&gt;
&lt;p&gt;To load the data, Microsoft released a &lt;a href=&quot;https://learn.microsoft.com/en-us/sql/tools/sqlpackage/sqlpackage?view=sql-server-ver16&quot;&gt;SqlPackage&lt;/a&gt; tool. You can run it directly or use &lt;a href=&quot;https://github.com/d365collaborative/d365fo.tools&quot;&gt;d365fo.tools&lt;/a&gt;. Both commands are shown below:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;powershell&quot;&gt;&lt;pre class=&quot;language-powershell&quot;&gt;&lt;code class=&quot;language-powershell&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;#USE d365fo.tools&lt;/span&gt;
&lt;span class=&quot;token variable&quot;&gt;$StartTime&lt;/span&gt; = &lt;span class=&quot;token function&quot;&gt;get-date&lt;/span&gt; 
Import-D365Bacpac &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;BacpacFile &lt;span class=&quot;token string&quot;&gt;&quot;J:\LCS\PreProd2022_05_24.bacpac&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;ImportModeTier1 &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;NewDatabaseName PreProd2022_05_24_2
&lt;span class=&quot;token variable&quot;&gt;$RunTime&lt;/span&gt; = &lt;span class=&quot;token function&quot;&gt;New-TimeSpan&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Start&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$StartTime&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;End&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get-date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
&lt;span class=&quot;token function&quot;&gt;WRITE-HOST&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Execution time was &lt;span class=&quot;token function&quot;&gt;$&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$RunTime&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Hours&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; hours, &lt;span class=&quot;token function&quot;&gt;$&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$RunTime&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Minutes&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; minutes, &lt;span class=&quot;token function&quot;&gt;$&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$RunTime&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Seconds&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; seconds&quot;&lt;/span&gt; 

&lt;span class=&quot;token comment&quot;&gt;#USE DIRECT SqlPackage CALL &lt;/span&gt;
&lt;span class=&quot;token variable&quot;&gt;$StartTime&lt;/span&gt; = &lt;span class=&quot;token function&quot;&gt;get-date&lt;/span&gt; 
cd C:\temp\
&lt;span class=&quot;token variable&quot;&gt;$fileExe&lt;/span&gt; = &lt;span class=&quot;token string&quot;&gt;&quot;C:\Temp\d365fo.tools\SqlPackage\SqlPackage.exe&quot;&lt;/span&gt;
&amp;amp; &lt;span class=&quot;token variable&quot;&gt;$fileExe&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;a:import &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;sf:J:\MSSQL_BACKUP\pope_2022_05_16_small&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;bacpac &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;tsn:localhost &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;tdn:pope_2022_05_16_small_sp_ind  &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;p:RebuildIndexesOfflineForDataPhase=True &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;MaxParallelism:32 &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;p:DisableIndexesForDataPhase=FALSE
&lt;span class=&quot;token variable&quot;&gt;$RunTime&lt;/span&gt; = &lt;span class=&quot;token function&quot;&gt;New-TimeSpan&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Start&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$StartTime&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;End&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get-date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
&lt;span class=&quot;token function&quot;&gt;WRITE-HOST&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Execution time was &lt;span class=&quot;token function&quot;&gt;$&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$RunTime&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Hours&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; hours, &lt;span class=&quot;token function&quot;&gt;$&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$RunTime&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Minutes&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; minutes, &lt;span class=&quot;token function&quot;&gt;$&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$RunTime&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Seconds&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; seconds&quot;&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Sometimes this procedure may be slow, so let&apos;s discuss what parameters may be used to improve BACPAC restore time:&lt;/p&gt;
&lt;h3 id=&quot;get-a-fast-hardware&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#get-a-fast-hardware&quot; aria-label=&quot;get a fast hardware permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Get a fast hardware&lt;/h3&gt;
&lt;p&gt;Azure VMs are quite limited in terms of disk performance. A standard configuration may have SSDs or HDDs disks, but their speed will be much slower compared to local PCEe drives(e.g. Samsung 870 PRO).&lt;/p&gt;
&lt;p&gt;The process is the following: you restore the BACPAC on the local machine, after the restore, create a backup of the SQL database, move it to the Azure file share and copy-restore this SQL backup on the cloud Azure VM. Working with native SQL backup is quite a fast operation compared to BACPAC conversion, and Local PC may provide a great advantage in restoring time. The sample code for this is the following:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;powershell&quot;&gt;&lt;pre class=&quot;language-powershell&quot;&gt;&lt;code class=&quot;language-powershell&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$StartTime&lt;/span&gt; = &lt;span class=&quot;token function&quot;&gt;get-date&lt;/span&gt; 
Import-D365Bacpac &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;BacpacFile &lt;span class=&quot;token string&quot;&gt;&quot;C:\Temp\PreProd2022_05_24.bacpac&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;ImportModeTier1 &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;NewDatabaseName PreProd2022_05_24_2  &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;DatabaseServer &lt;span class=&quot;token string&quot;&gt;&quot;SDS-WS83&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;SqlUser denis &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;SqlPwd &lt;span class=&quot;token string&quot;&gt;&quot;Pass&quot;&lt;/span&gt; 
&lt;span class=&quot;token variable&quot;&gt;$RunTime&lt;/span&gt; = &lt;span class=&quot;token function&quot;&gt;New-TimeSpan&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Start&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$StartTime&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;End&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get-date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
&lt;span class=&quot;token function&quot;&gt;WRITE-HOST&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Execution time was &lt;span class=&quot;token function&quot;&gt;$&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$RunTime&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Hours&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; hours, &lt;span class=&quot;token function&quot;&gt;$&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$RunTime&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Minutes&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; minutes, &lt;span class=&quot;token function&quot;&gt;$&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$RunTime&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Seconds&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; seconds&quot;&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;use-the-delayed-durability-database-option&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#use-the-delayed-durability-database-option&quot; aria-label=&quot;use the delayed durability database option permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Use the Delayed durability database option&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Delayed durability&lt;/strong&gt; is a database option that speeds up certain database operations, but the database may stay in corrupted mode if the server crashes. D365FO database contains a huge number of objects, and the time for DB structure creation may be improved by using the Delayed durability flag.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 691px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/bb166a0c84634ad7a278750e03feae3c/e185b/DurabilityOption.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 52.57142857142857%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB6UlEQVR42mVSuW7bQBDlNwdp/AVpUqZO7TaNm1SBk8KCLUviYZIidfC+RdKSKFLHy8wGFCxmgYeZvd7OznuSblqwlw4cL4IbxCirGl3Xomk7NIcWx+PxFt2R9rvrnPP9fo/dboemaSD9Gb1iHWZIqwZZ3cL1Q/iuA5vWzJWHsiiw2WxQliWqqroBr/FeD55LfuDjcrmgH1mWYbFYXA8VeS7iarWCqmnQCKqqQn/TMbcseJ4H13XhOA7lPiRNe0MUxVT6URCmaSouGKYhcn61rmvoho6np5HYUxQFc3MOiwht2xbgfL1eQzJMEy69st1uBWGepVBkGTJdiqLoSmjSA8/PL5BpT5EV8Yvlcikig0kFoa4biJMYURyTCAekeQFZ1cShf32rRUySBHGciDynNnD1Q/C6xJW1bYu+jSzQq0rl0+thGBK4yoqqfBcxCEIhCM+HKIoNpF6MXhhu7mw6Fd9SqdLJdCYswWNPcTwe40B2Op/POJ1ONyjIERITfRBZELJQ5tyGadlgn1qLFfk0QEjicc9b8uiQkD0pbDOsMPIdfP8p48vDHF8fdHy+n+HTvYK7H0t8+xVg9DImAd+J8HIlY3JuHffxP0L21GwygUpqqoqMLE3QNns+ge7Q4Pfjo2gBnx9+mSv8CykDNhVx6zYEAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Durability option&quot;
        title=&quot;&quot;
        src=&quot;/static/bb166a0c84634ad7a278750e03feae3c/e185b/DurabilityOption.png&quot;
        srcset=&quot;/static/bb166a0c84634ad7a278750e03feae3c/4edbd/DurabilityOption.png 175w,
/static/bb166a0c84634ad7a278750e03feae3c/13ae7/DurabilityOption.png 350w,
/static/bb166a0c84634ad7a278750e03feae3c/e185b/DurabilityOption.png 691w&quot;
        sizes=&quot;(max-width: 691px) 100vw, 691px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The main problem is that it can be enabled only after the database is created, but &lt;strong&gt;SQLPackage&lt;/strong&gt; doesn&apos;t have the option to automate this. So currently, I use this approach only with manual steps. In ~3-5 min after executing &lt;strong&gt;SQLPackage&lt;/strong&gt;.exe, it creates a database, and then I manually run the following command for the newly created database.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;sql&quot;&gt;&lt;pre class=&quot;language-sql&quot;&gt;&lt;code class=&quot;language-sql&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;USE&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;master&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
GO
&lt;span class=&quot;token keyword&quot;&gt;ALTER&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;DATABASE&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;PreProd2022_05_24_2&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;SET&lt;/span&gt; RECOVERY &lt;span class=&quot;token keyword&quot;&gt;SIMPLE&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;WITH&lt;/span&gt; NO_WAIT
GO
&lt;span class=&quot;token keyword&quot;&gt;ALTER&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;DATABASE&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;PreProd2022_05_24_2&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;SET&lt;/span&gt; DELAYED_DURABILITY &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; FORCED &lt;span class=&quot;token keyword&quot;&gt;WITH&lt;/span&gt; NO_WAIT
GO&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;use-rebuildindexesofflinefordataphase-switch&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#use-rebuildindexesofflinefordataphase-switch&quot; aria-label=&quot;use rebuildindexesofflinefordataphase switch permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Use RebuildIndexesOfflineForDataPhase switch&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;RebuildIndexesOfflineForDataPhase=True&lt;/strong&gt; is one of the &lt;strong&gt;SQLPackage&lt;/strong&gt; performance flags that rebuilds indexes with offline mode after the data load procedure. On my tests, I noticed some improvements with this flag, and it is something to keep in mind for a larger database.&lt;/p&gt;
&lt;h3 id=&quot;use-disableindexesfordataphase-switch&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#use-disableindexesfordataphase-switch&quot; aria-label=&quot;use disableindexesfordataphase switch permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Use DisableIndexesForDataPhase switch&lt;/h3&gt;
&lt;p&gt;By default &lt;strong&gt;SQLPackage&lt;/strong&gt; disables table indexes before loading the data and then enables them after the load. For large tables, it should improve the data load performance, but for small tables, you get two additional steps: disable and enable indexes.  &lt;strong&gt;/p:DisableIndexesForDataPhase=FALSE&lt;/strong&gt; flag changes this behavior, it loads the data without recreating indexes. For my test files, it provided a significant performance boost.&lt;/p&gt;
&lt;h2 id=&quot;test-results&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#test-results&quot; aria-label=&quot;test results permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Test results&lt;/h2&gt;
&lt;p&gt;In tests, I used the following BACPAC files:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;A small file&lt;/strong&gt;:  94MB BACPAC size,  2.2 GB SQL Server database size&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A standard file&lt;/strong&gt;: 2.5GB BACPAC size,  24.7 GB SQL Server database size&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I compared two different environments:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A Local PC with a fast CPU and PCE SSD Intel core i9 10900 2.8GHz(up 4.8Gz)&lt;/li&gt;
&lt;li&gt;A Standard development Azure VM D8v3 E5-2673 v4  (2.3Ghz) and 15HDDs&lt;/li&gt;
&lt;/ul&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Test type&lt;/th&gt;
&lt;th&gt;Small file/Azure&lt;/th&gt;
&lt;th&gt;Standard file/Azure&lt;/th&gt;
&lt;th&gt;Small file/Local&lt;/th&gt;
&lt;th&gt;Standard file/Local&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Default SQLPackage parameters&lt;/td&gt;
&lt;td&gt;1 hour, 16:24&lt;/td&gt;
&lt;td&gt;3 hours, 51:36&lt;/td&gt;
&lt;td&gt;21:33&lt;/td&gt;
&lt;td&gt;1 hour, 23:50&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Disabled durability&lt;/td&gt;
&lt;td&gt;46:35&lt;/td&gt;
&lt;td&gt;3 hours, 18:36&lt;/td&gt;
&lt;td&gt;20:11&lt;/td&gt;
&lt;td&gt;1 hour, 20:12&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Disabled durability, /p:RebuildIndexesOfflineForDataPhase=True&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;2 hours, 52:16&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;1 hour, 07:09&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;/p:DisableIndexesForDataPhase=FALSE&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;2 hours, 23:19&lt;/td&gt;
&lt;td&gt;21:01&lt;/td&gt;
&lt;td&gt;51:15&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;For the small file, the restore times varied from one hour to 20 minutes. What is interesting here is that for fast hardware, the restore time is almost independent of various switches. Delayed durability provided a significant boost for slow disk systems(standard DEV VM). Also, for a small amount of data, it is worth considering/p:DisableIndexesForDataPhase=FALSE flag&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;update 06/03/2023&lt;/strong&gt;: you can auto clean log tables from the file using the following script&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;powershell&quot;&gt;&lt;pre class=&quot;language-powershell&quot;&gt;&lt;code class=&quot;language-powershell&quot;&gt;Clear-D365TableDataFromBacpac &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;Path &lt;span class=&quot;token string&quot;&gt;&quot;X:\MSSQL_BACKUP\AxDB.bacpac&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;TableName &lt;span class=&quot;token string&quot;&gt;&quot;SECURITYOBJECTHISTORY&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;*Staging*&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;BatchHistory&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;SYSDATABASELOG*&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;ReqCalcTaskTrace&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;ClearFromSource&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;summary&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#summary&quot; aria-label=&quot;summary permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Summary&lt;/h2&gt;
&lt;p&gt;I described different options for the BACPAC restore process. Of course, every database size is unique, but this should be a good place to start if you want to optimise the restore time for your project. For example, in my test, a &quot;standard&quot; size file may be restored in 4 hours or just in 1 hour, depending on different configurations.&lt;/p&gt;
&lt;p&gt;What is also important is to have a process that covers the needs of your project. For example, you may have a standard automated restore process that takes 4h and have an &quot;emergency&quot; process that requires some interactions(e.g. Delayed durability, manually deleting large log tables from BACPAC before the restore, etc...) that can be done in 1h.&lt;/p&gt;
&lt;p&gt;I hope you find this information useful. As always, if you see any improvements, suggestions or have some questions about this work, don&apos;t hesitate to contact me.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Understanding Dynamics 365FO different Tiers performance]]></title><description><![CDATA[The blog post describes performance differences between various environments Tiers in D365FO.]]></description><link>https://denistrunin.com/performanceD365-tierperf/</link><guid isPermaLink="false">https://denistrunin.com/performanceD365-tierperf/</guid><pubDate>Thu, 03 Nov 2022 22:12:03 GMT</pubDate><content:encoded>&lt;p&gt;ERP system performance is always an essential topic in system implementation. And with the cloud systems, it is even more complex as we have different system tiers. General planning is described in the following docs article:   &lt;a href=&quot;https://learn.microsoft.com/en-us/dynamics365/fin-ops-core/fin-ops/imp-lifecycle/environment-planning&quot;&gt;Environment Planning&lt;/a&gt;  and we have the following environments:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/2aebc7ae3d7ac4fc0f4072d0f972d8e2/229ad/StandardTiers.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 39.42857142857142%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAIAAAB2/0i6AAAACXBIWXMAACHVAAAh1QEEnLSdAAABpUlEQVR42k1QPUscQRgeLdKbtEKqFP6KQLpAUJJKzkKESEIK/QGSRjBaJEiCcMUiFhYiaEizaIiC5JqkEEHljFzMul782tuP2ZnZuZvZnZ085hLwZRje93mf9+shZVlaa6WUgvNOWyY0yQRX7TZN00wIk+dSZpTSItcAYSlNWdSiYQslpCiKTqdjy9K7vDr45YNUP21u7x1orY785vzHDf86EJl4u+Yubu4UOXqo1f2TrUbTmoK4rjs7N5vEydM31XuVycPT8yfTH3oGn38/9sbeL5GHw1PLn77s1cnj0TvPXp40L75dpWRuvb+6ec7bpFarOY6DDccXlgdevfaDaOSd01eZqJ9dzKy6vUPjzuev+97vu5XJBy+mgpj+pPJ+dePRSo2pnMRxHIYhLo/i5DJo4f7rMDr2zqwtU8YOG57SOcDdo8aPG9BaY/xWFKQMLskyTBVKKajCWKq0BiKF0HluzI1MpizxcC3UwQz8gLshsf8NSnLOjTHQDw5yWmt0RF+AjHPGGECEYMq/9q8Y6e7+qEySBA4YYAdBgEbYpZvFjvaW/QG6L50e2+xdiAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Standard tiers&quot;
        title=&quot;&quot;
        src=&quot;/static/2aebc7ae3d7ac4fc0f4072d0f972d8e2/8c557/StandardTiers.png&quot;
        srcset=&quot;/static/2aebc7ae3d7ac4fc0f4072d0f972d8e2/4edbd/StandardTiers.png 175w,
/static/2aebc7ae3d7ac4fc0f4072d0f972d8e2/13ae7/StandardTiers.png 350w,
/static/2aebc7ae3d7ac4fc0f4072d0f972d8e2/8c557/StandardTiers.png 700w,
/static/2aebc7ae3d7ac4fc0f4072d0f972d8e2/e996b/StandardTiers.png 1050w,
/static/2aebc7ae3d7ac4fc0f4072d0f972d8e2/229ad/StandardTiers.png 1356w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;But there is not much publicly available information related to D365FO hardware configuration for these Tiers. In this blog post, I describe some cases that help to understand Dynamics 365FO performance basics.&lt;/p&gt;
&lt;h2 id=&quot;different-tiers-and-their-performance&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#different-tiers-and-their-performance&quot; aria-label=&quot;different tiers and their performance permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Different tiers and their performance&lt;/h2&gt;
&lt;p&gt;D365FO, as a backend, uses different database types: &lt;strong&gt;SQL Sever&lt;/strong&gt; for Tier1 and &lt;strong&gt;SQL Server Azure&lt;/strong&gt; for Tier2+ and PROD.&lt;/p&gt;
&lt;p&gt;In the standard system, there is a &lt;strong&gt;Run performance test&lt;/strong&gt; form that allows seeing the execution speed for different SQL queries. This is a single-threaded test that measures the speed of individual queries and not the overall capacity of the system.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 692px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/1a7795449602501eabd356df8575408e/91e7e/PerfTestForm.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 81.71428571428572%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAYAAAAWGF8bAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACQUlEQVR42p1T224aMRDdbwqVAm1IvjY/0D9Iq6iqVBoFSkKgbAHBwpL13u/r5XTGe0kISh9q6cj2zJzx8YytdTod9C8+4bJ/gaurS3TPz9HrdmnfVzPv2dcnfOz18IHiO2dn70LbmB4C38VyuYQQFpK0QJZlCnmeK7R7giyKf0IriFCBg3OUZCyVs7G/RfYKlY1jG2ir5QKj4T0eH8Z4GP/CfPqE2dPkFeGFWBQvCao1q06RpUkLLY4i+J4Hz3Xh2DaCOEZAjsD3lb3xvQXbOSah+FLKFloUhnApgGE7DoLZDPuvXyDWGzhEsukQBSFoFnAoRghbzcyJKSGPw+GgoEWkMAwDCCJZuy2M62tYgwH+d6iEfhDAsiyYpokdJyZlSZIgJB8r4HWapmrNYE4Uxa2vAdu1kJ7MfrdW8vlpcE1SRpLCtkysFjoWiwUMw1AkjomiEKaxAtc/pT0f1hyo7e0Qd5M9Ffl1PSr5s5UHfeNSJ6tEh9ohZYnB4zMsQT7q9NGVn90Mdzo9jSJrC9sknKxz6NuUTiiqg2pSWR7w43cGL2Bf2R6kEm5FjNuRgE9Xl2XZdozHUA8wXflkkEfKpTzgduzBtFzKJ48VOkGOmVGoN9SMhqgbMf4YPtUzOiKxwuHch+3yO6waJ2u+JmVx0vom4b2e4HER0ldMjxVSwptRCOFG9a8p2ltp/KHrm54k3FopjD2pqBU2leKE800IhxTGpLDp/rsKy5r5bRLj59SDzJOTGn7+7mNn+aqZrLC58l9P+qrWPoYrCgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Run performance test form&quot;
        title=&quot;&quot;
        src=&quot;/static/1a7795449602501eabd356df8575408e/91e7e/PerfTestForm.png&quot;
        srcset=&quot;/static/1a7795449602501eabd356df8575408e/4edbd/PerfTestForm.png 175w,
/static/1a7795449602501eabd356df8575408e/13ae7/PerfTestForm.png 350w,
/static/1a7795449602501eabd356df8575408e/91e7e/PerfTestForm.png 692w&quot;
        sizes=&quot;(max-width: 692px) 100vw, 692px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;I used 10k rows instead of the default 1k, ran it on several clients/environments and got the following results (to present the data in a table view, copy them to Excel and run Data &gt; Text to Columns with &quot;:&quot; delimiter)&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 686px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/6ca422b848c63b313f474a2306b7eb45/f6386/TierPerfTable.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 41.714285714285715%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABhklEQVR42iWR67KiQAyEef9XO1oiA8hdQFyGq6LibU9Vbyf7gwKSTOfrHsd4HrI8R3k8om1b3O93fdZ1RXM6IWcvTVOUVQnf9xGGIf6czwj4naUZ8ixjPUBVVTgcDnDc3Q5xHCNOYh1KkhTWtio+jiPOTQNjDF6vF7IsRcHFn8+bcwma5oyh7ykU4nq9aM3ZUTDwDdz9Hh5pXddFFEXa7Dh8ImUQhPh8v6wfUPP/9/evztquU8E0TXC73Uhq4ASBrxsEV0jEVtf1uHNgGAbUdaU25YA4OZJQ4hDxhvTWWp6NMM+T9h1jPHh7Dwl/JK+iKPStdigo2RgukVwjLs3ZfzweOi/0HSnF0TSNmrWz+flBQALbWQr0alNo1seKZVkQk2THGCTD7Xargt/vB5vNRpeKqLibpgkSnxOJXR6STISmp+Cy3PB8Phn0VZeIlff7rXbr+n+GBV20rVWrctMCoYRiWa5dLqHvB21cLhd9RHxgTQSlXpZHveWVliUWoRvHQe3P86y1f7PIRhrqFJf7AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Performance results&quot;
        title=&quot;&quot;
        src=&quot;/static/6ca422b848c63b313f474a2306b7eb45/f6386/TierPerfTable.png&quot;
        srcset=&quot;/static/6ca422b848c63b313f474a2306b7eb45/4edbd/TierPerfTable.png 175w,
/static/6ca422b848c63b313f474a2306b7eb45/13ae7/TierPerfTable.png 350w,
/static/6ca422b848c63b313f474a2306b7eb45/f6386/TierPerfTable.png 686w&quot;
        sizes=&quot;(max-width: 686px) 100vw, 686px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;I also ran the test in Tier3 and Tier4, and it seems they are similar to Tier2.&lt;/p&gt;
&lt;p&gt;Let&apos;s discuss these results:&lt;/p&gt;
&lt;h3 id=&quot;single-row-operations&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#single-row-operations&quot; aria-label=&quot;single row operations permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Single-row operations&lt;/h3&gt;
&lt;p&gt;In operations that include many small calls &lt;strong&gt;SQL Azure&lt;/strong&gt; is slower(4-8 times) than a standard SQL Server. This is probably happening due to a large latency. The difference looks dramatic(as a typical X++ code often contains many small select statements), but in the latest releases, Microsoft implemented a lot of caching classes, so for business operations, it is not so critical in general.&lt;/p&gt;
&lt;p&gt;One of the real-life examples where you can see this difference is a display method with multiple SQL statements that is used in a form grid. Even with the caching, it may dramatically slow down the form behaviour. For example, 1 second overhead that is not even noticeable on the development VM may become 8 seconds on PROD and create &quot;system is very slow&quot; effects for users.&lt;/p&gt;
&lt;h3 id=&quot;multiple-rows-operations&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#multiple-rows-operations&quot; aria-label=&quot;multiple rows operations permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Multiple rows operations&lt;/h3&gt;
&lt;p&gt;There is not much difference between environments in bulk operations(like &lt;strong&gt;update_recordset&lt;/strong&gt;). They are also faster compared to individual operations (e.g. row-by-row updates). You can often see advice to use these bulk operations by default, but I recommend avoiding this. The main issue is that &lt;strong&gt;update_recordset&lt;/strong&gt; and &lt;strong&gt;delete_recordset&lt;/strong&gt; are blocking operations and may stop the whole system if used in the wrong way. And for the cloud system, it will be very hard to troubleshoot and fix that.&lt;/p&gt;
&lt;p&gt;I wrote an article regarding this &lt;a href=&quot;https://denistrunin.com/understanding-sql-blocking&quot;&gt;Blocking in D365FO and why you shouldn&apos;t always follow MS recommendations&lt;/a&gt;, and my advice is to use them only if you can measure the business operation benefit.&lt;/p&gt;
&lt;p&gt;Also, the fun fact is for the small/mid clients, your laptop probably is more performant than a PROD instance of a multi-million ERP system. Keep this in mind while discussing performance issues with Microsoft support&lt;/p&gt;
&lt;h2 id=&quot;environment-planning&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#environment-planning&quot; aria-label=&quot;environment planning permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Environment planning&lt;/h2&gt;
&lt;p&gt;Let&apos;s discuss some considerations used for environment planning.&lt;/p&gt;
&lt;h3 id=&quot;pricing&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#pricing&quot; aria-label=&quot;pricing permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Pricing&lt;/h3&gt;
&lt;p&gt;The actual price depends on your agreements with Microsoft, but some indicative values are the following:
A typical Tier1 is ~500$/month. Tier2 is 1400$/month, Tier3 is 4000$/month and Tier5 ~12000$/month.&lt;/p&gt;
&lt;p&gt;But what is important is a billing period. For Tier1, it is per hour(you can stop the environment when it is not needed), but higher tiers are billed per month.&lt;/p&gt;
&lt;p&gt;Microsoft is also preparing a new &lt;a href=&quot;https://learn.microsoft.com/en-us/power-platform-release-plan/2022wave2/power-platform-pro-development/cloud-runtime-fo-dataverse-application-development&quot;&gt;&quot;Online development&quot;&lt;/a&gt; environment that looks like a simplified Tier2, but its price is unknown now.&lt;/p&gt;
&lt;h3 id=&quot;tier1-or-tier2-for-large-data-load-processes&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#tier1-or-tier2-for-large-data-load-processes&quot; aria-label=&quot;tier1 or tier2 for large data load processes permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Tier1 or Tier2+ for large data load processes&lt;/h3&gt;
&lt;p&gt;If we check the performance, in most cases, Tier1 will be faster than Tier2. For one customer, we measured data load time for Released products/Product/Customers entities that ran in multiple threads. The time difference between Tier1(D8v3) and Tier2 was 200-250%  (e.g. load run for 1h on Tier1 and 2-2.5h on Tier2)&lt;/p&gt;
&lt;p&gt;Another point to consider is stability. Tier2+ databases are located on Azure SQL Database elastic pools, you can even execute the following command and see who your neighbours are:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;sql&quot;&gt;&lt;pre class=&quot;language-sql&quot;&gt;&lt;code class=&quot;language-sql&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; sys&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;dm_user_db_resource_governance
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It allows to scale dynamically, but when the Database is migrated to a different instance &lt;a href=&quot;https://learn.microsoft.com/en-us/dynamics365/fin-ops-core/dev-itpro/dev-ref/sql-connection-error&quot;&gt;SQL TransientSqlConnectionError&lt;/a&gt; will be generated.&lt;/p&gt;
&lt;p&gt;Another point is ongoing maintenance. A table may be reindexed by DAMS service during the data load &lt;a href=&quot;https://devblogs.microsoft.com/azure-sql/running-1m-databases-on-azure-sql-for-a-large-saas-provider-microsoft-dynamics-365-and-power-platform/&quot;&gt;Running 1M databases on Azure SQL for a large SaaS provider: Microsoft Dynamics 365 and Power Platform&lt;/a&gt;. This leads to &quot;&lt;em&gt;Could not complete cursor operation because the table schema changed after the cursor was declared&lt;/em&gt;&quot; X++ error.&lt;/p&gt;
&lt;p&gt;Some D365FO functions can’t handle such errors properly(on one project with 10.0.20, DAMS actions stopped multithreaded DIXF job after 3 hours of execution).&lt;/p&gt;
&lt;h3 id=&quot;prod-performance&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#prod-performance&quot; aria-label=&quot;prod performance permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;PROD performance&lt;/h3&gt;
&lt;p&gt;Microsoft may dynamically scale the PROD database level, depending on customer workload. The exact scale-up/down criteria are unknown, but I saw some cases where the PROD database was allocated even to a lower database tier than a standard Tier2 environment. So you need to be able to measure and compare the performance for critical operations to communicate with support properly.&lt;/p&gt;
&lt;h3 id=&quot;performance-testing&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#performance-testing&quot; aria-label=&quot;performance testing permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Performance testing&lt;/h3&gt;
&lt;p&gt;You will see this advice in every Microsoft presentation: if you need to measure performance, always use Tier2+ instances. Also, performance testing should not be considered as a one-time exercise, the test should define some measures and a way to monitor them.&lt;/p&gt;
&lt;p&gt;The overall flow for D365FO performance testing works this way:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;You calculate the planned workload.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You submit it using the &lt;strong&gt;LCS Estimator&lt;/strong&gt; tool.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Before GoLive, you need to fill out a GoLive readiness checklist. One of the questions will be whether you tested your system on exactly the same number of lines you specified in the &lt;strong&gt;LCS Estimator&lt;/strong&gt; and whether you are happy with the results(on some projects they even required an official paper). You also need to provide dates of the  testing and environment ID&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Microsoft saves the monitoring data from this Environment during the specified dates&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So after GoLive, they have this data for any arguments that the PROD is “not fast enough”. You also need this data to register a case if you have general performance issues&lt;/p&gt;
&lt;h3 id=&quot;applications-servers&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#applications-servers&quot; aria-label=&quot;applications servers permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Applications servers&lt;/h3&gt;
&lt;p&gt;Now application servers are similar to 4-core CPUs and 16GB of RAM VMs. &lt;del&gt;You can&apos;t get better AOSes, but&lt;/del&gt; Microsoft may add more servers if needed. &lt;strong&gt;Update 07/11/2022&lt;/strong&gt; - Several people &lt;a href=&quot;https://twitter.com/IevgenMir/status/1589014609029378048&quot;&gt;reported&lt;/a&gt; that for the large number of users, AOSes may contain up to 50GB of RAM, so it seems it is possible to have a different config.&lt;/p&gt;
&lt;p&gt;LCS provides a view for AOS CPU load and AOSes free memory, so it is quite easy to check if you have reached your capacity&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/a7858c2f6ba2a78bf9a49bf9f1f95053/1cfc2/HealthMetric.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 46.857142857142854%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABcElEQVR42nVS2U7DMBDs/38Jj/wHEu8ICmmb0CZpDjuOb2fYdRPEudLIe3ivsXd9d8WheMPpdERJqMojXvfPaOoznDVQk4TRGpZ0tr2zdNp8GnOzv2KnZwUxDuBzEiOknHB6b3FpesxqAjec5wlLCojBrfAI3iIl97sgd7VGk+EQVqcj3VpNTWb0QqIbBtw/ViguHfpBoOl61L3A3cMZA8W1nrEsS8ZOSINJkSNGJEIMEaSgahRaSryOM5rRoWgVisaglxb1YAgW+1rTlJSXEjbZ1R1dGnillAMxcjDhqXTUiBI7jZdKYwmafFzMo2w9Do1DJxxdDQgh5OlyQV4zeJcJ38AUpOjzJevItjOUUvDEHws35likjZgWTY/zWfAnqbdXNHlSISXObU2cXdH2Heq2wSBHcG5KC9Ya3+Tvgjw1rRFXGjg5EldxnSxTs/njzR8iY/l/wo1sLhw4ieB9yEVYHOn8mBN9LaH4N2iMwuIDolS6L16DllkAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Environment monitoring&quot;
        title=&quot;&quot;
        src=&quot;/static/a7858c2f6ba2a78bf9a49bf9f1f95053/8c557/HealthMetric.png&quot;
        srcset=&quot;/static/a7858c2f6ba2a78bf9a49bf9f1f95053/4edbd/HealthMetric.png 175w,
/static/a7858c2f6ba2a78bf9a49bf9f1f95053/13ae7/HealthMetric.png 350w,
/static/a7858c2f6ba2a78bf9a49bf9f1f95053/8c557/HealthMetric.png 700w,
/static/a7858c2f6ba2a78bf9a49bf9f1f95053/1cfc2/HealthMetric.png 900w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;One of the CPU-intensive operations on AOS is a Data management import. For every record, it scans all record fields with all extensions in all modules, which produces a significant workload on application server CPUs.&lt;/p&gt;
&lt;h2 id=&quot;summary&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#summary&quot; aria-label=&quot;summary permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Summary&lt;/h2&gt;
&lt;p&gt;I described some performance measures related to different Dynamics 365 F&amp;#x26;O environments. I hope you find this information useful for project planning. As usual, don&apos;t hesitate to contact me in case of any questions or comments.&lt;/p&gt;
&lt;p&gt;Also, I can&apos;t find a working &lt;strong&gt;Tier5&lt;/strong&gt; environment. If you have &lt;strong&gt;Tier5&lt;/strong&gt; available, it would be great if you could share the &quot;Performance form&quot; results on this environment(with 10k records and when the system is not loaded).&lt;strong&gt;Update 04/11/2022 - it seems from a DB level Tier5 has the same speed as Tier2&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[D365FO upgrade. Transfer attachments from AX2012]]></title><description><![CDATA[The blog post describes a procedure to transfer attachments from AX2012 to D365FO]]></description><link>https://denistrunin.com/upgradeD365-attachments/</link><guid isPermaLink="false">https://denistrunin.com/upgradeD365-attachments/</guid><pubDate>Wed, 21 Sep 2022 22:12:03 GMT</pubDate><content:encoded>&lt;p&gt;An attachment migration procedure is one of the tricky parts you may face during the AX2012 - D365FO project upgrade. In this post, I describe an &lt;strong&gt;Attachment export/import journal&lt;/strong&gt; solution for doing such migration.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 279px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/c2212d9563e07a0b5f835fbbd15944cf/0c3ba/CloudFunny.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 98.28571428571429%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAUABQDASIAAhEBAxEB/8QAGAABAQEBAQAAAAAAAAAAAAAAAAECAwX/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIQAxAAAAH17eZVGdBkH//EABoQAAIDAQEAAAAAAAAAAAAAAAABAhEhECL/2gAIAQEAAQUCilEV8Wl+hPUyUt//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAEDAQE/AR//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAECAQE/AR//xAAZEAACAwEAAAAAAAAAAAAAAAABEAAiMVH/2gAIAQEABj8C6SshlcRf/8QAGxABAAIDAQEAAAAAAAAAAAAAAQARITFBUWH/2gAIAQEAAT8hEcqNs6tPkVd0lgNSxRL38n17mV0BmUcInif/2gAMAwEAAgADAAAAEAPPAP/EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQMBAT8QH//EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQIBAT8QH//EABsQAQEAAwEBAQAAAAAAAAAAAAERACExQVFx/9oACAEBAAE/EBZdFVZXy+FwixE0D3IDRODhAIB2vfvMjb4lNqai5E0ex+XWJGnpLWcyGjr1Tb7jxrjP/9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Fun image&quot;
        title=&quot;&quot;
        src=&quot;/static/c2212d9563e07a0b5f835fbbd15944cf/0c3ba/CloudFunny.jpg&quot;
        srcset=&quot;/static/c2212d9563e07a0b5f835fbbd15944cf/e52aa/CloudFunny.jpg 175w,
/static/c2212d9563e07a0b5f835fbbd15944cf/0c3ba/CloudFunny.jpg 279w&quot;
        sizes=&quot;(max-width: 279px) 100vw, 279px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;d365fo-attachments-types&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#d365fo-attachments-types&quot; aria-label=&quot;d365fo attachments types permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;D365FO Attachments types&lt;/h2&gt;
&lt;p&gt;As D365FO is a cloud-based system, attachment storage types may be different from what users get used to previously. So, let&apos;s discuss D365FO attachments types and the pros/cons of each of them:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Database&lt;/strong&gt;: attachments are stored in the database in a blob field. This is perfect for text attachments, like notes. You can edit the attachment content, but only from the D365FO user interface. It increases the D365FO database size.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Azure storage&lt;/strong&gt;: attachments are stored inside an internal Azure storage, managed by Microsoft. Users can&apos;t edit attachments directly(only download and upload files) as this storage account is accessible only from the D365FO user interface. This approach does not consume Database space, Microsoft charges for the storage separately.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SharePoint&lt;/strong&gt;: attachments are stored on the SharePoint site, managed by clients. Users can edit attachments, and documents are available outside of the D365FO interface(for example, you may use a group in Teams and link a SharePoint folder to it). But in this case, the customer needs to maintain the SharePoint site.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;transfer-attachment-module-description&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#transfer-attachment-module-description&quot; aria-label=&quot;transfer attachment module description permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Transfer attachment module description&lt;/h2&gt;
&lt;p&gt;There are already several ways of transferring attachments while doing a migration project from AX2012 to D365FO, but in this post, I will describe the additional method, and probably it can be called &quot;yet another way to transfer attachments from AX2012&quot;.&lt;/p&gt;
&lt;p&gt;Some of the out-of-the-box ways for attachment migration are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/microsoft/Dynamics-365-FastTrack-Implementation-Assets/blob/master/AX2012DataUpgrade/MoveDocumentsToDatabase&quot;&gt;MoveDocumentsToDatabase&lt;/a&gt; job from the FastTrack team. It moves all attachments to the AX2012 database that can be used in the upgrade process.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Standard entities for attachments creation(e.g. CustomerAttachmentsV2Entity). In the case of entity usage, you need to create a ZIP data package that contains all files and entity data.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The reason for the module development is to provide more flexibility and control over AX2012 attachment transfer. Let&apos;s check how it works.&lt;/p&gt;
&lt;p&gt;The module consists of AX2012 and D365FO parts.&lt;/p&gt;
&lt;h2 id=&quot;ax2012-functionality&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#ax2012-functionality&quot; aria-label=&quot;ax2012 functionality permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;AX2012 functionality&lt;/h2&gt;
&lt;p&gt;It is an XPO project that needs to be imported into an AX2012 live application. After the import, you need to run the &lt;strong&gt;DEVDocuExport&lt;/strong&gt; menu item.&lt;/p&gt;
&lt;p&gt;It will display the following window:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/120f1d25a5e6e6b64054228f57783307/3c051/ExportAx2012.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 63.42857142857142%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACV0lEQVR42oWR+VPTQBzF89/7CyMg4xQcRISKyoyUCjrlLLa2XB4MTMsojWmbnkmaHptkk83x3KxFOYZxZz6T7+7s9+V930rzq1nMruSQeJXD0+V9Xhcw9+YQM8kCniwXBdPJIiYWDvAosYPHz7OYW8pgajaF6bn1e0iZvSMspk4wyZuerX3Fi81LzKdL+JiTkT38hb0ipyDzr4x9Xh8cK1hY2cVkIhZM34ELGp068l9KSB/L+HDKG0ptZC+aaOkmgAhRFODmCqMIS293MDGziunZNUwl3nH4N65jwe3CN6xlikhtfUZqu4C94zLyZzI+nSnInauC/EWDo45p4PXWdyxunODl5qlgaSOeMo9k8j2kktKF3LZw1RhCbgxQbRMofF/tWOgR7y+mxTBwAl4zEDeE5UX/4HvqhzDNIaSO1oNhGCCOh5EHDGiIvh3CZdGtUX2fwbEthGGIu8vz+A8NDSaxIXU1A31DR7nlYP2cYLfiI/PTh9pnYIxhZLtw6RCEjNBsNmFZFlzXg+NQ2LYjarPfx9FhEXK1DmkwJKLRpZRfJohiBzz4GN/3eYMrXNi2DV3XBZqmCyHPYwLG7wV8AkIZJGJT0RCNJ4xucHNRSoVoEARweB07pNQVXMdAWXhHMLoXDz//czgajVCr1dDVunB5ZrHDawIhGMFhASTLcW85fGjF48duIhFFAMqjiB8jPg/HzcJhzxzw17NF2IS7eBBCbt1xeN7dXh/lahNKS0NNkaGoLUiXch2VqoqragP1tg61Y6AxRv0PsdAPLlhRO6godZSVJn4D7q+z103cL5EAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Export dialog&quot;
        title=&quot;&quot;
        src=&quot;/static/120f1d25a5e6e6b64054228f57783307/8c557/ExportAx2012.png&quot;
        srcset=&quot;/static/120f1d25a5e6e6b64054228f57783307/4edbd/ExportAx2012.png 175w,
/static/120f1d25a5e6e6b64054228f57783307/13ae7/ExportAx2012.png 350w,
/static/120f1d25a5e6e6b64054228f57783307/8c557/ExportAx2012.png 700w,
/static/120f1d25a5e6e6b64054228f57783307/3c051/ExportAx2012.png 760w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;This dialog allows you to specify a table and set up some filters for it(e.g. export attachments only for not blocked customers).&lt;/p&gt;
&lt;p&gt;As a result of this run, the system exports all attachments for the selected table to the directory and creates a &lt;strong&gt;Descriptor file&lt;/strong&gt; that links the primary table key to an attachment file.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/0852f3d847ae4776556da8f4dc757764/b59fb/ExportAx2012Result.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 34.285714285714285%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAAA7EAAAOxAGVKw4bAAABfklEQVR42i2RiXLbMAxE/f8/1A9oOp2mSZx63MSWLOskdVCyTB2W6+sVpsMZDCAuuMIuZlmWkiQJZVmhdU5RFARBQJ7nhGFEVVXu7oFr6qbBGINSyvVU5QOv69rhsyQOsXbP8Xjger0wDj1xtKXvLFmaADfu53T6Jw+1q6dpxO5bwVPOl4v0R/i+70hn878eXpQT5w1ZZdlmFa9LDz8pmH9sUMa6uOMLL5S6I9S1vNG8/Plg1wquUjzPo5HpZ99+hzwtE74vYn4sM54WicvPq5z3bcM8qHnbGJfv8WtV8LwueAsMP5cpq0DJpDHr9RdhEGUo8WHfj3TDUfKBthvJylamGcibkaY/o+qBtOzcd7E7SD5Q7id0bYnEIt/fPCRnYqQR42+3q/NQCo7TROJveV98kmrD4QSF2ROrEl02EjtM22P7QX4+EIXhl+Qds1DlwtwI2ZXz+cxFSCchNPemz5U01W4R1lrZbsVOZN2lDbK8YZBp65Zg44vkNVpp/gM+Fwf/uAqFJwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Export Ax2012 Result&quot;
        title=&quot;&quot;
        src=&quot;/static/0852f3d847ae4776556da8f4dc757764/8c557/ExportAx2012Result.png&quot;
        srcset=&quot;/static/0852f3d847ae4776556da8f4dc757764/4edbd/ExportAx2012Result.png 175w,
/static/0852f3d847ae4776556da8f4dc757764/13ae7/ExportAx2012Result.png 350w,
/static/0852f3d847ae4776556da8f4dc757764/8c557/ExportAx2012Result.png 700w,
/static/0852f3d847ae4776556da8f4dc757764/e996b/ExportAx2012Result.png 1050w,
/static/0852f3d847ae4776556da8f4dc757764/b59fb/ExportAx2012Result.png 1285w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;Descriptor file&lt;/strong&gt; gives you great flexibility, e.g. you can rename table keys or change document types mapping.&lt;/p&gt;
&lt;p&gt;The next step is to copy the created directory with AX2012 attachments to Azure storage. It can be done by using the following power shell command.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;powershell&quot;&gt;&lt;pre class=&quot;language-powershell&quot;&gt;&lt;code class=&quot;language-powershell&quot;&gt;cmd&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exe &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;C &lt;span class=&quot;token string&quot;&gt;&quot;cmdkey /add:`&quot;aaavmstorage.file.core.windows.net`&quot; /user:`&quot;localhost\aaavmstorage`&quot; /pass:`&quot;BQubgv1NlZE+LtbbL8jKLrkVSwBlLHGuygbu9fy6gDv+UiRTiw63cpmVlAEVhSLCup1XRbbVajt6ww==`&quot;&quot;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;#Mount the drive&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;New-PSDrive&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;Name Z &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;PSProvider FileSystem &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;Root \\aaavmstorage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;file&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;core&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;windows&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;net\aaavmfileshare

&lt;span class=&quot;token function&quot;&gt;Copy-Item&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;C:\Attachments&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;Destination &lt;span class=&quot;token string&quot;&gt;&quot;Z:\Attachments&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;Recurse&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;d365fo-part&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#d365fo-part&quot; aria-label=&quot;d365fo part permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;D365FO part&lt;/h2&gt;
&lt;p&gt;At that stage, we have our attachments in the cloud, and it is time to import them into D365FO.&lt;/p&gt;
&lt;p&gt;After installing the required X++ objects, open the following link&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;html&quot;&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;https://mycompany.operations.dynamics.com/?cmp=CMP&amp;amp;mi=DEVDocuExpImpJournalTable&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It will open the Import attachment form.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/c7fc8e85045200e407e8c81b5eee7c5e/91b29/EmptyJournalForm.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 68.57142857142857%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABSUlEQVR42q2TjW6DMAyEef8nXLVqUjeg0wqEkBDyY3Kzs3btpEkt2iydmqTk02Ef1WQXhBix+Ag7L9C8f+8MzDQhxoScsakq5xyICN4vMNYi0YrZeUwMpHXF1qoyW1j5oriMKZV1PtvKW+0JMDGEBMQuRbKODL+c0UYxcMWxqbHbPWG/f8br4QA9jvDLghj8ZlXrSgxQUENf+jbPFoH/CP4PQKV0kROYd0WRgSkGEOv2Ap3PEq8vonTdF+AwzuiVRdcNJTohyNQTjJmhRs2g8N1PNRoobeBDKpJE9GxGYieqkAm7N4eXZkFbj2gbg2PLaiY09YSPYcbA7bDWwPGF5hTQdBHHgYraPqHms699QkWUIJO+Vr4RysQt51N+JUb3ovQL8Gd577kVXYH+C1CcTVoX8CNBfwioGRh4MI98PXeBApJXvjxzD/gJjR1LDTjtmR0AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Empty Journal Form&quot;
        title=&quot;&quot;
        src=&quot;/static/c7fc8e85045200e407e8c81b5eee7c5e/8c557/EmptyJournalForm.png&quot;
        srcset=&quot;/static/c7fc8e85045200e407e8c81b5eee7c5e/4edbd/EmptyJournalForm.png 175w,
/static/c7fc8e85045200e407e8c81b5eee7c5e/13ae7/EmptyJournalForm.png 350w,
/static/c7fc8e85045200e407e8c81b5eee7c5e/8c557/EmptyJournalForm.png 700w,
/static/c7fc8e85045200e407e8c81b5eee7c5e/91b29/EmptyJournalForm.png 983w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The first step is to go to the &lt;strong&gt;Journal name&lt;/strong&gt; field(View detail) and create a new &lt;strong&gt;Journal type&lt;/strong&gt;. A &lt;strong&gt;Journal type&lt;/strong&gt; defines a reference to Azure file share (a connection string and a share reference).&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/21d5f257ddadcddc65496086760e29ba/d4c13/JournalNameSetup.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 45.142857142857146%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABOklEQVR42p2RbW+DIBSF/f8/a9+3ZMm+LKnNrNhaba28IyBnV1K7ZlmXZcCTw0VyufdYSGVhrIPSFqOw4ELhMo6QSsOHGWkm1pkSsKyUbgBf+5nuFlwYaDPBuoAQEwFKlAjATRHdsUVVVVn5eMFIXC4DRmKN1zNrNIrn1w2eXmq8lSPKY8Tm4FES7wcHaQIOe4bttsSu+kCzb8DqXabeUcwYGNE0DDWdKSlQKBvRnCxO3OMswo2eYjcFDOcORmtqPcJ7jxA8IjFTHCNpDKQha/AORUpz9uGnEWOE1gqc86zeT5gml3X5Nl+JV5Z9sRiZTb2mvWe5JIQEaxoIKW8P3f+U7/xa4fKYEBw1q9F1PYwxsNZS2wGPxh9a1uj7HsMwkOkKkip1zv4v4WK8VhJt26I79bm6teVHCT8BxkK8yv6fq7gAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Journal Name Setup&quot;
        title=&quot;&quot;
        src=&quot;/static/21d5f257ddadcddc65496086760e29ba/8c557/JournalNameSetup.png&quot;
        srcset=&quot;/static/21d5f257ddadcddc65496086760e29ba/4edbd/JournalNameSetup.png 175w,
/static/21d5f257ddadcddc65496086760e29ba/13ae7/JournalNameSetup.png 350w,
/static/21d5f257ddadcddc65496086760e29ba/8c557/JournalNameSetup.png 700w,
/static/21d5f257ddadcddc65496086760e29ba/d4c13/JournalNameSetup.png 825w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Then you need to specify the Azure location(folder with files) for our import and press the &lt;strong&gt;Test connection&lt;/strong&gt; button to validate the settings.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/f18e453e8d8e40b003b597956faf5156/b6529/JournalSetup.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 43.99999999999999%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABH0lEQVR42p2Si27DIAxF8/9fuKnd0iZdyJuERzAEcudEVStNmrQV6SCbK4yxnVWiQ9ONaDsJ0fT4LFrkRY1KNBgnDclM89/JrLVY1xXGWMyzgg8rNNtaa2zbhv+uLKWElCLILfDksLHN250XAtaTQ6MCpAdGAga3oV82dDa9RNZwwLxqcSoqnEqBnGta9QqDppfI9u+Ow4DiWkBUApOcEIgQAyHdicH98H/XsxhXTGqBMgTygVnhGO/pQQieCU/f++PsqYeHzgEjZmXQDxJKcZc5O2MMFue44+HALg7GLnxpPdi13d81In9MxT4lxA9liTOseofzzeCr9xAyci31Ydds73zcZrxfelyERlFbXIXhmo+HdusIb3mHcylRtg7fLzq39WWW090AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Journal Setup&quot;
        title=&quot;&quot;
        src=&quot;/static/f18e453e8d8e40b003b597956faf5156/8c557/JournalSetup.png&quot;
        srcset=&quot;/static/f18e453e8d8e40b003b597956faf5156/4edbd/JournalSetup.png 175w,
/static/f18e453e8d8e40b003b597956faf5156/13ae7/JournalSetup.png 350w,
/static/f18e453e8d8e40b003b597956faf5156/8c557/JournalSetup.png 700w,
/static/f18e453e8d8e40b003b597956faf5156/b6529/JournalSetup.png 1049w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;After Journal creation, the next step is to import lines from the Excel &lt;strong&gt;Descriptor file&lt;/strong&gt; generated previously during the AX2012 export(&lt;strong&gt;Import lines from Excel&lt;/strong&gt; button).&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 583px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/5c70a7b8fc7819c037e0f4a99ca21a27/9fc4b/ImportLinesFunction.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 43.99999999999999%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABJ0lEQVR42p1S206DUBDs//+IfofxxcRgfDA1pRSrUm4tnBuXcoDx7Faatolp6iaTmYUwO+csM2stqqpC09TQWrOu69r1DWuCMebs2dQTtFLoug5Tzdq2RRxvUBQ7xzGSJGFkWYZNFDFHv5ymKfL8wNQT6BsacjQcxxFkStNPJ/23ZsMwuKk5p9ptt6CehlziJkPl7uFaCVUhSkooKSGEYJaOSZ/dIRlSMsEvS5RlCVoUper7EZ09pHsO9rh/1Ghq4573f6Znw++vNZaLd6zDJcLAZ51nCVafMeb+BwpRcQqpNIxWfCLatHF/hXRJzxL2w4i3UMJblHhZiAP7Aq+BgucrPM0llOngrVrcPUhnIniJ1vZ8EjKjUEfDSYwnwIWm2ltAN9eX8wNGArl1XzUWFwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Import Lines Function&quot;
        title=&quot;&quot;
        src=&quot;/static/5c70a7b8fc7819c037e0f4a99ca21a27/9fc4b/ImportLinesFunction.png&quot;
        srcset=&quot;/static/5c70a7b8fc7819c037e0f4a99ca21a27/4edbd/ImportLinesFunction.png 175w,
/static/5c70a7b8fc7819c037e0f4a99ca21a27/13ae7/ImportLinesFunction.png 350w,
/static/5c70a7b8fc7819c037e0f4a99ca21a27/9fc4b/ImportLinesFunction.png 583w&quot;
        sizes=&quot;(max-width: 583px) 100vw, 583px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;It will create journal lines(one line per file).&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/dac93f5d6fc3d6fd709c9ac4cbe9534a/68947/LineView.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 45.142857142857146%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABLUlEQVR42pVSSW7DMAzU/3/YQ200ceogTWJZu6hlSsnNcsihITAgMRwPZVFCaQNrPbSxkNrDuoCUM96JUipWWxCpQhhjEEIAUUQu7xm9CpFzQU7EUzJSSt04ESHGLRc+7X+Q/7IgNpmmHcZxwDzP0FrBGIVVLnDWgGJADL7njhAe9RO6hiGas1yu0Eoy6bjpkSmgZuKTx143pBd45pu2ZZESGyoPuVosDOcTLyjgdJFYeUnLanCVZuNthOqLo472XcuG+fNV9Z4gyhiOAcPsOw6Xit0p9Xq6FAzfDh+7FSNrvpjf/2RM59IxHgl7zo37nAMOP2H75VJKXwLxErZnUO51443R/W4D39Fz5JzueqM1nHMPw7bhhpvgVjfjJvTe3Yc8DLdnVmvlvu/DfwF2c77kZdkexAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Line View&quot;
        title=&quot;&quot;
        src=&quot;/static/dac93f5d6fc3d6fd709c9ac4cbe9534a/8c557/LineView.png&quot;
        srcset=&quot;/static/dac93f5d6fc3d6fd709c9ac4cbe9534a/4edbd/LineView.png 175w,
/static/dac93f5d6fc3d6fd709c9ac4cbe9534a/13ae7/LineView.png 350w,
/static/dac93f5d6fc3d6fd709c9ac4cbe9534a/8c557/LineView.png 700w,
/static/dac93f5d6fc3d6fd709c9ac4cbe9534a/e996b/LineView.png 1050w,
/static/dac93f5d6fc3d6fd709c9ac4cbe9534a/68947/LineView.png 1281w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The final step is to load attachments to D365FO, you can do this only for one line(to test the process) or for the whole journal. It will use the standard &quot;Attach document&quot; procedure, which creates attachments according to the document type settings.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/306b9bafeee79fccfffbaa7726ad7e5c/71b12/JournalStatus.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 43.42857142857143%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABH0lEQVR42q2R6U7EMAyE+/6vCIIV0Gt7JM3R5h7s7GpVof0DItKnTB3HsaeNsTu0sRDKQpkDIQT8ZW02wRwZzX4c8N4jxoj/WE2iQjkl8B6oMHfIe6Sd478hEU3ffeFyeUPfd9BawRgFtUkY0sG7G8491ye840kPNEIIbFRgt6YG+TAGTx0HxHty9M+LnOE7TMM/hUd0VEwpVb1ktNbUralnlh5jSxhHnvN5Jny95+q4+04/laaqHvJKiRPcw1zWnFhKQc75ZHt5KI5zzk1TbmYPVw9hMuYtYBKuauZK32svsBCTDJD3+JlVJywqQtqCcdkpj0Z+HxxGWdDNDh+DwZX0VSR8zh7ja4f+pUVLepL0yA+GNaJfqJGt1LvtdOAbHwK+nPJj68oAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Journal Status&quot;
        title=&quot;&quot;
        src=&quot;/static/306b9bafeee79fccfffbaa7726ad7e5c/8c557/JournalStatus.png&quot;
        srcset=&quot;/static/306b9bafeee79fccfffbaa7726ad7e5c/4edbd/JournalStatus.png 175w,
/static/306b9bafeee79fccfffbaa7726ad7e5c/13ae7/JournalStatus.png 350w,
/static/306b9bafeee79fccfffbaa7726ad7e5c/8c557/JournalStatus.png 700w,
/static/306b9bafeee79fccfffbaa7726ad7e5c/e996b/JournalStatus.png 1050w,
/static/306b9bafeee79fccfffbaa7726ad7e5c/71b12/JournalStatus.png 1308w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;And as a result, you get a destination table record with attachments(e.g. attachments for the customer)&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/80e3bd8bae22484e8a3d74162c79e52f/98b29/CustAttachments.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 68%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB30lEQVR42o1TyW7cMAz1/39YTr00hwL1JEUaO17kXZZsydsryRmlnmkOJfBgieLyuDjy84x5sli8gx16uHmCo/tkLYZhgDFGvlpreHqbrcE4GqzOYdQDvHw1pmnCQN9IlQpNp2EsBZwX2MnT2ZPBjOT3G+L4J5IkgSoL5HmONH1HXSlUhDRN5MxvRZEjo3v09D3Htx8lLh8OL5kXxKlDWmooVUKRwziO0AxiUKqKvqMw7/sOl0uMpq5gRk33FtFLavEcK7wrR/CCt8IhUwOGrpMgi/dwVJrntlAl3nnReTfj1+srtWzCvq2CiA07cjzLcRzkaEXfdb3c930X8Jl9lmWR+9ln3w9E/MCO27Z9OvHZmBFD32OmoT0Ks+aELNegx+db5Il627aS4ZyN+7atK76SgaZbN40wXSn5WaKVGfb/MtTktD8YB2F2qqrQUFA+c6mBEPVwlpIfGRpiONE+csmcIIDfGBsN4Ezib0By4JLDQ2DImblsRtD/j0gPea8ehcsdSc/s2SYwZP1xSryfQbqIS6qq+o7+1XiVxf3IMrS3lgTIMG4DO+uNsczQkWP/RcCNArXCkJ3Pjee14T/lqr/fz4gbX9f1XSZpOhkvt1JDgsCK+1oUhQyM95gRhvIHypJBhuxR/FkAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Cust Attachments&quot;
        title=&quot;&quot;
        src=&quot;/static/80e3bd8bae22484e8a3d74162c79e52f/8c557/CustAttachments.png&quot;
        srcset=&quot;/static/80e3bd8bae22484e8a3d74162c79e52f/4edbd/CustAttachments.png 175w,
/static/80e3bd8bae22484e8a3d74162c79e52f/13ae7/CustAttachments.png 350w,
/static/80e3bd8bae22484e8a3d74162c79e52f/8c557/CustAttachments.png 700w,
/static/80e3bd8bae22484e8a3d74162c79e52f/98b29/CustAttachments.png 937w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;summary&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#summary&quot; aria-label=&quot;summary permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Summary&lt;/h2&gt;
&lt;p&gt;The described solution provides excellent flexibility for moving attachments from AX2012 to D365FO. You can find all code used in this post in the following folder(AX2012 project saved as a resource): &lt;a href=&quot;https://github.com/TrudAX/XppTools/tree/master/DEVTutorial/DEVDocuExpImp&quot;&gt;https://github.com/TrudAX/XppTools/tree/master/DEVTutorial/DEVDocuExpImp&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I hope you find this information useful. As always, if you see any improvements, suggestions or have some questions about this work, don&apos;t hesitate to contact me.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[XppInteg - Import purchase orders from XML files into D365FO]]></title><description><![CDATA[The blog post describes a sample approach how to implement XML based integration by importing purchase orders from Azure File Share in D365FO using X++]]></description><link>https://denistrunin.com/xpptools-integfilesharexmlpurch/</link><guid isPermaLink="false">https://denistrunin.com/xpptools-integfilesharexmlpurch/</guid><pubDate>Wed, 04 May 2022 22:12:04 GMT</pubDate><content:encoded>&lt;p&gt;This post extends my several previous &lt;a href=&quot;https://denistrunin.com/tags/integration/&quot;&gt;posts&lt;/a&gt; but with another messages format. We use an XML format and try to import files in X++ from Azure File Share and create purchase orders.&lt;/p&gt;
&lt;p&gt;I use a very simplified example of integration with the INFOR system. This system has an integration component that can export the data in XML format, and we will process(import) these files in D365FO.&lt;/p&gt;
&lt;h3 id=&quot;reading-xml-data&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#reading-xml-data&quot; aria-label=&quot;reading xml data permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Reading XML data&lt;/h3&gt;
&lt;p&gt;What is good that a file generated from INFOR is probably the most complex format that you may see in XML integrations. It has a custom namespace, data in tags, data in attributes, data in the similar elements. Here is a sample file context:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;xml&quot;&gt;&lt;pre class=&quot;language-xml&quot;&gt;&lt;code class=&quot;language-xml&quot;&gt;&lt;span class=&quot;token prolog&quot;&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;SyncPurchaseOrder&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;xmlns&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;http://schema.infor.com/InforOAGIS/2&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;languageCode&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;en-US&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;DataArea&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;PurchaseOrder&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;PurchaseOrderHeader&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;DocumentID&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;PO00001&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;DocumentID&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;DocumentDateTime&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;2022-04-16&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;DocumentDateTime&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;SupplierParty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;PartyIDs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;ID&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;accountingEntity&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;USMF&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;1001&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;ID&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;PartyIDs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;SupplierParty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;ShipToParty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;Location&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Warehouse&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;ID&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;accountingEntity&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;USMF&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;11&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;ID&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;Location&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;ShipToParty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;UserArea&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;Property&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;NameValue&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;eam.UDFCHAR01&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;StringType&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Requestor Name&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;NameValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;Property&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;UserArea&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;PurchaseOrderHeader&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;PurchaseOrderLine&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;LineNumber&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;10&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;LineNumber&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;Quantity&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;unitCode&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;EA&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;15&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;Quantity&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;UnitPrice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;Amount&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;currencyID&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;AUD&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;10&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;Amount&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;UnitPrice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;UserArea&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;Property&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;NameValue&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;eam.UDFCHAR01&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;StringType&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;M0001&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;NameValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;Property&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;UserArea&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;PurchaseOrderLine&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;PurchaseOrderLine&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;LineNumber&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;20&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;LineNumber&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;Quantity&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;unitCode&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;EA&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;2&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;Quantity&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;UnitPrice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;Amount&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;currencyID&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;AUD&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;10&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;Amount&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;UnitPrice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;UserArea&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;Property&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;NameValue&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;eam.UDFCHAR01&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;StringType&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;M0004&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;NameValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;Property&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;UserArea&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;PurchaseOrderLine&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;PurchaseOrder&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;DataArea&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;SyncPurchaseOrder&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We will read this file into the two staging tables(header and lines) and then create a purchase order based on these tables.&lt;/p&gt;
&lt;p&gt;In order to deal with such a complex format I created a helper class &lt;a href=&quot;https://github.com/TrudAX/XppTools/blob/master/DEVTutorial/DEVExternalIntegration/AxClass/DEVIntegXMLReadHelper.xml&quot;&gt;&lt;strong&gt;DEVIntegXMLReadHelper&lt;/strong&gt;&lt;/a&gt;. It uses the standard &lt;strong&gt;System.Xml&lt;/strong&gt;* methods and provides several helper methods that simplify the code structure:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;//set up namespace alias(used in search)&lt;/span&gt;
readHelper&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;initNamespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;xmlDoc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &apos;infor&apos;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; @&apos;http&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;schema&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;infor&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;com&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;InforOAGIS&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&apos;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;//read a typed data from the specified tag&lt;/span&gt;
header&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;PurchId  &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; readHelper&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;xmlGetValueNodeStr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nodePOHeader&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &apos;DocumentID&apos;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
line&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;PurchPrice &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; readHelper&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;xmlGetValueNodeReal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nodePOLine&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &apos;UnitPrice&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;Amount&apos;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;//search node inside the specified node by path&lt;/span&gt;
node &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; readHelper&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;xmlGetNodeByPath&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nodePOHeader&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &apos;SupplierParty&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;PartyIDs&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;ID&apos;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
header&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;OrderAccount &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; node&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get_InnerText&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;//search node inside the specified node by search string&lt;/span&gt;
node &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; readHelper&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;xmlSelectSingleNode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nodePOHeader&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &apos;infor&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;UserArea&lt;span class=&quot;token comment&quot;&gt;//infor:Property//infor:NameValue[@name=\&apos;eam.UDFCHAR01\&apos;]&apos;);&lt;/span&gt;
header&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;RequestorName &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; node&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get_InnerText&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;//getting the data from the attribute&lt;/span&gt;
xmlAttributeCollection &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; node&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get_Attributes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
xmlAttribute &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; xmlAttributeCollection&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get_ItemOf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;accountingEntity&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
header&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;CompanyId    &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; xmlAttribute&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get_InnerText&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The full class is here &lt;a href=&quot;https://github.com/TrudAX/XppTools/blob/master/DEVTutorial/DEVExternalIntegrationSamples/AxClass/DEVIntegTutorialProcessPurchConfirmXML.xml&quot;&gt;DEVIntegTutorialProcessPurchConfirmXML&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;solution-description&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#solution-description&quot; aria-label=&quot;solution description permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Solution description&lt;/h2&gt;
&lt;p&gt;In this blog post, I describe a solution(with &quot;Consuming external web services&quot; &lt;a href=&quot;https://devblog.sertanyaman.com/2020/08/21/how-to-integrate-with-d365-for-finance-and-operations/#Consuming_external_web_services&quot;&gt;type&lt;/a&gt;) for a D365FO Custom Service that will talk to the Integration Platform. It will do the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Process purchase orders for different companies.&lt;/li&gt;
&lt;li&gt;Avoid issues like OData or DMF like throttling, monitoring failed batch imports and rollback of partial failures.&lt;/li&gt;
&lt;li&gt;Read a custom data format in XML format from Azure File share as messages (sourced from an external program).&lt;/li&gt;
&lt;li&gt;Provide a solution to log and monitor the failures easily.&lt;/li&gt;
&lt;li&gt;Perform custom transformations within D365FO as part of the import.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Our integration should read messages from the Azure file share and create purchase orders in D365FO.&lt;/p&gt;
&lt;p&gt;The diagram that describes the process is below:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 667px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/a08c4a0fe7d1dc7556ef9f1a4ffd6bea/295bd/SolutionDiagram.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 92.57142857142858%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAACXBIWXMAAA7EAAAOxAGVKw4bAAACVklEQVR42qVUy27TUBD1R7HkE/go9kiIDRs+gB0SqIt2i4QQRYKKhlRNXUiauPG9tuv3+3WYueG6TpqGBSONZu7r3HPPjG20bYuu65TrXMe+75HlBSx5hyBMsBQekqxQ8+N949w4BMiRzuJ6vsSb98f4cSPR09zuvv2A7UPAhiLQ47O5wpNXR/hwYdG4Q30IkOlr18/Uka0oCgSBD99z4EhJEuToB4D2wRnDcRwIIcAxiiIFUJI7YYyV7aIuC6RFjd92TGslqqra7CnLwXmc00VZlsFwXRfsDJqmmWJFFCDjEp+mJtLYw+mvHM9e3+GLmaIpEkjpwnM9uETC9/3hNQxqNE2DXetYgrrByWRJwClEBDw/ivB1Xqv1tqX17l4qbczUqOvNpvGCGjNwt5kznQ4vTgKSoULXVMSkUIfZsyynC7p7QM1wXBwN3rSb+NFs8PRlhLenCdHL6ZmR0ps98ANojC3AfaZJu0mLd98SmKLamt81Bciirtdr3N6SW2sIKZAkiRKYGXAe+h5W11PItYVqkAj7NeRKSSFhrSwIWyiX1G9xHFF0qAdDJGmKFV0WhpHqv32aD4BxHA9fiu74lFhxro3nbGFTW6U4ZAqQG5N1rOsKXHFuaj68mC+o2V3VuDZJ8nMywWJxg3ER9wIORfm7oSM23PEZsSnpy1CMKb/zPMRR/O8nH6qyPliVFRXOVhc9WuLHAMc/CjYGuby4xGw2w/n5hAoT/h9Dbp+r2RXOvp9hOp2qNjoIyKJzMfgvws65Hqsi0TqzZGYMXlbl1vr4DP8c/gDXP8G6hqcprgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Solution diagram&quot;
        title=&quot;&quot;
        src=&quot;/static/a08c4a0fe7d1dc7556ef9f1a4ffd6bea/295bd/SolutionDiagram.png&quot;
        srcset=&quot;/static/a08c4a0fe7d1dc7556ef9f1a4ffd6bea/4edbd/SolutionDiagram.png 175w,
/static/a08c4a0fe7d1dc7556ef9f1a4ffd6bea/13ae7/SolutionDiagram.png 350w,
/static/a08c4a0fe7d1dc7556ef9f1a4ffd6bea/295bd/SolutionDiagram.png 667w&quot;
        sizes=&quot;(max-width: 667px) 100vw, 667px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;proposed-solution&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#proposed-solution&quot; aria-label=&quot;proposed solution permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Proposed solution&lt;/h2&gt;
&lt;p&gt;In the following section, I provide a solution that can be used as a starting point to import and process messages from Azure file share.&lt;/p&gt;
&lt;p&gt;Initially, our XML files will be loaded to the Azure storage and then processed by D365FO.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 470px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/5ad493301212cd39f4a1473c545efd91/f96db/FIlesOnStorage.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 48%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABRUlEQVR42q1Ry3LCMAz0//9Pr/2AHsgUpkBJQkIe5OFX4tjhAt3KplCmV3rY0a5k7cgSe91YxI2D5AJFUcFODiXFujreuVIDjLFIkhRSavS9wHazBaee47GBotxiEYFTnr285XiPO+zp8frjE3lWIk0yigX2aY7dZ0xIUBwqMtmRaYayPIZ8VdaUL1FVDZI4pYFqsPUuQ8c12rYl9JBCB/SdoKgguAoTCeI+57XnnEuabCAtr29+akwpCTOO4EJgNIa+JAkK1jpqlGTGYaYJehjIhJPuMXmtNbquw3w64XL5CjifL2Ba+/1MmOcTnJsD9wbe0PNxNGGX02SvNXOrWapdue+7geX5AU3Thmk8lNIBfvm/XN35X+35I9hyuUQURXSlBVarFS09eQqsKArUNV2Loj+Mc+4pMGttILf4tOF/mDwafgO9MO/S0k3KkAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Files on storage&quot;
        title=&quot;&quot;
        src=&quot;/static/5ad493301212cd39f4a1473c545efd91/f96db/FIlesOnStorage.png&quot;
        srcset=&quot;/static/5ad493301212cd39f4a1473c545efd91/4edbd/FIlesOnStorage.png 175w,
/static/5ad493301212cd39f4a1473c545efd91/13ae7/FIlesOnStorage.png 350w,
/static/5ad493301212cd39f4a1473c545efd91/f96db/FIlesOnStorage.png 470w&quot;
        sizes=&quot;(max-width: 470px) 100vw, 470px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h3 id=&quot;connection-types-form&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#connection-types-form&quot; aria-label=&quot;connection types form permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Connection types form&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Connection types&lt;/strong&gt; form allows specifying the Connection type resource(currently, it supports Azure file share, Azure Service Bus and SFTP) and connection details for the selected resource.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/a517dc223f9407db9edd2a9f297113fe/d125e/ConnectionTypesForm.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 34.85714285714286%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAAA7EAAAOxAGVKw4bAAABE0lEQVR42pVRi2rFIBTr///gYGNbH7bXvrS+6qO12Wmhg8EdbEJQw0lMsOD9AmsdjPUQi4E2GkJKhJiw75mwIaWEFCO2FBGCRwyR+B1Hzsh5v2ZuFE1dQy0C1igaXEnoEbyDcwZ+tRcnhQBjDOPAMc8jFilgtLp2rU+dvxD8ikLKBW/ViNfPHt3kMagNH0zg5b1D2SkIs2GeJpRlhYl2Sw20WjAMPRp6hPMHVueopaUADsVZS+oIs+5w4YAlaDorm6AdcT6TicHjwdEPAxQlOo6DquZvnPcbxU3+ts4hpTWqmoG1HdqOI8aNNMcPo38YZijjULUj2l5S+nQ1WMNzzd8SKo2mbsAahmkcIcRMvx2eGn4Bh9AfC0A0K3cAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Connection types&quot;
        title=&quot;&quot;
        src=&quot;/static/a517dc223f9407db9edd2a9f297113fe/8c557/ConnectionTypesForm.png&quot;
        srcset=&quot;/static/a517dc223f9407db9edd2a9f297113fe/4edbd/ConnectionTypesForm.png 175w,
/static/a517dc223f9407db9edd2a9f297113fe/13ae7/ConnectionTypesForm.png 350w,
/static/a517dc223f9407db9edd2a9f297113fe/8c557/ConnectionTypesForm.png 700w,
/static/a517dc223f9407db9edd2a9f297113fe/d125e/ConnectionTypesForm.png 737w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;For storing a connection string, there can be three options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Enter the value in this form as plain text&lt;/li&gt;
&lt;li&gt;Use encrypted value&lt;/li&gt;
&lt;li&gt;Store the connection string value as a Secret in the &lt;strong&gt;Azure Key Vault&lt;/strong&gt;. In this case, the user needs to provide a reference to the standard Key Vault name (steps to set up it are described in the following post: &lt;a href=&quot;https://jatomas.com/en/2020/06/02/azure-key-vault-msdyn365fo-setup-certificates-passwords/&quot;&gt;Azure Key Vault &amp;#x26; MSDyn365FO: Setup Certificates and Passwords&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;inbound-message-types-form&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#inbound-message-types-form&quot; aria-label=&quot;inbound message types form permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Inbound message types form&lt;/h3&gt;
&lt;p&gt;The next form to describe our integration will be the &lt;strong&gt;Inbound message types&lt;/strong&gt; form:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/9e2942f42e365d6879cee2dd540b8a56/f941f/MessageTypesForm.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 71.42857142857143%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABz0lEQVR42qVT2ZKcMAzk/38vednKZDYZGMCcBtuAD+hIHtgsM3lIKqrqwvhoSS0pGdUMpQy6XqKXCkoryEGi7TpI2aPve9RNHddqHKH1CDMZOOfh/SuSNE1R1zVB0AMJrUaUZU4oIESJqhJE2mEYeizLhLYfMYyaCC39LwR7QsJer1mLy61DVi8QzYAsveHH+ztGipTP52mKsLPB288BuZAIROjsQsRnJM476NlDTw6z3bBYh65ro3e2bVuxrStWQgiBvoH2tn0vvCDxRMiLw1iHoqzQtJLIPZxf4cNG3h3SLEUpBN0JHxpG8k+IhIG8bTshR/H9csPXL28YDOniAWPXSJ7ndxRFiZp0reqKijPh2fYI11OEXIw8z2FJI3JLDh9p/o29EIZIKGJqWusIY8zpzj8RcoR5XuB6vVLrCGqRMer3X4RN08SUOXVNjT7Pc9T2t/jrSzFORTkRUjRxOqjZ27aL0bETJuRvvEtyrkcrMfj8mBTvniN0uN/v+Ha5QFQVET3OrLXIaL+jEZyXOT5mU0qBp40hh4Ea+4mQ/81eDL58VJcjZAd3koILZsy0j94CSRlJKeOdP6b8Wa/DeM37j2lZP85Y37ZtY3SczS+rf0IuCFY49AAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Message type&quot;
        title=&quot;&quot;
        src=&quot;/static/9e2942f42e365d6879cee2dd540b8a56/8c557/MessageTypesForm.png&quot;
        srcset=&quot;/static/9e2942f42e365d6879cee2dd540b8a56/4edbd/MessageTypesForm.png 175w,
/static/9e2942f42e365d6879cee2dd540b8a56/13ae7/MessageTypesForm.png 350w,
/static/9e2942f42e365d6879cee2dd540b8a56/8c557/MessageTypesForm.png 700w,
/static/9e2942f42e365d6879cee2dd540b8a56/f941f/MessageTypesForm.png 736w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;This form contains three main sections:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1 - Details tab&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Defines Azure file share connection and a path to folders to import messages.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Contains a link to the custom Class that will do processing from the queue. The class should extend the base class &lt;strong&gt;DEVIntegProcessMessageBase&lt;/strong&gt; and implement the following method:&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;c#&quot;&gt;&lt;pre class=&quot;language-c#&quot;&gt;&lt;code class=&quot;language-c#&quot;&gt;abstract void  processMessage(DEVIntegMessageTable  _messageTable, DEVIntegMessageProcessResult _messageProcessResult)
{
...
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The integration engine will call this method outside of a transaction so that all transaction control can be implemented per Message type. There can be different options here: one transaction per message, multiple transactions(for example, if a file contains several independent journals) or a single transaction per line. The result of processing and the current stage should be written to &lt;strong&gt;_messageProcessResult&lt;/strong&gt; variable, so in case of an unhandled exception, this information can be saved for review. Also, this class will be created one time per entire import session so it can implement different caching options.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2 - Operation parameters tab&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Contains parameters that are individual for the current operation. In our case, we don&apos;t have any parameters.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3 - Advanced settings tab&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Contains some common parameters:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The number of parallel threads to process incoming messages.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Reading limits from the queue(e.g. to read only the first three messages, this is for testing purposes)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Also, this form contains service operations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Test connection&lt;/strong&gt; button that tries to connect to the specified Azure file share directory and read files from it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;View messages&lt;/strong&gt; button that display messages with this type&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Import file&lt;/strong&gt; button that can be used in testing scenarios to manually import a message from a user&apos;s computer without connecting to Azure file share.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;incoming-messages-form&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#incoming-messages-form&quot; aria-label=&quot;incoming messages form permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Incoming messages form&lt;/h3&gt;
&lt;p&gt;This table will store the details of each incoming message.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/b5f5dca0d54d5c9f4fbed0797814a081/136a2/MessagesForm.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 35.42857142857142%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAAA7EAAAOxAGVKw4bAAABGUlEQVR42nWQC3ODIBCE8/9/YWYaY15N1IACIo9D3R4k7aTTlJlPb9djkdtobTFZA9krCCFwu16gtYLRGt67glYPbdj3zmNO9IdICXqM2CQWp9MRVbXDvqpQH2rs6xqKQ+aUQDEiEf2QdQzhQXzCdWCIciAn37oecrDQxsE6grGhkGsXEiZPmNwTn9ibC/m7ffHym/8w4bORuLaCNwQMamQMQkxF31rJB00YtIHSI6RU6O4SQg5wPhZkP6DtRBnbhvgajXCoTgKdSjg3Iz4Od0iz4q5mbA89Ll1ANyS0PXGfxO4osON+oZfC8aqxrRrsz32+MmFZFqzr+ovvta5Lfrzodz2sOSOvEmhHw8MOPPT4hP6pXz16630Bil0c3PfD8t8AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Messages form&quot;
        title=&quot;&quot;
        src=&quot;/static/b5f5dca0d54d5c9f4fbed0797814a081/8c557/MessagesForm.png&quot;
        srcset=&quot;/static/b5f5dca0d54d5c9f4fbed0797814a081/4edbd/MessagesForm.png 175w,
/static/b5f5dca0d54d5c9f4fbed0797814a081/13ae7/MessagesForm.png 350w,
/static/b5f5dca0d54d5c9f4fbed0797814a081/8c557/MessagesForm.png 700w,
/static/b5f5dca0d54d5c9f4fbed0797814a081/136a2/MessagesForm.png 884w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Every message has a status field that can contain the following values:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Ready&lt;/strong&gt; – a message was read to D365FO&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cancel&lt;/strong&gt; – The user has decided not to process the message. This is an alternative to a delete option&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;In process&lt;/strong&gt; – system-generated status, a message is processing now.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Error&lt;/strong&gt; – failed validation or errors during the processing&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Processed&lt;/strong&gt; – completed successfully&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In this form, it is also possible to do the following operations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;View incoming message context&lt;/li&gt;
&lt;li&gt;Filter by different statuses&lt;/li&gt;
&lt;li&gt;View a detailed error message&lt;/li&gt;
&lt;li&gt;Change the status to process the message again&lt;/li&gt;
&lt;li&gt;View file processing statistics (processing duration, time, number of lines)&lt;/li&gt;
&lt;li&gt;View the processing attempt counter. It allows implementing scenarios like trying to process messages with &quot;Error&quot; status several times.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;load-incoming-messages-operation&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#load-incoming-messages-operation&quot; aria-label=&quot;load incoming messages operation permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Load incoming messages operation&lt;/h3&gt;
&lt;p&gt;It is a periodic batch job that we can run for one or multiple message types.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 318px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/7819c5b4a030cd083694213599faf44c/cd2d9/LoadIncomingFiles.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 94.85714285714285%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB5UlEQVR42q1U226jQAzl//9k/2AfV7vvqSptQqGBAAqk4TrDnRA4aw+hSrZtmqgdyYzFjM7YPj7W2rZFUeQQIkOWpuQXSJIEWZahLEv6L5Dn+es+DAOuLY0vPZsmNrYN13VhWRZs8nVdp33y+d9isYBpGDgej9cB8c1L4xfDMEQURdjv90gpbU5rHMd3bV4fnWnsSClV3eI4VrW6ZY0nexMhA9Z1paxtG9RVicPh8Clgf6D7TYEiLxRZHBRnplJ2vQAb14fN5mwpSomu68AdwEyfPzBn/fsxwa+HEFKkSKhM3BV93zNgj7UXw3AldEfg70YgTiW9KlUL7XY7VFV1VrcJ8MefCj8XHapSQlB087l2rTr/E/Hm5ul8JvGM5YjYzVToTAqHz6zXdf0h2MBg6unLBzVGD0NqlyQmpcSKbQYLguAi1Zv7kD9FC7yIEVExfr2x+cMkvEQCwV4Qq1MbMCFN0yifmb4ZkNMxTQO2tYa1njRtPD1htVxiu93C8zyl5c+GwoX0WG6+7xMZk0rOpTeMw/1a1ldLrJ9NREROTITMlpAUd4F/Fzkq5ZCGAltFtcqlIDnltEs1J3lGsmpujpDTY4lxpLx3JDPeWW7s3wP2mjIXnkeXRwPWJyLmoeo4jiLmHsB/txzIm319yNkAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Load incoming files&quot;
        title=&quot;&quot;
        src=&quot;/static/7819c5b4a030cd083694213599faf44c/cd2d9/LoadIncomingFiles.png&quot;
        srcset=&quot;/static/7819c5b4a030cd083694213599faf44c/4edbd/LoadIncomingFiles.png 175w,
/static/7819c5b4a030cd083694213599faf44c/cd2d9/LoadIncomingFiles.png 318w&quot;
        sizes=&quot;(max-width: 318px) 100vw, 318px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;It connects to the Azure file storage, reads a file, creates a record in the &lt;strong&gt;Incoming messages&lt;/strong&gt; table with &lt;strong&gt;Ready&lt;/strong&gt; status and attaches a message content to this record. After this, the file is moved to the Archive folder. If &lt;strong&gt;Run processing&lt;/strong&gt; is selected, the system will execute the processing of the loaded messages.&lt;/p&gt;
&lt;h3 id=&quot;process-incoming-messages&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#process-incoming-messages&quot; aria-label=&quot;process incoming messages permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Process incoming messages&lt;/h3&gt;
&lt;p&gt;Message processing may be executed as a separate operation - &lt;strong&gt;Process incoming messages&lt;/strong&gt; that selects all not processed messages and calls the processing class for them.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 256px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/16c29570a02d5cecad1e69368fb795dd/6f3f2/ProcessIncomingMessages.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 140%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAcCAYAAABh2p9gAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACsklEQVR42q1ViXbaMBDk/7+rpSkBQgIhjs3hgI0xPsD3KU939YCUlgRIq/fmyZbk8e5qd7alKCp4NE1zgt/Xzu3/efYwWtPp/OzGV0eLeVzXRa/Xw3Q6xePjI1RVha7rch6NRhiPxxgOh3Kf1waDARRFwdPTEzqdDnzfP3rRqqoKdV0jCAK54XmeRBRF8t1xHOx2O2w2GxiGIc/xPq/P53O5luf5u4VM+D/HkZD/nKYpsixDkiTyr59dxAFCiPOEHDOOFceG46Vp2l+Hb7Lwo9GcwVWEG3sNc7mAtTLh0AXYawu77fbrFi7tALq1hfZmY2Z6mBou1l6CMG0QJELCDyt6/zwMLVFXKOnMfOFhPBhj9DCm+QXddhe2vUVaABGRJJQZtp/A8svrLMyzCrEXIvFjpNsEsUvPcYmECJOiQZwLRJlAXjXXEaZZCtEI1KKWic4pUVUlatqvqoLL4LYYcppwWamvKj1PsDJNTCYTucbplFJ+4pZbFmRBLShZ98lxEAvOxVuE40joRwKGV2Ool1i69XsO3qhER8KiKJDlBXZRiiDKwOtcfhzPL+XhbDajsnvB4KGPfvceD/0+2u02LMs6cf2Ste+3TILAlcGWHrTtn9TGNA28vipS59jVjJSnoDnPM1KgVL6zCpX7H35IyDFidzRNxffv39D5eYfn0RC9+w66hLu7H+R+Dz0Kg6YqcJ3NZQvZuS25a61WWBE8z5WwrBWJhi1z0tnY8FxHWnmVy+yqSR8yIcu6Za2xWCzlM+Pa2LYOZcaStXh7k7LFljJY0tZkJcOjRsYISdkvEjJMY0mEOoKdT7d9Dp50mRvUVS6XZSlTh/sK33KeZbK/SOx7Dc+XEv1IyK3yQBCG4bFhxXF80rwu9ZmTSuFGZRimbOi6Pt83rmfZuHif+zB78hnhL6hrfbbOZ4JNAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Process messages&quot;
        title=&quot;&quot;
        src=&quot;/static/16c29570a02d5cecad1e69368fb795dd/6f3f2/ProcessIncomingMessages.png&quot;
        srcset=&quot;/static/16c29570a02d5cecad1e69368fb795dd/4edbd/ProcessIncomingMessages.png 175w,
/static/16c29570a02d5cecad1e69368fb795dd/6f3f2/ProcessIncomingMessages.png 256w&quot;
        sizes=&quot;(max-width: 256px) 100vw, 256px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The logic of how to process the file is different per message type/class. For a simple scenario, the class can just read the message content and create some data in one transaction. For this blog post, I implemented two-step processing. Also, for the &lt;strong&gt;Process&lt;/strong&gt; operation, you can specify the number of &lt;strong&gt;Processing attempts&lt;/strong&gt; per file. The system tries to process a message and in case of any error, it increases the message &lt;strong&gt;Processing attempts&lt;/strong&gt; counter. This allows retrying processing several times without a user involvement.&lt;/p&gt;
&lt;p&gt;See a sample diagram below:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/f91545c64d17aa3a7c516c54d97cb4bf/167b5/ProcessDiagram.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 74.28571428571428%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABzklEQVR42o2UW5eaUAyF+f//rgutM+M8VFAHuchNxAuY5ksNpV2drnnYmhxOdvbZJxA0dS2n08nQgra1uCwr6ftebrebZGkmu91OoiiWzY+NIflIbN84jhOGYZAgz3LJskzyPJciL6QoCjkWR0kPB6m1GSjLUqLNRlbfV/KyerH/VJucz2e53+9GBIgDCipVUx6VJE2NkLjQBqhFZdd12qSQ/X4vSZIIIlAH4aRweCqke125isgKIDoqKc0gvF6v0mtxVVW2DhlrYK7OCM/a3T2kYzfLifGQzZDTDEBKo7quzCoEcResB/y8vb6pNysJw4UswqWE30J5X7+bUieEoGka85kYoBiLuAN4OGXwS1Gnak6TMtAo2eVymchQD5lbwjOaPR4Puehz8vExSuDnv7sXw+9bw2z3qlY1y8VS1q9rieOt7UcMeyBjD3HgxZ8BFfjnFwWYV9acsH8qtEuZF/twznMIzXD1KtYpiKPIxqttWiO0I3+m8F+E2EEhKo5qOvOJn64KQs+JA/PvicnPv9YAxbyC2+3WLs1VARp+6ci+9sfR1UOKHXP/7Mj/U+g5CgBzdlD/PHffXIi9y1/1kBnkrUAhg8zXaK7MvzY/AXqTho0IpWf3AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Process diagram&quot;
        title=&quot;&quot;
        src=&quot;/static/f91545c64d17aa3a7c516c54d97cb4bf/8c557/ProcessDiagram.png&quot;
        srcset=&quot;/static/f91545c64d17aa3a7c516c54d97cb4bf/4edbd/ProcessDiagram.png 175w,
/static/f91545c64d17aa3a7c516c54d97cb4bf/13ae7/ProcessDiagram.png 350w,
/static/f91545c64d17aa3a7c516c54d97cb4bf/8c557/ProcessDiagram.png 700w,
/static/f91545c64d17aa3a7c516c54d97cb4bf/167b5/ProcessDiagram.png 776w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The class reads the message data and writes data into a staging table during the first step. Then based on the staging data values, a new purchase order is created. It can be done using data entities or just directly writing to tables.&lt;/p&gt;
&lt;h2 id=&quot;error-types-and-how-to-handle-them&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#error-types-and-how-to-handle-them&quot; aria-label=&quot;error types and how to handle them permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Error types and how to handle them&lt;/h2&gt;
&lt;p&gt;It is not a big task to create a purchase order based on some data. The complexity of integration is often related to exception processing and error monitoring. Let&apos;s discuss typical errors and how users can deal with them.&lt;/p&gt;
&lt;h3 id=&quot;connection-errors&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#connection-errors&quot; aria-label=&quot;connection errors permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Connection errors&lt;/h3&gt;
&lt;p&gt;A batch job exception will be generated if our batch job can&apos;t connect to an Azure file share or read files. It is a configuration error requiring a system administrator&apos;s attention. Notification may be done using a batch job status. After troubleshooting, the system administrator can use the &lt;strong&gt;&quot;Test connection&quot;&lt;/strong&gt; button to validate that the system can now read files from Azure file share.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 586px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/ee8701bbd8d7cc2f0d79a18591cd646a/a76f4/TestConnection.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 60.57142857142858%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAA7EAAAOxAGVKw4bAAABxUlEQVR42o1T7bLTIBDN+7+Hv30PR2fUH2q9TW9bS75IgEAaEiA5LrS9vTpWZebMArt72D3ZZAXXaKSG0gOkmcDovPvBULUKVScvvsGiFgqsERQz0r1C1w/pXIsewwyMHrCE7Fs54P2W492zwefCY9M4fCkGfG8snviEbTsh71zab+ox2Zsv2ohtO78g4w3HkY948wF4+2mFsSuc8+i6Bi2vwJsKZXGifQ1xvet7CT9bBDfDJTu9INvlOY6MkrhEP0yoOw1BbTREtN8/E3EL3Su0Lcc4njFPFpMdEYIn/w759gkzkborMucDNgeJj18L5MzgUDvS6AyjFXjdEFmP2VpYIhvPd0RSQY8pKYhogqdqIzLnHHxYsKwAmWTjnRAdhJSIa1mWXxBCgPc+7dd1xRLzw8WXhavj9YrBLecoGKN25nviNU4bjcNhj7Kq6P6eF2P+TEilGxoVVmt0yiS9XhNakoAVjHTm6JWCpLYVSfOwwuAdOG+x3R0psSQJ5iTDrdrYsjEmYRgIyQ7p4YeESkmc2Im0FIkgVnjD39aDliMh/RlFgV5r+lCXquJ8/h77X4QzjYEmoqqk+WRlar+jSmPb/yL8CfAJnrNERW5HAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Test connection&quot;
        title=&quot;&quot;
        src=&quot;/static/ee8701bbd8d7cc2f0d79a18591cd646a/a76f4/TestConnection.png&quot;
        srcset=&quot;/static/ee8701bbd8d7cc2f0d79a18591cd646a/4edbd/TestConnection.png 175w,
/static/ee8701bbd8d7cc2f0d79a18591cd646a/13ae7/TestConnection.png 350w,
/static/ee8701bbd8d7cc2f0d79a18591cd646a/a76f4/TestConnection.png 586w&quot;
        sizes=&quot;(max-width: 586px) 100vw, 586px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h3 id=&quot;file-format-errors&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#file-format-errors&quot; aria-label=&quot;file format errors permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;File format errors&lt;/h3&gt;
&lt;p&gt;The next error type is the wrong file format, so we can&apos;t even read the data from a message.&lt;/p&gt;
&lt;p&gt;To test this case, I renamed one XML element. After the import, users will see this message with the Error status. Notification may be done using standard filtering by the &lt;strong&gt;Status&lt;/strong&gt; column.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/662260250abdaf8cc8f0262c8fa3569e/90712/WrongColumnError.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 34.85714285714286%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAAA7EAAAOxAGVKw4bAAABV0lEQVR42l2Qy5KbMBBF/f//M/ssss0m2Yw9PMXbGOwBJIEQnGlYJFNR1am+6r59S3CJrxF1VpCGijSIycIYFSZE7wHJR0R8C4iuAaFQJDmVyqlVcdYqzU7aoqIta1RUcjF9Tx5FEhRwz5QMcxqV8tnembqO8fGQ+kCL7/DqU3f/ZqL9NLFpzWY0F+cceZ6hsoxUKYqyJE4SOlmelwVrDNZajFQtS4f+Hy1Bx0yL57KujrZtGceB2Wr8urB5d1Y3G0Gz2EnuM/vuxWNOzpn4D9bFnhw9CVxR1ZO6Gxi0E1aa9pOi7uhfhtc4Y+zGLW74+esqesbOC1X74jnMjOKvmid5+aCWPQn0NJ0mLXv6cWWwULYTH3HFvbfS8+gFft8a3n78YTQrk/V0w8pL7ydR1hKmjWQ8uXh5ofce5xb5pI3jbHI/fsX3s+87++a/N/5KL95V9t0y8wVorRVME9yXLwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Wrong column error&quot;
        title=&quot;&quot;
        src=&quot;/static/662260250abdaf8cc8f0262c8fa3569e/8c557/WrongColumnError.png&quot;
        srcset=&quot;/static/662260250abdaf8cc8f0262c8fa3569e/4edbd/WrongColumnError.png 175w,
/static/662260250abdaf8cc8f0262c8fa3569e/13ae7/WrongColumnError.png 350w,
/static/662260250abdaf8cc8f0262c8fa3569e/8c557/WrongColumnError.png 700w,
/static/662260250abdaf8cc8f0262c8fa3569e/90712/WrongColumnError.png 882w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Users can view an error log, then download the message and check the reason for this error. For example, there may be the following reasons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Our code that processes messages contains some mistakes. In this case, we can download and send this message to a developer to fix the logic. The main advantage of this solution is that users can run processing without connecting to Azure by using the manual &lt;strong&gt;Import message&lt;/strong&gt; button. After fixing the problem, we can rerun the Processing.&lt;/li&gt;
&lt;li&gt;External system sent a message in the wrong format. In this case, the user can send this file back to the external party and then change the message status to &lt;strong&gt;Cancel&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;data-errors&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#data-errors&quot; aria-label=&quot;data errors permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Data errors&lt;/h3&gt;
&lt;p&gt;The message has a correct structure but contains incorrect data(e.g. values that don&apos;t exist). In this case, a Status of our Message will be &lt;strong&gt;Error&lt;/strong&gt;, and an error log will be generated.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/af4fcb7672b65938b43908185b0f23f2/96e92/WrongDataError.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 27.999999999999996%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABLUlEQVR42n2Qy3KCMBiFef+ZvkJ3fYTu+hDtxiqKBFEIKndIQlC+xnSc7rr45pyc/5JMgkbmXE+Swy7mkh7IY0EhEo7bCOn0FEUUSYJYb8j2e6SrSyFIt1uqU06TF+iy4t4P3Lqe4BTHiDCkzDPa85m6kJ6xqtBNg2pqVF2j2+YXl5m29V7V1W/NZVPXeYIkidnuQnbuJcLdnBwEm3BNcS6wdsIY/Q8GMxm080+CS1kzDAqllG+w1jI51Ur77InWrq61R6s//1j8OD8JMvcH12vJOLRu0eiaRmarud8mbrNhuU8si8VOblj1WDMwT6P3RnVeb1Z5HnmwEj27tOTSLch6ZhUVbOIzImspmpm3909eXj+4VAMH2ZLIkSit+fpOiY4Ncd6TV7PrXRB5zw8ABsYswF3UPwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Wrong Data Error&quot;
        title=&quot;&quot;
        src=&quot;/static/af4fcb7672b65938b43908185b0f23f2/8c557/WrongDataError.png&quot;
        srcset=&quot;/static/af4fcb7672b65938b43908185b0f23f2/4edbd/WrongDataError.png 175w,
/static/af4fcb7672b65938b43908185b0f23f2/13ae7/WrongDataError.png 350w,
/static/af4fcb7672b65938b43908185b0f23f2/8c557/WrongDataError.png 700w,
/static/af4fcb7672b65938b43908185b0f23f2/96e92/WrongDataError.png 779w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Users can view this error, display a &lt;strong&gt;Staging data&lt;/strong&gt; to check the values from the message and take some actions(e.g. create missing values in the related tables if they are valid). After that, they can Process this message again.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 690px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/d1f4828c2e8974fac1849dbadba9f718/1e043/WrongDataErrorStaging.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 66.85714285714286%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABqklEQVR42q2Si3KcMAxF+f/vyyTbzS4bHuFpbLDNwxi4FWLSbDfttJ2phzOSrm1ZxgqKSqGRDWohkRUCVVUjywvkeYk4TVBWFeIk4XmtLYz5DfYg2DagLAuczyeE4RWnby/Isne0SkIR1mgoOlB3LWY3ws/ujunBnxAAGyUsEcUxmkZwMqM7rIs/Frpjw+wm4vDdNDIf+g+foApXqLbjKw1Dj2kcuKq9IkPWWkNXbXnT0FvW90PcOLI/2J5jTUVYrREsy4JcDLgmNdK8wWsk8HwpEBU93nKDl1Dh6dLgHBvcMosbaYXySKsRT+eMNI1cOjxfS5zCak/o0Q8TpnmFXzayG/v0UbUeKskh4xwiTGAqeejz57p7f3QLJfT0r4hfj+0vtc/xh4T/PoKV/uE0Tf+NYF1Xej3Dr2TolXb0HV9ic1gl5U/6BwGos6XcG9hgWxwWbtCR7er3eDxif8SemvvQj/gRvnIle0jt2b6lNaL3GqId0fUL0kLilpQcK+14vhCG51rrv8BtI9QAoVfUncclrpEUBtKCtVLNCFNJ1rG22yhrIczG8498ByNL69OTlYzfAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Staging error&quot;
        title=&quot;&quot;
        src=&quot;/static/d1f4828c2e8974fac1849dbadba9f718/1e043/WrongDataErrorStaging.png&quot;
        srcset=&quot;/static/d1f4828c2e8974fac1849dbadba9f718/4edbd/WrongDataErrorStaging.png 175w,
/static/d1f4828c2e8974fac1849dbadba9f718/13ae7/WrongDataErrorStaging.png 350w,
/static/d1f4828c2e8974fac1849dbadba9f718/1e043/WrongDataErrorStaging.png 690w&quot;
        sizes=&quot;(max-width: 690px) 100vw, 690px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;In some implementations(EDI), we can even allow staging data editing. A similar type of error is a posting error.&lt;/p&gt;
&lt;h3 id=&quot;wrong-result-errors&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#wrong-result-errors&quot; aria-label=&quot;wrong result errors permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Wrong result errors&lt;/h3&gt;
&lt;p&gt;That is probably the worst scenario. The message was processed successfully, but the resulting document contains some incorrect data.&lt;/p&gt;
&lt;p&gt;Users can view the staging data and check that they are correct to analyse the result. Also, a message content can be sent to a developer, and they may trace the document processing using the manual &lt;strong&gt;Import message&lt;/strong&gt; button&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/c07d4ca7ec717e2c83146875c53bd124/f1901/ManualImport.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 29.142857142857142%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABAElEQVR42n1Q0WrDMAzM/z+tT2Xdw6CUdRuMwZ469iuDQWhhSUjtWLKdOHZuckofxsIEh2Q43elcrDaPuLndY7XZS3/A3e4Nu5cPbJ/fcf90wHr7is+vEnEcMQqmafoXBbEFsYPuDDpzATHBSG9PRzRlCSae32OMyJUXl8o5j8JaRkoRuROZGc5ZeO8Qeo9eZmYWww4hBCxpXQ2q6huF8wNiuqhnMe89olyS46UpyVXjbFbXFZqmhlYK1fEkZv2yoDI9yEUY9hKNMAzhF1F3WuISqlrLzPDWwrUtUgh/BNX5jCK7kgjlOEQWStN8YUppJiqtwCJyXVz6vcy1wtG6ww+hyMsClCQdKwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Manual import&quot;
        title=&quot;&quot;
        src=&quot;/static/c07d4ca7ec717e2c83146875c53bd124/8c557/ManualImport.png&quot;
        srcset=&quot;/static/c07d4ca7ec717e2c83146875c53bd124/4edbd/ManualImport.png 175w,
/static/c07d4ca7ec717e2c83146875c53bd124/13ae7/ManualImport.png 350w,
/static/c07d4ca7ec717e2c83146875c53bd124/8c557/ManualImport.png 700w,
/static/c07d4ca7ec717e2c83146875c53bd124/f1901/ManualImport.png 942w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;summary&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#summary&quot; aria-label=&quot;summary permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Summary&lt;/h2&gt;
&lt;p&gt;I provided a sample implementation for an Azure File Share integration for D365FO. The main concept of it is to create a basic framework to simplify troubleshooting(most typical errors and all related data can be viewed in one form - &lt;strong&gt;Incoming messages&lt;/strong&gt;) and provide some additional logging.&lt;/p&gt;
&lt;p&gt;In the &lt;a href=&quot;https://denistrunin.com/tags/integration/&quot;&gt;series of posts&lt;/a&gt; I provided samples for different file formats used for import:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;XML&lt;/li&gt;
&lt;li&gt;CSV&lt;/li&gt;
&lt;li&gt;JSON&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Different most complex D365FO documents:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Sales order&lt;/li&gt;
&lt;li&gt;Purchase order&lt;/li&gt;
&lt;li&gt;Ledger journal&lt;/li&gt;
&lt;li&gt;Standard DMF project&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And different exchange media:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Azure File Share&lt;/li&gt;
&lt;li&gt;Azure Service Bus&lt;/li&gt;
&lt;li&gt;SFTP&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This may or may not be appropriate in your case(there are different options how to implement this). Anyway, I recommend using the following checklist while designing the integration: &lt;a href=&quot;https://github.com/TrudAX/TRUDScripts/blob/master/Documents/Integration/Integration%20Data%20Flow%20Requirements.md&quot;&gt;Integration solution specification&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Files used for this post can be found in the following &lt;a href=&quot;https://github.com/TrudAX/XppTools#devexternalintegration-submodel&quot;&gt;folder&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I hope you find this information useful. As always, if you see any improvements, suggestions or have some questions about this work, don&apos;t hesitate to contact me.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Dynamics AX performance monitoring: missing indexes]]></title><description><![CDATA[The blog post describes a monitoring solution for SQL Server missing indexes.]]></description><link>https://denistrunin.com/performance-monitormisind/</link><guid isPermaLink="false">https://denistrunin.com/performance-monitormisind/</guid><pubDate>Fri, 28 Jan 2022 22:12:03 GMT</pubDate><content:encoded>&lt;p&gt;Proper SQL indexes play a vital role in the performance of Dynamics AX(or D365FO on-premise). Even one query that doesn&apos;t have appropriate indexes may slow down the system and increase the load on the SQL Server. In this post, I want to describe how to implement a monitoring solution for missing indexes.&lt;/p&gt;
&lt;h2 id=&quot;missing-indexes-example&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#missing-indexes-example&quot; aria-label=&quot;missing indexes example permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Missing indexes example&lt;/h2&gt;
&lt;p&gt;Let&apos;s simulate the missing indexes issue. I am using a standard AX2012 Demo VM for this. For example, we need to find all vendor invoice lines related to a sales order.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 597px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/7140f325554d7cfa50788962d3146019/17602/TableBrowserVIT.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 43.99999999999999%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB3ElEQVR42k1R2Y7TMBTNX/LIDIsQ/AovfAuLBl6QGEFfgCmCoTNqmzjO0iRN4mxO0mw+XHvYrnR0fXzsu1r3LzZ4dMnxbOUZPP30HzRf+XjywcbZq884f7P+i7OXmn/D+esrPHx3jQdvf+Dx+y2sey++4/mFh+OosC9OYPUIt5kMnGownNV0Lnrsc0no4JQ9bNHRuTWwSdO6U55gHQ4pbm4dhH4IKTsE5B2bwfcClEWFMDiAOS6SJEPfD+RTcNdHFCWGd90JeZrTnWc0S1Y54uiAsixRFAVEnqOua3Rti4Z8UQgIIdB3HVq6y/OM9IqC9RgGHbAz77MspYIkLEEPGPegAIzTBM59SPqoTcoW3PMRU2atD6TvbAdFVRt9WhaCQi4KMKqwpWqtkgJyCqhtXmZTus6krW074ow6iO/0eYbLGGRzpyuljM+zDAElHscRlh9n+Lp1cRyAVA7Y72zKKLCoBamocLVl+OlGOJ4UonYynGUNkl4hbmfjN36M9Y4jrAdYe1rK5YYeSYWgok3u9sgooM4e5SU+kvbFjuDKhbY+YnXDcB1X8Fpltu82C9b8iNUtx05QyzUNPQjD3y0vCILQtKpND9zjHEmcGL4Y/d+M/7Tc0JISGss0TfgFEV2XIzTpVAAAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Table Browser VIT&quot;
        title=&quot;&quot;
        src=&quot;/static/7140f325554d7cfa50788962d3146019/17602/TableBrowserVIT.png&quot;
        srcset=&quot;/static/7140f325554d7cfa50788962d3146019/4edbd/TableBrowserVIT.png 175w,
/static/7140f325554d7cfa50788962d3146019/13ae7/TableBrowserVIT.png 350w,
/static/7140f325554d7cfa50788962d3146019/17602/TableBrowserVIT.png 597w&quot;
        sizes=&quot;(max-width: 597px) 100vw, 597px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;To do this, a developer may write the following code:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;    &lt;span class=&quot;token class-name&quot;&gt;VendInvoiceTrans&lt;/span&gt;        vendInvoiceTrans&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;select&lt;/span&gt; vendInvoiceTrans
        &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;vendInvoiceTrans&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;InventRefTransId &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;002862&quot;&lt;/span&gt;
    &lt;span class=&quot;token range operator&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;    &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The problem is that &lt;strong&gt;InventRefTransId&lt;/strong&gt; field is not indexed, so to get the result, SQL Server needs to scan all rows in &lt;strong&gt;VendInvoiceTrans&lt;/strong&gt; table. Depending on where this code is used, it may affect user performance or increase the load to a SQL Server. Also, &lt;strong&gt;InventRefTransId&lt;/strong&gt; is a highly selective field, so it is a perfect candidate for an index.&lt;/p&gt;
&lt;p&gt;SQL Server query optimiser can automatically detect such cases and generate recommendations for index creation. These recommendations can be displayed by querying &lt;a href=&quot;https://github.com/TrudAX/TRUDScripts/blob/master/Performance/AX%20Technical%20Audit.md#missing-indexes&quot;&gt;missing index&lt;/a&gt; view. Moreover, analysing the output of this view is a prominent part of any &lt;a href=&quot;https://denistrunin.com/performance-audit&quot;&gt;performance audit&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/eec3d01bd4d47c4216b946996a34bd03/ee9b6/MissingIndRecommendation.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 27.999999999999996%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABR0lEQVR42p2P3U7CQBBG+/6P4YVoEKuCETXxShOjxgsNCBaw0m3ptt3+7XQxtPRzkDdwki9nTjKTyVi++wzpPCGYPqIUr3h5uMfBkY1Ot4/Dkz663Uv0OkMc2wOcXd7h5HzIuYLdv8bpxRD24AY95im7PbiFlaYNvDDBV+BBJBIJKWhT4r9lkf6BkAKfyzkWwQKON8dMzJBTjrYF6rpF3QBN2zA37PU+TYPNhr3ZYrtteXYfK4oaLJcBvt0Iia+hFEEmEUIluddI4gpxTIjSEoUhVKaCMWus12sQEbP+O7yrHflljTCUSFWKPCugS40sK6G1gaYKVBlOhbI0yFJiVihKQp4TioL7gniHQJpnycB6G43VaDxRs/lCOY6jVsFKTd5H+fxjkvvud+4tvv4o3Fnm+1MlpauE8Jkr5lTFiaciGbFLdqF+AY00u5rq+mLQAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Missing index recommendations&quot;
        title=&quot;&quot;
        src=&quot;/static/eec3d01bd4d47c4216b946996a34bd03/8c557/MissingIndRecommendation.png&quot;
        srcset=&quot;/static/eec3d01bd4d47c4216b946996a34bd03/4edbd/MissingIndRecommendation.png 175w,
/static/eec3d01bd4d47c4216b946996a34bd03/13ae7/MissingIndRecommendation.png 350w,
/static/eec3d01bd4d47c4216b946996a34bd03/8c557/MissingIndRecommendation.png 700w,
/static/eec3d01bd4d47c4216b946996a34bd03/ee9b6/MissingIndRecommendation.png 1041w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;From some real-life experience of Dynamics AX performance optimisation, usually, it is enough to analyse 50 first rows from this view with an impact of more than 99%. Most(but not all) of such recommendations will be valid, and new indexes should be created.&lt;/p&gt;
&lt;p&gt;But you should not automatically apply every recommendation. Here are some exceptions where you don&apos;t need to create an index even if the impact is 99%:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;A &quot;select&quot; is an external query with a missing DATAAREAID/PARTITION field and a field already presented in the index: In this case, it is better to add DATAAREAID/PARTITION to such an external query.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;There may be a lot of fields in the missing index recommendation, but not all are selective. Extensive indexes may slow down the system, so the number of fields for the new index must be minimal, you should add only selective fields to the new index.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;A field is already presented in the index but not in the first place. A perfect example of this is &lt;strong&gt;CustPackingSlipJour&lt;/strong&gt; table. To get a packing slip for a sales order, a Module(&lt;strong&gt;RefNum&lt;/strong&gt;) should be specified. Usually, it contains just one value(Sales order type), and developers often forget to select it.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 286px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/a4c1e147f482312a79bc0c3a6598603d/357e3/CustPackingJour.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 74.28571428571428%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACiklEQVR42pVTyW4TQRD1XyK2SAjlwJkP4E+4AVlAIlyIhDiEgBesBGf23ZM4DmNnPB7P5lnzqB7b2XwJJZW6e5bXr96ragydKb7/PsPrPQ8b2zE2Pyd4sRNjYyvEy90Qzz6EePI+xFNaX30K8ZyeP6bzJr179C7Cm30fKAuwuKJsJEkCwzSx1w2w3x3iW1tGWxriIihhewXMywz6OEX/MqV9CnWUwqCzSanT/tzLCOkKq2hkWQbXvcQh56En2DBkAbZlIph68D0XRVHgf6KRZznGIwe73210/vRhqgo0zYBtWjANC/M0W5RDLBiRtbwPWBYlwijEcesXNGMASVTB8wJmQYgyL5BlKTICzfMcZVmiqirKq+UF1XK9VfLqMAt8mIqEdkeAavbBixKOj3vgZRmipIA74WFaFqIoRjJPaI0QBAHiOKbLbmRp4NofFnQ7sT3qDMAddiH8OIDabGNMpTM2JbG7+f4us3uAqEthEZye4cvbr2ju7KG7vYXuzkc4R70lwANMAe5yLOivA2WOnmxB1DTYwwucXTgYj13SsHo4INNk6odwRjOcqCOoqglDUSCRQSLHg6ec+rPamFWylmKmVlW1boo7mRAAmdLsoU99aOga+N4JOE6CKsrQNX1pSoQ4WZgSkd4LU/J1QH/mQxYV/GzJcBwHsiBBligVFZpuwJtOa0ZzcjgMF0Bpmq6XvAKceB4GlkHlqRgMBjCouWWJlSwSSwECtY1MTT8ajWsgBsj6l7Fk47vCuQb0aNQ00qzZ4nBqn6JPkyIJCgxDx/lwSKyC+ptV7zEQpiP7n2m4Bui6bs2q1ZGJmUhjZ0IURGiqSnsDzl8HEyqbaReGETX3vJ4ipt/tef8HSRNkwhelhisAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Cust packing slip table&quot;
        title=&quot;&quot;
        src=&quot;/static/a4c1e147f482312a79bc0c3a6598603d/357e3/CustPackingJour.png&quot;
        srcset=&quot;/static/a4c1e147f482312a79bc0c3a6598603d/4edbd/CustPackingJour.png 175w,
/static/a4c1e147f482312a79bc0c3a6598603d/357e3/CustPackingJour.png 286w&quot;
        sizes=&quot;(max-width: 286px) 100vw, 286px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Another variation of this case is my example with &lt;strong&gt;VendInvoiceTrans&lt;/strong&gt; above. In this case a code contains a condition for &lt;strong&gt;InventRefTransId&lt;/strong&gt; field but the value for &lt;strong&gt;InventRefType&lt;/strong&gt; is not specified. This is a development error, and both fields should be specified in the code and in the index.&lt;/p&gt;
&lt;p&gt;Let&apos;s discuss how we can automatically monitor such issues.&lt;/p&gt;
&lt;h2 id=&quot;missing-indexes-monitoring-solution-implementation&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#missing-indexes-monitoring-solution-implementation&quot; aria-label=&quot;missing indexes monitoring solution implementation permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Missing indexes monitoring solution implementation&lt;/h2&gt;
&lt;p&gt;Such problems are pretty easy to fix; you need to periodically check the missing indexes view. To automatically perform this task, I created the following Dynamics AX performance missing indexes  monitoring &lt;a href=&quot;https://github.com/TrudAX/TRUDScripts/blob/master/Performance/Jobs/SQLTopQueryMonitor/dbo.AXMissingIndexesMonitor.StoredProcedure.sql&quot;&gt;procedure&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;sql&quot;&gt;&lt;pre class=&quot;language-sql&quot;&gt;&lt;code class=&quot;language-sql&quot;&gt;msdb&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;dbo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;AXMissingIndexesMonitor&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;@DBName&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;MicrosoftDynamicsAX&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token variable&quot;&gt;@SendEmailOperator&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;axoperator&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;@DisplayOnlyNewRecommendation&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;@Debug&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The idea is the following:&lt;/p&gt;
&lt;p&gt;You create a SQL Agent job to run this procedure every day. If there are any missing indexes with 99% impact in the first 50 rows of the missing index view, the system sends an email to the person responsible for Dynamics AX performance monitoring.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/2704228499ee9e78ff2c8f78db5c8ab1/6c745/Email.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 26.285714285714285%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAYAAABFA8wzAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAoElEQVR42qVQSQ6DMBDL//9XjjmVQBbIwiYW4caR4IB6akeyxmONPHHEq6rwrmuE4KGaBlprpJRwnid+KaGNgbEOfd8jhpiNA8ZxvBdofOGb9oQ4jgP7vheQ/1timiZIKdG2LYZhQJNjs19H+GKlFExOwnld15Km6zo452CtLZwgF/M8lwX+G40o0iTGCO/9vUhDasSyLNi2rXTOPMSZxz6hn4Sil3wyhAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;E-mail&quot;
        title=&quot;&quot;
        src=&quot;/static/2704228499ee9e78ff2c8f78db5c8ab1/8c557/Email.png&quot;
        srcset=&quot;/static/2704228499ee9e78ff2c8f78db5c8ab1/4edbd/Email.png 175w,
/static/2704228499ee9e78ff2c8f78db5c8ab1/13ae7/Email.png 350w,
/static/2704228499ee9e78ff2c8f78db5c8ab1/8c557/Email.png 700w,
/static/2704228499ee9e78ff2c8f78db5c8ab1/6c745/Email.png 893w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The developer should always react to this email. There can be two outcomes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Either the index should be created(it should be done in AX application level and new application release deployed)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Or if missing index recommendation is not valid a developer may mark it approved(set the flag &lt;strong&gt;IsApproved&lt;/strong&gt; from &lt;strong&gt;AXTopMissingIndexesLog&lt;/strong&gt; table)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;d365fo-cloud-version&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#d365fo-cloud-version&quot; aria-label=&quot;d365fo cloud version permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;D365FO Cloud version&lt;/h2&gt;
&lt;p&gt;The manual monitoring is valid only for On-premise D365FO versions(based on SQL Server). The Cloud version of Dynamics 365 for Operations uses Azure SQL Database at the backend, and missing indexes are created automatically by the DAMS service. The following article is an excellent description of how the process works internally&lt;a href=&quot;https://devblogs.microsoft.com/azure-sql/running-1m-databases-on-azure-sql-for-a-large-saas-provider-microsoft-dynamics-365-and-power-platform/&quot;&gt;Running 1M databases on Azure SQL for a large SaaS provider: Microsoft Dynamics 365 and Power Platform.&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#conclusion&quot; aria-label=&quot;conclusion permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Using the described solution, you can monitor your Dynamics AX SQL indexes and get a notification when SQL Server identifies new recommendations. It will help to maintain a stable level of Dynamics AX performance.&lt;/p&gt;
&lt;p&gt;The code for this can be found in the following &lt;a href=&quot;https://github.com/TrudAX/TRUDScripts/tree/master/Performance/Jobs/SQLTopQueryMonitor&quot;&gt;folder&lt;/a&gt;. This procedure is a valuable addition to my previous monitoring solution&lt;a href=&quot;https://denistrunin.com/performance-snifmonitor&quot;&gt;Monitoring the most problematic performance problem in Dynamics AX - parameters sniffing&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I hope you find this information useful. Don&apos;t hesitate to contact me in case of any questions or if you want to share your Dynamics AX/D365FO SQL monitoring approach.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[XppInteg - Azure Service Bus integration solution for Dynamics 365 FinOps]]></title><description><![CDATA[The blog post describes a sample approach to implement Azure Service Bus integration in D365FO using X++]]></description><link>https://denistrunin.com/xpptools-integservbussalesjson/</link><guid isPermaLink="false">https://denistrunin.com/xpptools-integservbussalesjson/</guid><pubDate>Thu, 11 Nov 2021 22:12:04 GMT</pubDate><content:encoded>&lt;p&gt;This post extends my previous post &lt;a href=&quot;https://denistrunin.com/xpptools-fileintegledger&quot;&gt;How to implement file-based integration in Dynamics 365 FinOps using X++&lt;/a&gt; but with another way to transfer messages. As the file-based approach still may work for many cases, in the cloud world, we have a lot of other, fancier ways to transfer messages. In this post, I will describe how to use &lt;strong&gt;Azure Service Bus&lt;/strong&gt; to do a custom X++ based integration.&lt;/p&gt;
&lt;p&gt;Azure Service Bus is a cloud-based messaging service providing queues with publish/subscribe semantics and rich features. It is a fully managed service with no servers to manage or licenses to buy.&lt;/p&gt;
&lt;p&gt;Common Service Bus usage scenarios:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Build reliable and elastic cloud apps with messaging.&lt;/li&gt;
&lt;li&gt;Protect your application from temporary peaks.&lt;/li&gt;
&lt;li&gt;Distribute messages to multiple independent backend systems.&lt;/li&gt;
&lt;li&gt;Decouple your applications from each other.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The pricing for Service Bus starts from 10USD per month for 12M operations.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 610px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/39572bd825f58374a8d11c70a091bc46/5aae9/ServiceBusPrice.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 70.85714285714285%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAA7EAAAOxAGVKw4bAAADH0lEQVR42l1UXYscRRQdkvwO/QcB8yN80AcRXPISCII+BMUfIMhGNARCiIg+Kij4oPMgioYFlV132LCJayfr7szsfDCz0z3TM9vV3dPd1V/T3VV1vF2zkjW3OVRXU3X63HtuVSPPUvT7fQwGA4xHI4wI4/EYw8FQf+v3ewjCEHUopUQ95nn+pEFBr1cIly/gUqOqSpSi0FhVOfIyX8/pe55nyFY5FD1SSQgpNGFVVZpwc3PzUuPFqMoKXm8J+6lL8GA/IxgOzPYZ9rsRtv5ysfWY4eE+w0+tqTrsOYii0DZN8/ZkMrlD2XxKWX1yenp6b2jzdxp5ssIvdww0P9jG97d+ww/v/YEf3/8d3328jdtfj/Dg2x4++vIfwjE+/PwQ3/zcB3MWuiymOdHjaDwWjuPUpWg1hKgwcDiWnCPgHs68BeIsQpCWOLYicB4iDBhcNkeaRIhyBcaYms1mgghEHCeEuBBSQkq5o1O25gy2PcdsOkPMYyREfubFGExszOc2ZjOb0uQIyRwWFXA9D5Y11XNOa5Mk1rUVQrTIlArH8wXYckmpMJRlCSUFnCDD/iTBMoxIYfCfy/A51ZwISaWeS6k017lZNaGkzW0kaUAbIyyJOE0SMCI8sObwlz5c10VGjkdRRGtXWCzIsMdP0G530T3podPtCdfziRxrhVWlf3AhFLwww+F0F8ydUz8OQS6iLrwfV+j1h3jtjbdw/cbbuPnuLbz6+pvi/mdf1BvXhEVZaPka69zghilOnQ6yNEYQhIgo9TRNEWYK1nSKXx9uobX3CDu7LWz/uSsmprUmLIpCUd2UlnUBpFDxtPifbnIRHi/pB4Gi9EVRrLTToqqKc1N2NCFB0imQdQgaitVKnvlcRgn1iNLtUC/WCp0g10dx6fvkbqJd5hF/7jKpk77vC5e5wnWZIPeEYfwtjk9GYuH4ynUd3SbUd9jb21NDk4H6LqGGPrAsy6BTYnQ63QM69ydZln1VK7xrGMbLnU7nFePIuHp0dHS12+1ea7fbL5mLsMlXwNSJhM04bDcRuS4yzi+HnSvNZvPyxsaGRn05/Au5mNewzDAZ2AAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Service Bus Price&quot;
        title=&quot;&quot;
        src=&quot;/static/39572bd825f58374a8d11c70a091bc46/5aae9/ServiceBusPrice.png&quot;
        srcset=&quot;/static/39572bd825f58374a8d11c70a091bc46/4edbd/ServiceBusPrice.png 175w,
/static/39572bd825f58374a8d11c70a091bc46/13ae7/ServiceBusPrice.png 350w,
/static/39572bd825f58374a8d11c70a091bc46/5aae9/ServiceBusPrice.png 610w&quot;
        sizes=&quot;(max-width: 610px) 100vw, 610px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h3 id=&quot;setting-up-azure-service-bus&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#setting-up-azure-service-bus&quot; aria-label=&quot;setting up azure service bus permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Setting up Azure service bus&lt;/h3&gt;
&lt;p&gt;To set up a new Service Bus, we need to create a new &lt;strong&gt;Service Bus&lt;/strong&gt; resource in the Azure portal and set up a new Queue for incoming messages.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 698px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/3ff466383c23a2c0243a683024040b5d/487bb/ServiceBusQueue.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 89.71428571428571%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAYAAABb0P4QAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB20lEQVR42qWUXYvUMBSG+9e89drrxf/lByLsjftDRBAEb1aRZdyZdaDTNknz0TRJ29dzMtOx4KDs9sBLOu3Jc76SKZ692uD5uy2ubva4+vALL653eHnzgLefKrz+eCCVJx3w5vT8/rPA9Rd1UYXyA6Tx2AuDXWUhtUepPLaVg3I9fBpJE/oB6Gn1Cfl3Fy+r+Fp63P58wP3dD9xv7vD92y3quoaoKlSHEilGPMYK10e02qBVCsZYWGsRCTIMQ3ZIw5ihYaAs+4BxHP8D7DwkwbQxCCHmDawQQpYPiQIZWiO01ujp3TRNZz8OPD+zitIEKNXCOZcjsDMbZ1rXDZz39F1CtYpWRVn252CXVNQ2ZaCQIkNjTBnIWTVNA0trJMdlsKVZa9B13Z+SraIeKo2YUo6QTr1joBANtB8hbMTMYuisuRJPVczfCmccpJSUiYWzDob61Lku91QIkR3HC5nNtoQfh0JlGorCDZ3G6TxFswBO/wD+NWXv6Mw1NfXB5x76zq8Dap4iTbARx6GklNYBW3vsIR8J3er1QEuXUwqJlmDz4VwFVG7I2fH4l5ufDHT0N2Kp7HnTaqCSXG57vpfcQwbwuycBN/sDdrst6qqkGyOgZJMl6SjxvX2s/QbnzHVqTf6LzgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Service Bus Queue&quot;
        title=&quot;&quot;
        src=&quot;/static/3ff466383c23a2c0243a683024040b5d/487bb/ServiceBusQueue.png&quot;
        srcset=&quot;/static/3ff466383c23a2c0243a683024040b5d/4edbd/ServiceBusQueue.png 175w,
/static/3ff466383c23a2c0243a683024040b5d/13ae7/ServiceBusQueue.png 350w,
/static/3ff466383c23a2c0243a683024040b5d/487bb/ServiceBusQueue.png 698w&quot;
        sizes=&quot;(max-width: 698px) 100vw, 698px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Then go to the &lt;strong&gt;Shared access policies&lt;/strong&gt; menu and create a new access key for the Service Bus. Copy &lt;strong&gt;Primary Connection String&lt;/strong&gt; for this key.&lt;/p&gt;
&lt;p&gt;Then you may install and run  &lt;strong&gt;ServiceBusExplorer&lt;/strong&gt;, a handy utility to manage Service Bus from a local computer
&lt;a href=&quot;https://github.com/paolosalvatori/ServiceBusExplorer/releases&quot;&gt;https://github.com/paolosalvatori/ServiceBusExplorer/releases&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/79d29c7c98d56ff96667193cb5e8c8ea/79e48/ServiceBusExplorer.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 54.85714285714286%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB8klEQVR42oWSi27aQBBF/f+/0P+gSVq1oZAEcMDgJ7bX+IXfQGzzVKDcjpeQVqqUrHw0q5nV3TuzFlhYwPEiIgHzYrhhhmp7RL07vXFE1cBzxP70IUJXS/GkJxjZGSSW4VGL0JbneFBjijEe9QyilaNvUk1P0VGiC+qVGF2iiU1ecKISI9XD2HIhmjE0J0KYFFhVWzhJjY4coKsEeJB9tKUZ+lO63FliyBYc0S4woAtFq+B5od7/xrbM0Rpo+CLWMPIDrmtRHzB2FriXXOj+EmZUwYpr2MmaR2NeoT0J8FPy8UsO+RlhczjR/ELYFsN2XXOh8/kimFcHTEiwJ5mwwyW8rIabVvDSmu9Vb4VnzYPipJDtCJJJLW/2RxTlFuvNjpT4hzc9LjgiwW9DD7fPHr4OZmj1HbR6DAMzgeqX+CEFuKParejyulDtXi+u8Hdd91l5gOwuMfVzGF5G802IGAqLoDqN4AvPGd6lrrDkH8Hz+T/BxqFEg75pnJGrnpFiGq2hz5v51VBI8PvIxw25E60Msrf82CFvmeXoSA6eFB9jVkALKqLEZLbg7nU3hU4Om9i4/rTlyayAwUKwMMe8WL9j0gurJHxPr3wnzuiXI/fz8jPBPc1phambwApyet3qHT14oZZLjHUHw8kUY9Wmi338AbUeKz3RMtKsAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Service Bus Explorer&quot;
        title=&quot;&quot;
        src=&quot;/static/79d29c7c98d56ff96667193cb5e8c8ea/8c557/ServiceBusExplorer.png&quot;
        srcset=&quot;/static/79d29c7c98d56ff96667193cb5e8c8ea/4edbd/ServiceBusExplorer.png 175w,
/static/79d29c7c98d56ff96667193cb5e8c8ea/13ae7/ServiceBusExplorer.png 350w,
/static/79d29c7c98d56ff96667193cb5e8c8ea/8c557/ServiceBusExplorer.png 700w,
/static/79d29c7c98d56ff96667193cb5e8c8ea/79e48/ServiceBusExplorer.png 865w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;solution-description&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#solution-description&quot; aria-label=&quot;solution description permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Solution description&lt;/h2&gt;
&lt;p&gt;In this blog post, I try to describe a solution(with &quot;Consuming external web services&quot; &lt;a href=&quot;https://devblog.sertanyaman.com/2020/08/21/how-to-integrate-with-d365-for-finance-and-operations/#Consuming_external_web_services&quot;&gt;type&lt;/a&gt;) for a D365FO Custom Service that will talk to the Integration Platform. It will do the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Process sales orders for different companies.&lt;/li&gt;
&lt;li&gt;Avoid issues that OData has with bulk sales orders import like throttling.&lt;/li&gt;
&lt;li&gt;Avoid issues that DMF has with monitoring of failed batch imports and rollback of partial failures.&lt;/li&gt;
&lt;li&gt;Read a custom data format in the Azure Service Bus queue as messages (sourced from an external program).&lt;/li&gt;
&lt;li&gt;Provide a solution to log and monitor the failures easily.&lt;/li&gt;
&lt;li&gt;Perform custom transformations within D365FO as part of the import.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The first step for building such integration is to create a mapping document. I put a sample template here - &lt;a href=&quot;https://github.com/TrudAX/TRUDScripts/tree/master/Documents/Integration&quot;&gt;Field Mapping sample&lt;/a&gt;. For this post, the format for Sales order will be a simple custom JSON document that describes the sales order header and lines.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;CompanyId&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;USMF&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;customerId&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;US-002&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;externalOrderNumber&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;ABCDEFG&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;lines&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;lineQuantity&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;linePrice&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;11&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;lineItemBarcode&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;M0001&quot;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;lineQuantity&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;linePrice&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;22&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;lineItemBarcode&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;M0004&quot;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;lineQuantity&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;linePrice&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;33&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;lineItemBarcode&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;M0007&quot;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Our integration should read messages from the Service Bus queue and create sales orders in D365FO.&lt;/p&gt;
&lt;p&gt;The diagram that describes the process is below:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 663px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/dc759a87934c4d6b0de674237821a34c/0786c/SolutionDiagram.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 93.14285714285714%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAACXBIWXMAAA7EAAAOxAGVKw4bAAACRklEQVR42o2UyW7bMBCG9WJ9gj5SHyKnvkEORXvpseixRVHAycGoUxtegtiKLGuLNmuzKOkPf9o0HG/IAAOC1PDjzPykjLZtQW+aRrme07uuQ15WWHohgpcQphNgnZeQH05itRvXgE0joY3AyArx7d7C/aMPUW/Oxu6B+qMQQrmeb9ca0EZ+gduBh56VqrnYxR/GajdYlnZdJkdaJct98T38mz3jy+//6I0tBJ6LJE1VnM7ycK/h+z5c14XneUiSBEVRSFABL07xbHvI12vESQpzGaAscqQSpmKqSnlZlmpOz/MchuM4CrharbCWm5V1LZy0xJ/hDGUWovdU4ePnCHdPBUSVyXgPQRCoJMIwVJnRCDfqusaxtWyB7N+PBxNuuoYdd/j0PUZvLnia7OHbm6CNGRubzWab1MEHWiODa7Ht5aPf4OZnhDCTQkiVC5lJuXOWyl6eZHgojoY37Xb8NRP4cJPg651sSZ0jjBLV7ziOVcmacbFkbTppJxa4/Zti6oo368emSo6iSIlCcSgMVc+yTJ1GkfK8QBQGWMwe4K6sXTan1eyBhC2XSywWCzXatq3ALIcjDyTYsuWaLLMR4mJFCshe6KenlSNAX271MiSEcGZ9zRSQKrEMqk3nIrOcz+fqnnGN88FgANM0Ffwq8FgUZsYeMkseRgBfANXkur4i7waeMwKZMYHdJYmvAQ9/EISMx2NMp1MMh0Ml0rmH8O4MKcRkMkG/38doNNq/94tAbmCf2HzCj51B/MNQII6cn4sjgz1/BYfYwW+i/yFNAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Solution diagram&quot;
        title=&quot;&quot;
        src=&quot;/static/dc759a87934c4d6b0de674237821a34c/0786c/SolutionDiagram.png&quot;
        srcset=&quot;/static/dc759a87934c4d6b0de674237821a34c/4edbd/SolutionDiagram.png 175w,
/static/dc759a87934c4d6b0de674237821a34c/13ae7/SolutionDiagram.png 350w,
/static/dc759a87934c4d6b0de674237821a34c/0786c/SolutionDiagram.png 663w&quot;
        sizes=&quot;(max-width: 663px) 100vw, 663px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;proposed-solution&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#proposed-solution&quot; aria-label=&quot;proposed solution permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Proposed solution&lt;/h2&gt;
&lt;p&gt;In the following section, I provide a solution that can be used as a starting point to import and to process messages from Azure Service Bus.&lt;/p&gt;
&lt;h3 id=&quot;connection-types-form&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#connection-types-form&quot; aria-label=&quot;connection types form permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Connection types form&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Connection types&lt;/strong&gt; form allows specifying the Connection type resource(currently two resources are supported: Azure file share and Azure Service Bus) and connection details for the selected resource.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/85f10098911194d8d2946125d84c89df/7131f/ConnectionTypesForm.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 37.714285714285715%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABPElEQVR42p1S23KDIBT0/7+nH9KXTJ5SNfEGKkRBFBC3B22TPHTamTKzwwLDsmcPSXufkTID1k+Qw4C2FxhGDWsD/Brg/ErcYllmOJqNMVhm4s5hXdcD3j+QnCuPt3eLbqSLfoOxB6YlYJo3aOMg+h5NU6PvONqWQYgeWilM+sBsJnrE7EjSK0OWV2g6DakDqlbhkjW45BwNuVYkWBQ5zucT6rqGGkeMwx0d58iyFGmaghOPrrXWSPJ6wI2p3aHQG7i0KGhdcgUmLMbJkYAEY4zctRjJWSw3lr/Pzu6RfPNk2zb8NmIuUkoUZbk7LIoSnvbiiFcPbA8kIQS8aj4PvwRXT5kJEirAqLTItabMlgU/mfnbIXWx6zp8UFbX2w13+gmxITNl9i/BWN5ATeAt34U5ZVlXJe0Nz2/zgk+AVGsQx+mHpQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Connection types&quot;
        title=&quot;&quot;
        src=&quot;/static/85f10098911194d8d2946125d84c89df/8c557/ConnectionTypesForm.png&quot;
        srcset=&quot;/static/85f10098911194d8d2946125d84c89df/4edbd/ConnectionTypesForm.png 175w,
/static/85f10098911194d8d2946125d84c89df/13ae7/ConnectionTypesForm.png 350w,
/static/85f10098911194d8d2946125d84c89df/8c557/ConnectionTypesForm.png 700w,
/static/85f10098911194d8d2946125d84c89df/7131f/ConnectionTypesForm.png 710w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;For storing connection string, there can be two options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Enter the value in this form&lt;/li&gt;
&lt;li&gt;Store the connection string value as a Secret in the &lt;strong&gt;Azure Key Vault&lt;/strong&gt;. In this case, the user needs to provide a reference to the standard Key Vault name (steps to set up it are described in the following post: &lt;a href=&quot;https://jatomas.com/en/2020/06/02/azure-key-vault-msdyn365fo-setup-certificates-passwords/&quot;&gt;Azure Key Vault &amp;#x26; MSDyn365FO: Setup Certificates and Passwords&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;inbound-message-types-form&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#inbound-message-types-form&quot; aria-label=&quot;inbound message types form permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Inbound message types form&lt;/h3&gt;
&lt;p&gt;The next form to describe our integration will be the &lt;strong&gt;Inbound message types&lt;/strong&gt; form&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/0a1d1e5ad8ec7f908434a55c4c6547d9/c483d/MessageTypesForm.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 58.85714285714286%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAA7EAAAOxAGVKw4bAAABn0lEQVR42o1T0XKcMAzk//8iX9AP6WumT8kNlx4YYxsMGBuDYSuZkOlLm9PMzpwlbi3tyoXpHawd0FsHbSzGcYAxHewwYJomaK1yztoeSil0xkBpDe8D1nXFvickwrZtSIRCtRLb6qm4YAmefkfsiYtrPscloK4e+P1xh2wEGlETqYaUAsF76G6CokbWuORvi0fd4eXHT7y+SdzFgEoFtDZBmIjbw6IbAhHVmXSwFs45+HnGTIiLRykcHs2ItIbcVDGHiF83jW6MiAnw8fhCWIFl2dB3BhMRcRz7TmMSUqIadRUjjuPIuePYUSQq/C+43rYtmlZhobH4fGJDXVeohcj6sZ6cz4R0wT+D9VS6x+2jxTCOuaMQQiZhc6SU0GQWXzrP7vsO2UVBnby9v+cR+fvT3f2UgLq5wPHUyH1PK0MjWzLFU3dMzB3+TbZ/avs0YUMro7Sh8/lHzjs30Y6O2TC+4GlC1qe8l18GnFLsqKoKZVlCUv2Kbwk3WnDGRX4Frw+b1JMMLMHThGxA5HX5fFoXNsrzkvPInl4M7yU/vT+IkKXyhWVSlQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Message type&quot;
        title=&quot;&quot;
        src=&quot;/static/0a1d1e5ad8ec7f908434a55c4c6547d9/8c557/MessageTypesForm.png&quot;
        srcset=&quot;/static/0a1d1e5ad8ec7f908434a55c4c6547d9/4edbd/MessageTypesForm.png 175w,
/static/0a1d1e5ad8ec7f908434a55c4c6547d9/13ae7/MessageTypesForm.png 350w,
/static/0a1d1e5ad8ec7f908434a55c4c6547d9/8c557/MessageTypesForm.png 700w,
/static/0a1d1e5ad8ec7f908434a55c4c6547d9/c483d/MessageTypesForm.png 751w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;This form contains 3 main sections:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1 - Details tab&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Defines Service Bus connection and a Queue name from which to import messages.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Contains a link to the custom Class that will do processing from the queue. The class should extend the base class &lt;strong&gt;DEVIntegProcessMessageBase&lt;/strong&gt; and implement the following method:&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;c#&quot;&gt;&lt;pre class=&quot;language-c#&quot;&gt;&lt;code class=&quot;language-c#&quot;&gt;abstract void  processMessage(DEVIntegMessageTable  _messageTable, DEVIntegMessageProcessResult _messageProcessResult)
{
...
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This method will be called by the integration engine outside of a transaction, so all transaction control can be implemented per Message type. There can be different options here: one transaction per message, multiple transactions(for example, if a file contains several independent journals) or a single transaction per line. The result of processing and the current stage should be written to &lt;strong&gt;_messageProcessResult&lt;/strong&gt; variable, so in case of an unhandled exception, this information can be saved for reviewing. Also, this class will be created one time per entire import session, so it can implement different caching options.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2 - Operation parameters tab&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Contains parameters that are individual for the current operation. In our case, we don&apos;t have any parameters.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3 - Advanced settings tab&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Contains some common parameters:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The number of parallel threads to process incoming messages.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Reading limits from the queue(e.g. to read only the first three messages, this is for testing purposes)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Also, this form contains two service operations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Check connection&lt;/strong&gt; button that tries to connect to the specified queue and read(with Peak only) the first three messages.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Import message&lt;/strong&gt; button that can be used in testing scenarios to manually import a message from a user computer without connecting to Service Bus.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;incoming-messages-form&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#incoming-messages-form&quot; aria-label=&quot;incoming messages form permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Incoming messages form&lt;/h3&gt;
&lt;p&gt;This table will store the details of each incoming message.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/cea5f67c9e16c1a09d7a3ed66c362aa4/1568e/MessagesForm.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 31.428571428571427%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABCUlEQVR42nWPy26DMBBF8//f1HV3XXVTqU0CJE0BYwzYGDCP0wGiSk3VkY7nYc/V9cE6T1Hk3G6ZZIUxJWWpqauKvu/ovMc2Ddbu9H3PGMK/HKZx5JLExNGZJI5F+JPT6YgR0VXMOye5/cG3jtbtrPVjfxhFUCmFc1aGVgQsUxgYxF0YOphHwr0eek8IHeOwutzZ7u6ztT5M08g1rcmKhsYNpLlBG4fzgVw7Xl4jqtqhygZTe/JC3qpKMFJXVE239UrX2Hb78kSmW6JrQelmrlnNMc5IbiXvsebp+W0T101A1YHTRZF8GY5JzkeUkmrPWXbXnYsY2xzO8wQs7CF5mVkEOfgbywO/Z9/xT81FeADIzAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Messages form&quot;
        title=&quot;&quot;
        src=&quot;/static/cea5f67c9e16c1a09d7a3ed66c362aa4/8c557/MessagesForm.png&quot;
        srcset=&quot;/static/cea5f67c9e16c1a09d7a3ed66c362aa4/4edbd/MessagesForm.png 175w,
/static/cea5f67c9e16c1a09d7a3ed66c362aa4/13ae7/MessagesForm.png 350w,
/static/cea5f67c9e16c1a09d7a3ed66c362aa4/8c557/MessagesForm.png 700w,
/static/cea5f67c9e16c1a09d7a3ed66c362aa4/1568e/MessagesForm.png 892w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Every message has a status field that can contain the following values:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Ready&lt;/strong&gt; – a message was read to D365FO&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hold&lt;/strong&gt; – The user has decided not to process the message. This is an alternative to a delete option&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;In process&lt;/strong&gt; – system-generated status, a message is processing now.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Error&lt;/strong&gt; – failed validation or errors during the processing&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Processed&lt;/strong&gt; – completed successfully&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In this form, it is also possible to do the following operations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;View incoming message context&lt;/li&gt;
&lt;li&gt;Filter by different statuses&lt;/li&gt;
&lt;li&gt;View a detailed error message&lt;/li&gt;
&lt;li&gt;Change the status to process the message again&lt;/li&gt;
&lt;li&gt;View file processing statistics (processing duration, time, number of lines)&lt;/li&gt;
&lt;li&gt;View the processing attempt counter. This allows implementing scenarios like trying to process messages with “Error” status several times.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;load-incoming-messages-operation&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#load-incoming-messages-operation&quot; aria-label=&quot;load incoming messages operation permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Load incoming messages operation&lt;/h3&gt;
&lt;p&gt;It is a periodic batch job that we can run for one or multiple message types.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 375px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/7a5e60df43f0fe695ca694346285fe24/5ff7e/LoadIncomingFiles.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 81.71428571428572%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAYAAAAWGF8bAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABlUlEQVR42pVU127DMAz0/39Qv6EvLfqSpln1TOQh78TxkHQVlQnEzSBwoCyIpyMp2ur7HlVVIc8zjRxlUYBzftzLUejvLMvQti2eMatpGqzXa4RhiM1mA8YYXNdFEARm3/M9zOdz1HVtApRS9wlPi0cHnzVLCGGUEUgZKSaTUplLrnG+/JFCMfRQcjBe6gvumhKaXICEDMNwk5kl9cYqSDFzIizcGAFL0fbAvlOoGwkhTyU5+M95hq+fCCmPEUXROaMTsUVu5TWYzkpMFjV4JVHuDmBpq8kPjPJI+Paxx/usQ7MtjMLRlA27gTSByhCoM8lI3jd1vaSscwpDhjBiiOMIPEngeS7KshjtvpSX9P9tSrkbwMse+1bogEOxxaPm3COsmx4b3iKvWk00GEKaIJqOsTrdJZS6bp7nwHdtOPYvbNvGcrmA7/tmWmiCXnn4Fh2kcXMcF7vd1ijsus4oHHtnT6U8/Z7A1epSniDRjSHEcWymh8hfIiQFFHRCf7UmvKyQuklqEv1cyDMWmtqROvqNvdrlP0IL5Arv1QSXAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Load incoming files&quot;
        title=&quot;&quot;
        src=&quot;/static/7a5e60df43f0fe695ca694346285fe24/5ff7e/LoadIncomingFiles.png&quot;
        srcset=&quot;/static/7a5e60df43f0fe695ca694346285fe24/4edbd/LoadIncomingFiles.png 175w,
/static/7a5e60df43f0fe695ca694346285fe24/13ae7/LoadIncomingFiles.png 350w,
/static/7a5e60df43f0fe695ca694346285fe24/5ff7e/LoadIncomingFiles.png 375w&quot;
        sizes=&quot;(max-width: 375px) 100vw, 375px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;It connects to the Service Bus, reads messages(with Peek&amp;#x26;Delete type), creates a record in the &lt;strong&gt;Incoming messages&lt;/strong&gt; table with &lt;strong&gt;Ready&lt;/strong&gt; status and attaches a message content to this record. If &lt;strong&gt;Run processing&lt;/strong&gt; is selected, the load system will execute the processing of the loaded messages.&lt;/p&gt;
&lt;h3 id=&quot;process-incoming-messages&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#process-incoming-messages&quot; aria-label=&quot;process incoming messages permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Process incoming messages&lt;/h3&gt;
&lt;p&gt;Message processing may be executed as a separate operation - &lt;strong&gt;Process incoming messages&lt;/strong&gt; that selects all not processed messages and calls the processing class for them.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 336px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/dc20385a6bfc79771ed86f28013252cc/d99f2/ProcessIncomingMessages.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 90.28571428571429%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAYAAABb0P4QAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABfUlEQVR42qVU2W6DMBDM//9cVFVqCFc4AsQGCuLGHFOvW/JQNShOkZZdG3s8uzv4ME0T2rbFMAzK+r5XnuYoFkKg67r7/DiO2HsOdV3Dtm1lruvC933lTdOEZVn3ecMwcDweEQTBPuDex3Vdlf2OdwGXZUGapsjzHJxzlGX5EOwpQHpVVYWiKJBlmYr/89wBiVn947fCP8Poz5Qp1dvtBsYYmPTUqK3jdACt0QKkzeSnecYsjaRCLMm+AWe9lIkJaa3rehVvYwKmA7RTTuJIphzLdGOVfizHnndRzHVrqRg2w4K8mlH3epp7DNgJ8EIgykZVL0pzfVU2xOQaBvAvDqzzB87GCa5jS9DpVYYrGM+R8E/0YoWQPZikSmZJcZCY46yrQ7nxZIV4e5fMvAiWE8B2A5i2D56VSLJWykmjKbSU5Q0cL0bMC4RxCu/K4PoJ8rJFUUnpLKteDZumUSIm7ZFUNr/didpNIe0xzpCSl78f3XnXMEQURerS0NHiF1KJgb4m+1nnAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Process messages&quot;
        title=&quot;&quot;
        src=&quot;/static/dc20385a6bfc79771ed86f28013252cc/d99f2/ProcessIncomingMessages.png&quot;
        srcset=&quot;/static/dc20385a6bfc79771ed86f28013252cc/4edbd/ProcessIncomingMessages.png 175w,
/static/dc20385a6bfc79771ed86f28013252cc/d99f2/ProcessIncomingMessages.png 336w&quot;
        sizes=&quot;(max-width: 336px) 100vw, 336px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The logic of how to process the file is different per message type/class. For a simple scenario, the class can just read the message content and create some data in one transaction. For this blog post, I implemented two-step processing. See the sample diagram below:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/1d5e89221fed4418fd226ca267fe8495/a1792/ProcessDiagram.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 74.28571428571428%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABf0lEQVR42o2U3Y6CUAyEef/nUy+4ADSKgoCKooJozddkyMmuWfdiPH/ttNMWo+PxaFVV2X6/t+12a2VZWl3Xfu773sHdZrOx9Xo9Ybfb2eVysXEcJzweD4vO57N1XWdt21qe505+vV79zHo6naxpGkvT1ObzuS0WCwcBb7ebPZ/PCZBGh8PBHwGZQVgUhZ8JBikBISUgmWFDdrz9IiQDpGIsIA+ZckI2ewICAnF3v99dpuS6ZAg/gcxxHIbBDRUY8AZZaEdA+hHxs1qtLMsyX5fLpa9AhED1hIDacUY6SiiRGhvx+BNEl1TkiAAHdRcbAr1eL3/Hln0k7Z9AoXHEmKbMZjOL49hrTCCahY0IvSnhHKlT4ZkscFRjtCdjiJQhdth/JcSZziI1SRKfR80rAZThRBhKDNuvsxqCEySALFVrMtTZJf9FGN7hTEfJDgLOqq/K8LWGupN0Rgb5IgPKVPZfa8iqL4K5ZG7Za+CxQfa/CXGERF8JQ8zYhH8Ooc8bQguGW0NCYHIAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Process diagram&quot;
        title=&quot;&quot;
        src=&quot;/static/1d5e89221fed4418fd226ca267fe8495/8c557/ProcessDiagram.png&quot;
        srcset=&quot;/static/1d5e89221fed4418fd226ca267fe8495/4edbd/ProcessDiagram.png 175w,
/static/1d5e89221fed4418fd226ca267fe8495/13ae7/ProcessDiagram.png 350w,
/static/1d5e89221fed4418fd226ca267fe8495/8c557/ProcessDiagram.png 700w,
/static/1d5e89221fed4418fd226ca267fe8495/a1792/ProcessDiagram.png 780w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;During the first step, the class reads the message data and writes data into a staging table. A sample code for this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;c#&quot;&gt;&lt;pre class=&quot;language-c#&quot;&gt;&lt;code class=&quot;language-c#&quot;&gt;tutorialSOHeaderContract = FormJsonSerializer::deserializeObject(classNum(DEVIntegTutorialSOHeaderContract), serializedJSONstr);
 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then based on the staging data values, a new sales order is created. It can be done using data entities or just directly writing to tables.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;c#&quot;&gt;&lt;pre class=&quot;language-c#&quot;&gt;&lt;code class=&quot;language-c#&quot;&gt;salesLine.initValue();
salesLine.ItemId = salesLineStaging.ItemId;
salesLine.initFromSalesTable(salesTable);
salesLine.initFromInventTable(InventTable::find(salesLine.ItemId));
salesLine.SalesQty              = salesLineStaging.SalesQty;
salesLine.QtyOrdered            = SalesLine.calcQtyOrdered();
salesLine.SalesDeliverNow       = salesLine.SalesQty;
salesLine.setInventDeliverNow();
...
salesLine.createLine(true,false,false,true);&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;error-types-and-how-to-handle-them&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#error-types-and-how-to-handle-them&quot; aria-label=&quot;error types and how to handle them permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Error types and how to handle them&lt;/h2&gt;
&lt;p&gt;It is not a big task to create a sales order based on some data. The complexity of integration is often related to exception processing and error monitoring. Let&apos;s discuss typical errors and how users can deal with them.&lt;/p&gt;
&lt;h3 id=&quot;connection-errors&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#connection-errors&quot; aria-label=&quot;connection errors permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Connection errors&lt;/h3&gt;
&lt;p&gt;A batch job exception will be generated if our batch job can&apos;t connect to a Service Bus or read messages. It is a configuration error, and it requires a system administrator&apos;s attention. Notification may be done using a batch job status. After troubleshooting, the system administrator can use the &lt;strong&gt;&quot;Test connection&quot;&lt;/strong&gt; button to validate that the system can now read messages from the Service Bus.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/a2920baf0e99fd333ceaf491805509f9/0f7d5/TestConnection.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 38.857142857142854%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABJ0lEQVR42pWR227CMBBE8/8/1edKFbTqAxIQQUMgFxw7cZx7nOmuCYhS+tCVjnZ2Y09GsrfxI2zTButAYLXaY+2fsI4KbGONTVw6vSEdyB5h3uOgOoJ6fsc8h8UA72Xh49UXeNspLMMSy4PBe1gR5sKxcvMi0Pg41g4+s5y/uXnWn1ELT4gMSilUpkLbdqjrhqghM4E4jnA+p5BSoCwL2hvSEn3XYeiZlnT7Q3tfpxyRqHE618i0RZQ1iGWFXEnoIkfXNmiaCj1dYJ0m8Z3Jb7xxtJgmuOLuNMGpjTG41jAMbsf9cnZ6ijdd3R5KZAq7gNLQX621zihJEqhcQeviZvxYfxpymiRJMZGZHcdbgpE0m9n/JOSdKUv3ALqgNPwIbMLmM2z8jG+qsWi6tXi3ogAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Test connection&quot;
        title=&quot;&quot;
        src=&quot;/static/a2920baf0e99fd333ceaf491805509f9/8c557/TestConnection.png&quot;
        srcset=&quot;/static/a2920baf0e99fd333ceaf491805509f9/4edbd/TestConnection.png 175w,
/static/a2920baf0e99fd333ceaf491805509f9/13ae7/TestConnection.png 350w,
/static/a2920baf0e99fd333ceaf491805509f9/8c557/TestConnection.png 700w,
/static/a2920baf0e99fd333ceaf491805509f9/0f7d5/TestConnection.png 993w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h3 id=&quot;file-format-errors&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#file-format-errors&quot; aria-label=&quot;file format errors permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;File format errors&lt;/h3&gt;
&lt;p&gt;The next error type is a wrong file format, so we can&apos;t even read the data from a message.&lt;/p&gt;
&lt;p&gt;To test this case, I renamed several columns. After the import, users will see this message with the Error status. Notification may be done using standard filtering by the &lt;strong&gt;Status&lt;/strong&gt; column.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/89aa452c7784aa01c9c5cfc303dc610f/42d54/WrongColumnError.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 69.71428571428572%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAByUlEQVR42qVSz0vcQBjN39VT8VQooiBtL1YUqRSqt5aC0EPB/QMEwYt3wZv4FxQ9eCmFnoTdbjetim4yyWR+J9nk+U0WFpdVd8HAYybMfG/e994XLK1+wZv1r3j1bgtzS5/wfquF5c0W3m58x8LaN8yvbOPl4kfML3/Gi9cfsLN7iJilkFJCCImqqnD/CzhP0O9H6EcxMsGRcY4kSWC0xqAoUZUlrC3AhYOQOXKXI0lTuh8190o696R1XQ8Jb2+u0Wm30fvbxdXVf4RhD//CEM4aWKNHyJ1BbjUcrUYpEtFvSGPGELEYPONEXCPwirIsg6RLKRfQ2hdbKrTNen/v7HBf0GM8YY1SRipZSqB/5xwCIznqUgGVRuEUqTHNweOwoxYfQvDjwmDvdID9sxIH5wPccu+TI6UOxkxCKEuF40GMhfI7VDg6j3D8k+PkF0f3MiKvFMoiJ7gJKG0nkh0jNGS4EzfQ6TUlKlFQkferyN2DmEqoqLWUzO1RsnHMyOzkUbKZCKUy0IqGlGL34/EU2UyE3uiEReh02ohprrIpCr2AqQqtlpAioxTNk/7NROgVpqTwT7dDSllD/KyWhVCNd0oKKPLS+/kcwjutaikAsgAswwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Wrong column error&quot;
        title=&quot;&quot;
        src=&quot;/static/89aa452c7784aa01c9c5cfc303dc610f/8c557/WrongColumnError.png&quot;
        srcset=&quot;/static/89aa452c7784aa01c9c5cfc303dc610f/4edbd/WrongColumnError.png 175w,
/static/89aa452c7784aa01c9c5cfc303dc610f/13ae7/WrongColumnError.png 350w,
/static/89aa452c7784aa01c9c5cfc303dc610f/8c557/WrongColumnError.png 700w,
/static/89aa452c7784aa01c9c5cfc303dc610f/42d54/WrongColumnError.png 858w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Users can view an error log, then download the message and check the reason for this error. There may be two reasons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Our code that processes messages contains some mistakes. In this case, we can download and send this message to a developer to fix the logic. The main advantage of this solution is that users can run processing without Service Bus by using the &lt;strong&gt;Import message&lt;/strong&gt; button.  After fixing the problem, we can run the Processing again.&lt;/li&gt;
&lt;li&gt;External system sent a message in the wrong format. In this case, the user can send this file back to the external party, then change the message status to &lt;strong&gt;Hold&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;data-errors&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#data-errors&quot; aria-label=&quot;data errors permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Data errors&lt;/h3&gt;
&lt;p&gt;The message has a correct structure but contains incorrect data(e.g. values that don&apos;t exist). In this case, a Status of our Message will be &lt;strong&gt;Error&lt;/strong&gt;, and an Error log will be generated.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/0f87e90682d3f0ff5e10ac70635a0e04/cab8c/WrongDataError.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 57.14285714285714%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABoElEQVR42pWSy2vbQBDG9ef3UvoIJaWGlpIQQgo+Fnor9NIeCj305MRO/FrZeqyk7T5nJX+ZVXop9GAvfMxK2v3NNzPKzj98wvvLKSYXU7yeXOP5mwu8fHuFV++u8WIyxbOzK3y8+YL5UqCWEvuihOR4wP9XprYCutjD8EFdVDh4D1AEAsE1Fqq0CFLBtO0IrOoKDe9jJFZEPwz/Ap11WK2WmM1mWC4fILYb7HYCm80asq7hrIE1Gt5ZdAwUuxwiz5GnyNoXBXwIIGJxkmzo+xHycH+P7XqDXAgIscVisUBZFgy0MFqDgoeqqhEgZQPnHCx/0ykZV2X52fOZrO8jlOqg9Z/xYtt2LIUDJ0qQ5Cy5TA6OWVnqQy1bGEucJUDpANmyK+P4nf8rdzyQGNg0CiUPpuISy7JE5MuRCIFLSS4T3PtjHXJpkh3O726x4qEkpd7VPM0Ei/Tk8Hhg7NEp7l9XYfAGA1kcIosMeobFcCKQ+J8zjvBzLvH5xwLfZx1+i4hfa8K+8RjiqSWnHiqHb3ceX2+JFXkfx7iqArs9DfgI25VJ+vftyCIAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Wrong Data Error&quot;
        title=&quot;&quot;
        src=&quot;/static/0f87e90682d3f0ff5e10ac70635a0e04/8c557/WrongDataError.png&quot;
        srcset=&quot;/static/0f87e90682d3f0ff5e10ac70635a0e04/4edbd/WrongDataError.png 175w,
/static/0f87e90682d3f0ff5e10ac70635a0e04/13ae7/WrongDataError.png 350w,
/static/0f87e90682d3f0ff5e10ac70635a0e04/8c557/WrongDataError.png 700w,
/static/0f87e90682d3f0ff5e10ac70635a0e04/cab8c/WrongDataError.png 744w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Users can view this error, display a &lt;strong&gt;Staging data&lt;/strong&gt; to check the values from the message and take some actions(e.g. create missing values in the related tables if they are valid). After that, they can Process this message again.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 644px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/cc105f43581156de8272c039e284496a/78274/WrongDataErrorStaging.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 67.42857142857143%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABnUlEQVR42q2T2ZKbMBBF9f+/l4cxNgzDAGIVuxCg5aahbMdOPJmHhKpTzVVLTdG3xaI4QVULFFWNlOeIU46S3rOyQpoV8C4+YlrPqwZl/T1MzRKntzeEYYjz+YQguODknXC5nJFxjr7v0QgBQUzTBL1tf4VN4wjP8+hwiiSJkRc5ougD7+E79ty2rliX5c5y5ZdWBzfNlJrp9xqsVN1ZA2M0nDMHRi9/YM0K+6Cd3Y61m2aTVEjylnpXYJQrxnlDmAj4UYlPLsDLAVFKPa0GyllEvMXlo0BKZwox4RwkCKIcZSPRSwPWjwppNaMbFKTSB1xsyBqNureoHtg1FxopUQ8WZWeQFBMysdz3sHVdAIf/9hwFnXuuuMuvvuGu+ae97rEgOaM3TWaYb9C/xdcwSbPF8wp6VTCbOuK/wOSsUDcT4qxB1c6Hk5UY6ZbQMHcz5OJQkuZ5c8Qkq9GP+zSYl7B2mBFmEj+CFn5KI0QOZq29Yu74SQ9OzvufHZJ6Rd4952+w/SZorel61dRc+9oI6rqUIyzlx3E4evWVyz8B6A/sJtIHxn4AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Staging error&quot;
        title=&quot;&quot;
        src=&quot;/static/cc105f43581156de8272c039e284496a/78274/WrongDataErrorStaging.png&quot;
        srcset=&quot;/static/cc105f43581156de8272c039e284496a/4edbd/WrongDataErrorStaging.png 175w,
/static/cc105f43581156de8272c039e284496a/13ae7/WrongDataErrorStaging.png 350w,
/static/cc105f43581156de8272c039e284496a/78274/WrongDataErrorStaging.png 644w&quot;
        sizes=&quot;(max-width: 644px) 100vw, 644px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;In some implementations(EDI), we can even allow staging data editing. A similar type of error is a posting error.&lt;/p&gt;
&lt;h3 id=&quot;wrong-result-errors&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#wrong-result-errors&quot; aria-label=&quot;wrong result errors permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Wrong result errors&lt;/h3&gt;
&lt;p&gt;That is probably the worst scenario. The message was processed successfully, but the resulting document contains some wrong data.&lt;/p&gt;
&lt;p&gt;To analyse the result, users can view the staging data and check that they are correct. Also, a message content can be sent to a developer, and they may trace the document processing using the manual Import message button&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/67c13f916cc20297c0f24df3cf6e3bdb/cc155/ManualImport.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 29.142857142857142%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABAElEQVR42n2Q60oDMRCF9/3fqtgqtfeCpdAfwgoVF7tNsrlsJpfjbFxFkRoYJjOc+XIm1XS+xeR+g7uHNSazFR43Byx3Ryy3R8zXT5gt9ljtDjDGQEoJpRT+O1UgQk6Jr3lsZeScECMhhB5EPYxWsNYwTCIV7ahk3c+6AC/CoJUOovPQLkFqD6EYYi3a9sJ5cCZwlR3Oby3Ie36EynBnHPc1eoocCdYRquHiAzjydxDXvWeo0WXQOcduI0JMnAO7j2OfcD6d8Fq/oGkayM6iuvUXnp0I0bGbUIC/V/3MUlnUzzWu7wKStdrSbeCwVssi6zwD7Z+/Gk5icvqil4cyPgCny9EAcq5yZQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Manual import&quot;
        title=&quot;&quot;
        src=&quot;/static/67c13f916cc20297c0f24df3cf6e3bdb/8c557/ManualImport.png&quot;
        srcset=&quot;/static/67c13f916cc20297c0f24df3cf6e3bdb/4edbd/ManualImport.png 175w,
/static/67c13f916cc20297c0f24df3cf6e3bdb/13ae7/ManualImport.png 350w,
/static/67c13f916cc20297c0f24df3cf6e3bdb/8c557/ManualImport.png 700w,
/static/67c13f916cc20297c0f24df3cf6e3bdb/cc155/ManualImport.png 886w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;dmf-integration&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#dmf-integration&quot; aria-label=&quot;dmf integration permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;DMF integration&lt;/h2&gt;
&lt;p&gt;The text above was for the custom-written integration, but the same engine may be used for importing data with the standard Data Management module.
The idea is the same as for the file integration - &lt;a href=&quot;https://denistrunin.com/xpptools-fileintegdmf&quot;&gt;Multicompany DMF integration in Dynamics 365 FinOps using X++&lt;/a&gt;, in the message parameters, we can specify a DMF processing class and the entity from the  Data management import project.&lt;/p&gt;
&lt;p&gt;This class connects to Service Bus, saves the message to a temporary file and executes Data management project import for this file. This allows you to use a full set of Data entities, settings and transformations that Data management can provide. Let&apos;s consider the simple scenario: Customer group import&lt;/p&gt;
&lt;p&gt;First you need to create an import project based on the sample XML&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;xml&quot;&gt;&lt;pre class=&quot;language-xml&quot;&gt;&lt;code class=&quot;language-xml&quot;&gt;&lt;span class=&quot;token prolog&quot;&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;Document&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
 &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;CUSTCUSTOMERGROUPENTITY&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;CUSTOMERGROUPID&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;MyTestGroup&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;CUSTOMERGROUPID&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;DESCRIPTION&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;MyTestGroup Description&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;DESCRIPTION&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
 &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;CUSTCUSTOMERGROUPENTITY&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;Document&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/4444aaa030c9b17adc40de171bf5623d/218a4/DMImportProject.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 45.714285714285715%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABWElEQVR42qWRy46cMBBF+f+/S1ajJE3T3dBgXsY8jQ2cKTvKKpuJUtJVgTHHt64TrQeyLCNNb7yeT+bRsNsNt9vYvbNoo6nqFlV3sZdVRVEqUYVqWtq2YxhnOrOSzPNEkPdOII7De3aBhR50Hgd1XZJ+fCP7+E55+4F6VzSiIm9oGk3XNjwrzaMwJMYMPB4ZWvdYcWS3TQ6YBbrjBLitKz9vKVn6JL9PFPeR8uWoX4ZOzZjeMgyeaXSy15Fs64YeJpbFslovUItzLsraXZx7cnGjlGJeIL3Dr9sph2iJoKbXAu68CPmHMPLMu6hY5pXjuAgVoKs4u67f7yGrWrIT8/KNuM/7i+uEi5M/FbZHoJKQh2FgniYmUSuZ5Hken0O2papj8F+pxElWwcl5nnG8Qy5hHEdxVIujLa69qwBsvwh0+1+LYVxjTDwkVPm/wOCs73u5qCXqX4CfhlC3qSjCx8cAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Data management import project&quot;
        title=&quot;&quot;
        src=&quot;/static/4444aaa030c9b17adc40de171bf5623d/8c557/DMImportProject.png&quot;
        srcset=&quot;/static/4444aaa030c9b17adc40de171bf5623d/4edbd/DMImportProject.png 175w,
/static/4444aaa030c9b17adc40de171bf5623d/13ae7/DMImportProject.png 350w,
/static/4444aaa030c9b17adc40de171bf5623d/8c557/DMImportProject.png 700w,
/static/4444aaa030c9b17adc40de171bf5623d/e996b/DMImportProject.png 1050w,
/static/4444aaa030c9b17adc40de171bf5623d/218a4/DMImportProject.png 1052w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Setup a new Inbound connection type(based on DMF class) and specify the link to the import project.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/a7d3e74f4d8be63f787d7be1f14ab7f6/17a7a/DMFProjectSetup.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 50.857142857142854%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABcUlEQVR42o1SCW6kMBDk/w+MJtlNJsAc5rAN5jD4qpQZRYpWu9oxKhraXUW5m0LqGeNoMBBKj3weGPWBaZogpYQxj7yUPbRS6GWHeVmwbxti9ESA9+5AUX2WJBrYdcG2WRZZhOAObHbFvm9oW4HLpYIQd9zFDVpLDIMiZ0avRtwaCce6zC3MNOOtVKgbi4+rQSlWiCFA6IDf9YhGWfRtg0Y0h8t5nrDSnV1Xiqy4tDNqYRC8hXcbCuc9XIgICYhEjj4+kN899wzbkY+fV0oJKUbEECi4U8g98sxlFJ6CuehfK6UIyb6V1RWGos7tRxsCBcu6wkdZYqHb3bGHwT8n2HMwp1819GCOATiSA3nd+RO30wm31xPU+Yy5654RTFB0WFclh2QPwT0flQ55QyL/iPxI9E84jOyLMYYTFpx2B0W3Wfhwyb1vRGrEZ3qYi/QwYLELB/Yg/3T/J/5/ZF5dfcX55R2TaNHXDdT1Dsd/92/rC9S+CaB6q18bAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;DMF inbound type&quot;
        title=&quot;&quot;
        src=&quot;/static/a7d3e74f4d8be63f787d7be1f14ab7f6/8c557/DMFProjectSetup.png&quot;
        srcset=&quot;/static/a7d3e74f4d8be63f787d7be1f14ab7f6/4edbd/DMFProjectSetup.png 175w,
/static/a7d3e74f4d8be63f787d7be1f14ab7f6/13ae7/DMFProjectSetup.png 350w,
/static/a7d3e74f4d8be63f787d7be1f14ab7f6/8c557/DMFProjectSetup.png 700w,
/static/a7d3e74f4d8be63f787d7be1f14ab7f6/17a7a/DMFProjectSetup.png 753w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Then load a message to our Service Bus queue and run the import&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/10493762c35ffb6bb7257e7048c0bf74/4ef40/SBSendXMLMessage.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 34.285714285714285%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAAA7EAAAOxAGVKw4bAAABYUlEQVR42nWQ627TQBCF/f4vAFSIPgA/m3L5UYk2QYKgUuILduxcbO/GWbtrZxMnoVVLPxarBYTakT7NnNnRkfY4ojQI1SArQ7xYEc4KIkuSl5TmyvLjUdQ9/++dvisZRku+RAWDQPHB6o++5MwVnLqLJ+l7C868ws7yn73EEYVhNkvQVUmyMHxNFMMg4zwSjCYlodhY1oRyw/eur/FzwzC+ZDiu8DPT7b3UENhbZ7Pdkk5idm1LrnfdY9/NOb2YE+Y102Vro1gzlubPHOQNxwOX1yfn9AZeF1G+rPHHKY42e1JZcnN9Rab39nhl86yRQjCOE0vMdDJFKUWjNWmhuZhawoxwbvNOFbJsWF4a61Ph3Nz+5KFya+hnDdq0NLVmnqZkWYYQEmMMW/sLoWo+RYrD9wGvfvPO5+CNx4uey8u3/mOGK9btvtN3/K27e1Gtdny2hgfHI54dfeP5A71R138Bit77fqLCDHEAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;SB Send XML&quot;
        title=&quot;&quot;
        src=&quot;/static/10493762c35ffb6bb7257e7048c0bf74/8c557/SBSendXMLMessage.png&quot;
        srcset=&quot;/static/10493762c35ffb6bb7257e7048c0bf74/4edbd/SBSendXMLMessage.png 175w,
/static/10493762c35ffb6bb7257e7048c0bf74/13ae7/SBSendXMLMessage.png 350w,
/static/10493762c35ffb6bb7257e7048c0bf74/8c557/SBSendXMLMessage.png 700w,
/static/10493762c35ffb6bb7257e7048c0bf74/e996b/SBSendXMLMessage.png 1050w,
/static/10493762c35ffb6bb7257e7048c0bf74/4ef40/SBSendXMLMessage.png 1057w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;As the result a new message will be created and after processing a new Customer group record will be created&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/6f8be562a11898f89e1c31733044e228/8ae3e/DMFResultCustGroup.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 53.14285714285714%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB6ElEQVR42oWS22rcMBCG3Yu+/3P4qnelbCEv0C2kJE02YU9ZZ21HPsk6y7L276w2gRJKOvDxo7E1I82vTBsFYy36QUFpBa01rQ3EOEIKAecdZNeiWq3A1hsMTQPOR3g/IcwB8zuy8viMm5tbrGjDdrtFcXjCZrPGoTjAO5dwRsNKkfDUfPIejvRfZP0g0CVkUi402l4ktA3EBO3OzBfMdMklwl96IatZHw/HNiqlohAyKqniNIVIV4rOuYT3PjrrorU2ra11r999UmsvOWtszKwP6LmiWQWcQ2mLUWqEeMJMnPNcmKRhniGVwel0opPSKGiO1nrEGPEW2b6SX++2/fffu2GxY3FxT3q9ekl6u+4W93u1WB30Ylt5wi3Wpfv2WNj8x22Z36z7/OddnV8/NPmvxzZ/KHSecS6/WKPJYF13HWdKEXJko+Ss71s2DB1r24aNfKjHceBhCsvlEp8zCjrQp+x9IOLKe4uieJrrqgR7qcCHDoaekxAjlJL0fCQ569K9Ypy3JB8VjFfneez2z3NZNyieq+Q4GYPT+W0FnwivBcPkPi5IHa8M/VuU/dxxA+NPUCai6UbUNUsmGRq8kCaeDWna7v8FBw1sSjNX/YR6CGCcGjCDddFjX0pC4Nj62Crg2E0fFvwDzQHY3dbCrTkAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;DMF result CustGroup&quot;
        title=&quot;&quot;
        src=&quot;/static/6f8be562a11898f89e1c31733044e228/8c557/DMFResultCustGroup.png&quot;
        srcset=&quot;/static/6f8be562a11898f89e1c31733044e228/4edbd/DMFResultCustGroup.png 175w,
/static/6f8be562a11898f89e1c31733044e228/13ae7/DMFResultCustGroup.png 350w,
/static/6f8be562a11898f89e1c31733044e228/8c557/DMFResultCustGroup.png 700w,
/static/6f8be562a11898f89e1c31733044e228/8ae3e/DMFResultCustGroup.png 756w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;You can even implement a more complex scenarios, for example, import sales orders by using Composite data entities - &lt;a href=&quot;http://mukesh-ax.blogspot.com/2018/07/dynamics-365-operations-composite-data.html&quot;&gt;Dynamics 365 Operations | Composite data entity – Sales order import (Only works with XML)&lt;/a&gt;. However, this is not something that is recommended by Microsoft:  &quot;Composite entities are not recommended&quot; from &lt;a href=&quot;https://community.dynamics.com/ax/b/axinthefield/posts/5-tips-to-improve-the-performance-in-a-dmf-import-project&quot;&gt;5 Tips to improve the performance in a DMF import project&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;summary&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#summary&quot; aria-label=&quot;summary permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Summary&lt;/h2&gt;
&lt;p&gt;I provided a sample implementation for an Azure Service Bus integration for D365FO. The main concept of it is to create a basic framework to simplify troubleshooting(most typical errors and all related data can be viewed in one form - Incoming messages) and provide some additional logging.&lt;/p&gt;
&lt;p&gt;This may or may not be appropriate in your case(there are different options how to implement this). Anyway, I recommend using the following checklist while designing the integration: &lt;a href=&quot;https://github.com/TrudAX/TRUDScripts/blob/master/Documents/Integration/Integration%20Data%20Flow%20Requirements.md&quot;&gt;Integration solution specification&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Files used for this post can be found in the following &lt;a href=&quot;https://github.com/TrudAX/XppTools#devexternalintegration-submodel&quot;&gt;folder&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I hope you find this information useful. As always, if you see any improvements, suggestions or have some questions about this work, don&apos;t hesitate to contact me.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Working with LedgerDimension values from posted transactions in D365FO]]></title><description><![CDATA[This post describes a case to consider while working with LedgerDimension values from posted transactions.]]></description><link>https://denistrunin.com/xpptutorial-postedledgerdim/</link><guid isPermaLink="false">https://denistrunin.com/xpptutorial-postedledgerdim/</guid><pubDate>Thu, 14 Oct 2021 22:12:03 GMT</pubDate><content:encoded>&lt;p&gt;Recently we faced and fixed an interesting bug. We had a custom procedure that reversed a posted ledger journal. The logic of this procedure is quite simple - take the existing values from &lt;strong&gt;LedgetDimension&lt;/strong&gt; fields for posted lines and create the same transactions but with the negative amount.&lt;/p&gt;
&lt;p&gt;So the simplified version of the code looked like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;debitAccount  &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ledgerJournalTransSource&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;LedgerDimension&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
creditAccount  &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ledgerJournalTransVariance&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;LedgerDimension&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//Do the posting using these account&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then suddenly it stopped working with the following error:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Ledger account with 511-323-300 with record ID 1111 does not match the current account and/or advanced rule structure associated with structure&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;After some troubleshooting, we found out that the customer recently had updated settings for Ledger account structures.&lt;/p&gt;
&lt;p&gt;In X++ a &lt;strong&gt;LedgerDimension&lt;/strong&gt; type is a reference to 3 entities:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Dimension structure&lt;/li&gt;
&lt;li&gt;Ledger default account&lt;/li&gt;
&lt;li&gt;Default dimension&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So the error basically said that we couldn&apos;t use the same Dimension structure again.&lt;/p&gt;
&lt;p&gt;The fix was quite simple - extract a &lt;strong&gt;Default account&lt;/strong&gt; and &lt;strong&gt;Default dimension&lt;/strong&gt; from the old &lt;strong&gt;LedgerDimension&lt;/strong&gt; value and create a new &lt;strong&gt;LedgerDimension&lt;/strong&gt; using these extracted values:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;
debitAccount  &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; LedgerDimensionFacade&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;serviceCreateLedgerDimension&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;              &lt;span class=&quot;token named-parameter punctuation&quot;&gt;LedgerDefaultAccountHelper&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getDefaultAccountFromLedgerDimension&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;DebitAccount&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token named-parameter punctuation&quot;&gt;LedgerDimensionFacade&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getDefaultDimensionFromLedgerDimension&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;DebitAccount&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

creditAccount  &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; LedgerDimensionFacade&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;serviceCreateLedgerDimension&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
&lt;span class=&quot;token named-parameter punctuation&quot;&gt;LedgerDefaultAccountHelper&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getDefaultAccountFromLedgerDimension&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;CreditAccount&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token named-parameter punctuation&quot;&gt;LedgerDimensionFacade&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getDefaultDimensionFromLedgerDimension&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;CreditAccount&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;After this change, the posting was successful. It was quite a tricky fix, hard to see at first.&lt;/p&gt;
&lt;p&gt;So, I am trying to maintain a helper class that contains references to common ledger dimension operations(like in this post), feel free to check it and comment if something is missing. &lt;a href=&quot;https://github.com/TrudAX/XppTools/blob/master/DEVCommon/DEVCommon/AxClass/DEVDimensionHelper.xml&quot;&gt;https://github.com/TrudAX/XppTools/blob/master/DEVCommon/DEVCommon/AxClass/DEVDimensionHelper.xml&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[D365FO Infolog call stack]]></title><description><![CDATA[This post describes an extension for the standard D365FO system that allows saving stack trace data for infolog messages.]]></description><link>https://denistrunin.com/xpptools-devinfocallstack/</link><guid isPermaLink="false">https://denistrunin.com/xpptools-devinfocallstack/</guid><pubDate>Fri, 24 Sep 2021 20:12:03 GMT</pubDate><content:encoded>&lt;p&gt;Infolog is a primary message display system in Dynamics 365 FO. And &apos;&lt;strong&gt;infolog.add()&lt;/strong&gt;&apos; is probably the most favourite place for developers to insert breakpoints. The reason for this is that the source of some messages may be unclear and you need to use the debugger to understand the reason for a particular message.&lt;/p&gt;
&lt;p&gt;In this post, I describe an X++ utility that saves stack traces for every infolog message. It allows, in some cases, understanding the source of the message without debugging.
The idea of this post is based on the following post on &lt;a href=&quot;http://axforum.info/forums/showthread.php?t=78119&quot;&gt;AxForum&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;functional-description&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#functional-description&quot; aria-label=&quot;functional description permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Functional description&lt;/h3&gt;
&lt;p&gt;In order to display the last infolog messages, a new form was created in &lt;em&gt;&lt;strong&gt;System administration - Inquiries - DEV Tools - Call stack&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The form has 2 tabs:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Data tab&lt;/strong&gt; that displays saved infolog messages and X++ call stack for the current message&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/b607d41687e67d9fd9ababd025fe62c9/ec821/DevCallStackInfoMain.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 61.71428571428571%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAMABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAEDAgX/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIQAxAAAAHruyJGw//EABkQAAIDAQAAAAAAAAAAAAAAAAACAQMSIP/aAAgBAQABBQKVrgwhhOP/xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAaEAABBQEAAAAAAAAAAAAAAAAAAQIgMpEh/9oACAEBAAY/Auo0q3CiZD//xAAaEAEAAgMBAAAAAAAAAAAAAAABABEQMXHx/9oACAEBAAE/IR7F0JaWMcTxUdRMf//aAAwDAQACAAMAAAAQuM//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/ED//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/ED//xAAeEAADAAEEAwAAAAAAAAAAAAAAAREhMUFxkbHB8P/aAAgBAQABPxBBWrKkRmhumVdH1XoVPJCmppwSY8n/2Q==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Main view&quot;
        title=&quot;&quot;
        src=&quot;/static/b607d41687e67d9fd9ababd025fe62c9/29d31/DevCallStackInfoMain.jpg&quot;
        srcset=&quot;/static/b607d41687e67d9fd9ababd025fe62c9/e52aa/DevCallStackInfoMain.jpg 175w,
/static/b607d41687e67d9fd9ababd025fe62c9/70ebb/DevCallStackInfoMain.jpg 350w,
/static/b607d41687e67d9fd9ababd025fe62c9/29d31/DevCallStackInfoMain.jpg 700w,
/static/b607d41687e67d9fd9ababd025fe62c9/ec821/DevCallStackInfoMain.jpg 1030w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Setup tab&lt;/strong&gt; that allows setting up a logging level per user. You can also setup logging to all users for Warning and Error messages&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 627px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/0e37124912a8fada0e752ab1759d4561/362f5/DevCallStackInfoSetup.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 73.14285714285714%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAEDBf/EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAAdZ2RIsH/8QAGBAAAwEBAAAAAAAAAAAAAAAAAAMTEBH/2gAIAQEAAQUCisioio5v/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAGBAAAwEBAAAAAAAAAAAAAAAAAjORACD/2gAIAQEABj8CWMyxmWM4/8QAGhAAAwADAQAAAAAAAAAAAAAAAAEREDHx4f/aAAgBAQABPyHjBeKOfIuhJSY//9oADAMBAAIAAwAAABAwz//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8QP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8QP//EAB0QAAICAQUAAAAAAAAAAAAAAAERACExQXGBkdH/2gAIAQEAAT8QYUTrSBQfdJ9nl8JQQAbQBToYiAwFP//Z&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Setup view&quot;
        title=&quot;&quot;
        src=&quot;/static/0e37124912a8fada0e752ab1759d4561/362f5/DevCallStackInfoSetup.jpg&quot;
        srcset=&quot;/static/0e37124912a8fada0e752ab1759d4561/e52aa/DevCallStackInfoSetup.jpg 175w,
/static/0e37124912a8fada0e752ab1759d4561/70ebb/DevCallStackInfoSetup.jpg 350w,
/static/0e37124912a8fada0e752ab1759d4561/362f5/DevCallStackInfoSetup.jpg 627w&quot;
        sizes=&quot;(max-width: 627px) 100vw, 627px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h3 id=&quot;technical-description&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#technical-description&quot; aria-label=&quot;technical description permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Technical description&lt;/h3&gt;
&lt;p&gt;The modification is executed by subscribing to &lt;strong&gt;Info.onInfoLogMessageAdd()&lt;/strong&gt; delegate. Then Call stack is saved by using &lt;strong&gt;xSession::xppCallStack();&lt;/strong&gt; method. Below is the sample code for this&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;c#&quot;&gt;&lt;pre class=&quot;language-c#&quot;&gt;&lt;code class=&quot;language-c#&quot;&gt;class DEVCSXppCallStackHandler
{
    [SubscribesTo(classStr(Info), delegateStr(Info, onInfoLogMessageAdd))]
    public static void Info_onInfoLogMessageAdd(InfoLogMessageAddEventArgs _eventArgs)
    {
        DEVCSXppCallStackTable       callStackTable;
        boolean                      isEnabled;
        DEVCSXppCallStackUserSetup   callStackUserSetup;
        callStackUserSetup = DEVCSXppCallStackUserSetup::findCurrent();
        if (callStackUserSetup.RecId &amp;amp;&amp;amp; callStackUserSetup.IsEnabled)
        {
            isEnabled = true;
            switch (callStackUserSetup.SysInfologLevel)
            {
                case SysInfologLevel::None:
                    isEnabled = false;
                    break;
                case SysInfologLevel::Warning:
                    if (_eventArgs.exception== Exception::Info)
                    isEnabled = false;
                    break;
                case SysInfologLevel::Error:
                    if (_eventArgs.exception == Exception::Info ||
                        _eventArgs.exception == Exception::Warning)
                    isEnabled = false;
                    break;
            }
        }
        if (isEnabled)
        {
            UserConnection       userConnection = new UserConnection();
            callStackTable.setConnection(userConnection);
            callStackTable.clear();
            callStackTable.initValue();
            callStackTable.Exception = _eventArgs.exception;
            callStackTable.InfologStr = _eventArgs.message;
            callStackTable.CallStack = xSession::xp CallStack();
            callStackTable.insert();&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then form &lt;strong&gt;DEVCSXppCallStackTable&lt;/strong&gt; displays the saved data.&lt;/p&gt;
&lt;p&gt;An additional tool that may be combined with this one is &lt;a href=&quot;https://arbelatech.github.io/aotbrowser/&quot;&gt;Arbela AOT Browser&lt;/a&gt; that allows viewing the code on Tier1 environments without Visual Studio usage.&lt;/p&gt;
&lt;h2 id=&quot;trace-dialog-calls-update-05112023&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#trace-dialog-calls-update-05112023&quot; aria-label=&quot;trace dialog calls update 05112023 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Trace dialog calls (update 05.11.2023)&lt;/h2&gt;
&lt;p&gt;The Trace dialog calls option allows you to see the class and the stack trace information of any dialog form in D365FO. You can enable or disable this option for each user by checking or unchecking the Trace dialog calls checkbox in the “Dev Tools – Call stack” form.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/50d62f1467fbd1b5ce01a824e98513df/0f2bc/TraceDialogCallsOption.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 27.999999999999996%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABJklEQVR42lWRy07EMAxF+/8/wIewYMuKDYLVAEJkgFHVMk3ppHk3r17cjECDpSO7Stx7HTdXNxLjySAEB+ccrLU1G2MgxAmackwZOf+nlIJzrLVeN9YVTTcoiFnRpYSUNiJi3AgkEhCJ7eyStWSMnIOxN3RdBylniNOEaRrROL9A6qWqnH+Yaw6pIERyQqplxV/8lnw44n2/x57gfEDfd1QzNN4peKfrmFKKqmS0hPeBvhWc1UjkOJOrQO5TSXU8aw2dS+rzuIzm+vYF97uWGoD2KPHEvvDZz+hHi29VwFqBjlsc2BFvuw9yNWA2iUxYGnEiYX9+mu2ZKDesldRMS4kF0qZ6WehYUa7ALIAyGf3jM/q7B/DXA2xYqXmpC9Na0wJ1XebGD3pGzQE0XuHyAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Trace DialogCalls Option&quot;
        title=&quot;&quot;
        src=&quot;/static/50d62f1467fbd1b5ce01a824e98513df/8c557/TraceDialogCallsOption.png&quot;
        srcset=&quot;/static/50d62f1467fbd1b5ce01a824e98513df/4edbd/TraceDialogCallsOption.png 175w,
/static/50d62f1467fbd1b5ce01a824e98513df/13ae7/TraceDialogCallsOption.png 350w,
/static/50d62f1467fbd1b5ce01a824e98513df/8c557/TraceDialogCallsOption.png 700w,
/static/50d62f1467fbd1b5ce01a824e98513df/0f2bc/TraceDialogCallsOption.png 742w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;To demonstrate how this feature works, I ran some periodic operations that use dialogs, such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;History by transaction report&lt;/li&gt;
&lt;li&gt;Create prenotes&lt;/li&gt;
&lt;li&gt;Rebate management&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These operations use different types of dialogs, such as Reports, Runbase classes, and SysOperation classes.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 488px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/ecf61f74c743ffd110eff63042227bf1/bd48c/SampleDialogOperation.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 68%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABcUlEQVR42p1Ty26DMBDk/3+h9957zLHHnvIHUVTyAAIYDDYGjKe72xIlEihJLa1WwDI7M96N9vs9sixDkiQ4Ho8SaZpiHEeEEJ6OaZrQ9z2ipmnQdR0cRV3XaLSW50AFrxwG5SOARVEI2H8PsxMSBBoZa9G0rbxgmXN476/Bz8Mw3OWl7wKYZSni+HtVIhedz2fsdjucTieqjVHk+Z3M2xPlpUaSlai0weAB6zwa4xBu5KiyxIUuzpASZsNqrDWLBKKiosswI0wf0LoAbT3yymJuzsxb8tkYIxfnnBOL1jyPlFI0Jhl1dRLWdsLkVnJOEvnieCwY0JLvHIuAAxV5NpXySMa6zqKkn2d/mCEz6wlozsy4IiKLgJrmrqqqa9Fa50djw43Yp6gleQzI88jZmFYKnhnkafoL/6tCANlcpUqRyV7xGjL4q1tyncO1FXoMAmy2Fh9fBrVuxS7Z5bVlf+gblbx/Nnjb1EgvCvHhIP7/AGvTSLBfYRkYAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Sample dialog operation&quot;
        title=&quot;&quot;
        src=&quot;/static/ecf61f74c743ffd110eff63042227bf1/bd48c/SampleDialogOperation.png&quot;
        srcset=&quot;/static/ecf61f74c743ffd110eff63042227bf1/4edbd/SampleDialogOperation.png 175w,
/static/ecf61f74c743ffd110eff63042227bf1/13ae7/SampleDialogOperation.png 350w,
/static/ecf61f74c743ffd110eff63042227bf1/bd48c/SampleDialogOperation.png 488w&quot;
        sizes=&quot;(max-width: 488px) 100vw, 488px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;After running the operations, I opened the Trace form and saw the class and the X++ stack trace information for each dialog&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/563fd735a2900a64172e0669c3572a35/d69c4/DialogTraceResults.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 35.42857142857142%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAAA7EAAAOxAGVKw4bAAABLklEQVR42oWR6UrDQBSF8/4PJRTEggtWBVsNNm2S1iSTrVk6+xxvJ1qk/vDAxx1mOdx7JugGDqU14CyccxOY5L45Kcv2iKI1WJEj+9yhKksoKf4QNG0LQQuhFH7kyNwaA2uNr7SB9tCiqmsoJSEEh6Q3hs4uCV63HcIwx3L+jM0ixObpA9tc4CVkWG0aLImsUej73ptyIQh+7vxSQTMasKTA6uoab7MbvM/mKIsD8npAQdSdxMANNE1wisNa6/mtc1REQMmBUy7s7hbV4hHVwz2GeEu5Sj+eMdob8OORGHE8M/g6jgOMVv6epjeBd6bZnZQEdSGoKo2LFlC3PdYJQ5SUiNKJdVz4vSSjWKoRdW8mw//k/KccEMcp0t0OcUI13YOxEmVVg5UVnXf0sQZf4psbP+iHLgkAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Dialog Trace Results&quot;
        title=&quot;&quot;
        src=&quot;/static/563fd735a2900a64172e0669c3572a35/8c557/DialogTraceResults.png&quot;
        srcset=&quot;/static/563fd735a2900a64172e0669c3572a35/4edbd/DialogTraceResults.png 175w,
/static/563fd735a2900a64172e0669c3572a35/13ae7/DialogTraceResults.png 350w,
/static/563fd735a2900a64172e0669c3572a35/8c557/DialogTraceResults.png 700w,
/static/563fd735a2900a64172e0669c3572a35/d69c4/DialogTraceResults.png 1002w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;This feature is very handy when you need to quickly identify the related classes and operations in D365FO. I have used it several times during calls with business users and it works very nicely.&lt;/p&gt;
&lt;h2 id=&quot;summary&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#summary&quot; aria-label=&quot;summary permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Summary&lt;/h2&gt;
&lt;p&gt;You can download the tool using the following link - &lt;a href=&quot;https://github.com/TrudAX/XppTools#installation&quot;&gt;https://github.com/TrudAX/XppTools#installation&lt;/a&gt;. I hope you may find this tool useful, also feel free to comment if you see something is missing.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Multicompany DMF integration in Dynamics 365 FinOps using X++]]></title><description><![CDATA[The blog post describes a sample approach to implement recurring file-based integration in D365FO using X++ and DMF]]></description><link>https://denistrunin.com/xpptools-fileintegdmf/</link><guid isPermaLink="false">https://denistrunin.com/xpptools-fileintegdmf/</guid><pubDate>Wed, 11 Aug 2021 22:12:03 GMT</pubDate><content:encoded>&lt;p&gt;In one of my last posts I described a sample approach for a &lt;a href=&quot;https://denistrunin.com/xpptools-fileintegledger&quot;&gt;periodic file-based integration using X++&lt;/a&gt; custom code. The external system creates files on the Azure file share, then D365FO pulls these files, parses and processes them. One of the comments on this post was why DMF is not used for such tasks.&lt;/p&gt;
&lt;p&gt;That is a perfectly valid comment, given that if you want to develop a custom import you need to do a lot of programming, like create staging tables and forms, implement a file parsing and create the final document via X++ code.&lt;/p&gt;
&lt;p&gt;In this blog post I will show how DMF can be used in the same framework in order to implement a periodic files import.&lt;/p&gt;
&lt;h2 id=&quot;task-description&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#task-description&quot; aria-label=&quot;task description permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Task description&lt;/h2&gt;
&lt;p&gt;We have an incoming folder in the &lt;strong&gt;Azure file share&lt;/strong&gt; that contains a set of files and we need to import them via DMF. In this example I will use a “Customer group” entity in Excel format. Also let&apos;s implement a multi-company import. A company code will be specified for a file as a first characters before &quot;_&quot;.&lt;/p&gt;
&lt;p&gt;We need to import these files in D365FO and view the import status per file.&lt;/p&gt;
&lt;h2 id=&quot;proposed-solution&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#proposed-solution&quot; aria-label=&quot;proposed solution permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Proposed solution&lt;/h2&gt;
&lt;p&gt;In the following section, I provide some code samples that can be used as a starting point to implement a periodic file import and processing.&lt;/p&gt;
&lt;h3 id=&quot;file-share-connections-form&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#file-share-connections-form&quot; aria-label=&quot;file share connections form permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;File share connections form&lt;/h3&gt;
&lt;p&gt;This form is used to define a connection to a cloud file share. In this example we will use a &lt;strong&gt;Azure file share&lt;/strong&gt; link.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/ddcb75b81bd1ebfee131ffc89d5bab5c/cecac/ConnectionTypesForm.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 40.57142857142858%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABU0lEQVR42o2RyW7EIBBE/f9fN7lEySFKZvECZrHBNowNrpTJHCaXKEhPXQJ10RSVUA7DMMA7X6o2DkZrotD3PZxzmKcJMSy4x1DqM2GZf1ENdsSy8DBGpJSw54yUE3VGzjv2fWdjgBQd6tsNvRTomgb19Uot4cah4N0Iz1qdTi/QStJgxXqPNEgAciHnDZn7d+6LrsXlckZT12ymgXdY5gnWaAgh+Dpb9qrZjzi3I14/FN4+Ja5ygRgyOpuKfv/S0HYqUxhtGIlB4MQrX3REMHkPxWg0I/LUVVoDehtwY3PbzxDmDuXyg4RazjT0mJijUrqYKqUQYixxZEJR9BFXFcOMbVvx1zryHaxF0zaQzK3j87dtK2fFNOfCoYvhuq54XPQDntgPwwDDz7s1jKQRnNjBLxHjFLDE7dfl/5zwMHRohSH8BGkglUUnGcEw8eO2MvHBN0XFaWqgVSihAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Connection type&quot;
        title=&quot;&quot;
        src=&quot;/static/ddcb75b81bd1ebfee131ffc89d5bab5c/8c557/ConnectionTypesForm.png&quot;
        srcset=&quot;/static/ddcb75b81bd1ebfee131ffc89d5bab5c/4edbd/ConnectionTypesForm.png 175w,
/static/ddcb75b81bd1ebfee131ffc89d5bab5c/13ae7/ConnectionTypesForm.png 350w,
/static/ddcb75b81bd1ebfee131ffc89d5bab5c/8c557/ConnectionTypesForm.png 700w,
/static/ddcb75b81bd1ebfee131ffc89d5bab5c/cecac/ConnectionTypesForm.png 728w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h3 id=&quot;inbound-message-types-form&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#inbound-message-types-form&quot; aria-label=&quot;inbound message types form permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Inbound message types form&lt;/h3&gt;
&lt;p&gt;In this form we need to create a new class that processes our files. The logic for this will be quite simple: load a file, change the company, pass the file to a DMF framework. The DMF call will be &lt;strong&gt;synchronous&lt;/strong&gt;, so we can get the status from DMF after the processing and update our message table.&lt;/p&gt;
&lt;p&gt;On this form we can also specify for which entity we need to run our import. Basically it links the Incoming directory with a DMF project/entity. The same processing class can be used for different entities.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/6461e73f04bf1dde469616f0d8b6d00d/d1d24/InboundMessageType.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 71.42857142857143%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABu0lEQVR42p1Ti46bMBDk//+vPZ2udwoQkvAwfmNeZjomyUl3apuoFiOMvR5md7xZrwy893B+gLWecwdjzf5OULJHU18g+x5Gqx1a9bBaI3iLKTDO2U9k+SHHGDzWZUZcF8QYAWx8CA6tJMqiQNtcUOQ5quMRXdtg4OFT3ePl/Qxn5OfPMikVfr53KGuPt0LgVy5w6ibUMuIsZvTcTyrnaYKzlocMBQQgLhBqxEfF78EhDANCGJClwF57aBtgHOeKaRpuThtGwpJEknCaxl3xVfyGeZ4xjeN9aV9LyFLgdkvvTyPV91K3aDq5l2Nd12spWMOyqjCQdOV6vHE8RdgJA6kDyXgwrjuxb1v0ZQlRFrB1jUDTNq4/JnQO1hgsybSbwt24hO1qXiLadjOfVNhSTYIhcRj/Hf+QcOBd7LoODa+KYd2klLshdxO+4ymFyWUhBFoSezZASvtveEhojIVmqsnJhabcY/9bYbrMVSXYamxNw3sqR3bJQMb4Je5pQsVef/1xwMdrgSpvcWI3Hd4qVGeFTrOT7ApBaDcz5eUxoTYOx1rz8ATLxrAT0LsFx4vEuTXQPhIbFDdTNr8Bju5DJCVSjN4AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Message type form&quot;
        title=&quot;&quot;
        src=&quot;/static/6461e73f04bf1dde469616f0d8b6d00d/8c557/InboundMessageType.png&quot;
        srcset=&quot;/static/6461e73f04bf1dde469616f0d8b6d00d/4edbd/InboundMessageType.png 175w,
/static/6461e73f04bf1dde469616f0d8b6d00d/13ae7/InboundMessageType.png 350w,
/static/6461e73f04bf1dde469616f0d8b6d00d/8c557/InboundMessageType.png 700w,
/static/6461e73f04bf1dde469616f0d8b6d00d/d1d24/InboundMessageType.png 987w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Also, this form contains two servicing operations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Check connection&lt;/strong&gt; button that tries to connect to the specified directory&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Import file&lt;/strong&gt; button that can be used in testing scenarios to manually import a file from a user computer without connecting to a network&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;incoming-messages-form&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#incoming-messages-form&quot; aria-label=&quot;incoming messages form permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Incoming messages form&lt;/h3&gt;
&lt;p&gt;This table will store the details for each inbound file. It displays the original incoming file name and its status.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/3b6fb7fd04f632ab97041588e599cb07/ecf19/MessagesForm.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 42.285714285714285%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABSUlEQVR42m2R20rDQBCG8/53giA+gILgK3grKAUvPIBKW5NakxjTJHvKpjn8zkybSLFLfuawk29mdwNjHb7TFB/LJVZRRH4ySVUltKoO7CiOjylovEOaxIiikBRhvf4UPwxDGKPhrP0vZ4/nSQLcbDZI0gxaK2iCeO/pJ0dAA2vNDkAylmMLS761f3t234TjwNcORVkhyQoCaiilRAwcVVWV5Oq6nmp2vpK9UTxAUBPZ+5oKHNq2RdM0KIpignHMxQzgtd1uJceL6/h0rDzPpdkOSMVc1HWdQBU/wP6SR/AwDALp+37yeVKeiiflepnQy9kd3Yun7q3YryRDnP6IspxeVRtqRiCCtGS7fgB9KEturOXKiqIUP+gai7dI4/ZF431lcDOLcXJxh7OrGU4v73F+/YDZq8Ii6TCP2wM9zks8LRTZSvS8UPgFUc9hfzkktScAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Messages form&quot;
        title=&quot;&quot;
        src=&quot;/static/3b6fb7fd04f632ab97041588e599cb07/8c557/MessagesForm.png&quot;
        srcset=&quot;/static/3b6fb7fd04f632ab97041588e599cb07/4edbd/MessagesForm.png 175w,
/static/3b6fb7fd04f632ab97041588e599cb07/13ae7/MessagesForm.png 350w,
/static/3b6fb7fd04f632ab97041588e599cb07/8c557/MessagesForm.png 700w,
/static/3b6fb7fd04f632ab97041588e599cb07/ecf19/MessagesForm.png 948w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;In this form it is also possible to do the following operations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;View incoming file context&lt;/li&gt;
&lt;li&gt;Filter by different statuses&lt;/li&gt;
&lt;li&gt;View a detailed error message&lt;/li&gt;
&lt;li&gt;Change the status to process the message again&lt;/li&gt;
&lt;li&gt;View file processing statistics (processing duration, time, number of lines)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;load-and-process-incoming-files&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#load-and-process-incoming-files&quot; aria-label=&quot;load and process incoming files permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Load and process incoming files&lt;/h3&gt;
&lt;p&gt;It is a periodic batch job that we can run for one or multiple message types.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 365px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/7488ede1948c5e53e151b625a7a5cfb4/2e8d1/LoadIncomingFiles.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 83.42857142857143%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAARCAYAAADdRIy+AAAACXBIWXMAAA7EAAAOxAGVKw4bAAABmElEQVR42q1U126DQBDk/38kX5AvyGserUiOC9gUF7ijg43Bk5t1iFwSy0ReabRHubkts2fVdY0oihDHMfI8R6w1tFayTtNUoJXCbrfDI2ZpQzCdThEEAXzfx2KxwGQyEe95HhzHxmg0kgNpx+PxPiGebBZTXi6XEh0jYmqMous6Qb8+t3tBWvyZJPv9Xvz15mvjAdcHXhCSxPN8rFYrgTINaNsWh8NB0G/o/ValsN1QGhWGofx/QVgUJT7mGpsoRZFnpqsZsiyTLnND392uOxG+vpd4eStRFQnKsrpplCXhf6dxDqbDSK9Tak1F6gYSPb/f1LBpGqgoRJIkP7qjLh/V3Q0hm+EHa6kFtaaUxnq9RlVVf+quf/XbN6s173ITTGB027RP0CFTm89mcF1P9MjJsG0b2+1GnjlJgwhZQ44ZRy+JE0mbJEVRIM1S8YMIS7Phczw2WnSNXFKURS6ghHIDdnMQIYu/MGnG5oZJYi2+h1aRTNAgQmqprk+jx7lmTQmWgvjX5cBLIQy3ckFw/BzHkTX1OJTwCz/HMOGe5oTCAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Load incoming files&quot;
        title=&quot;&quot;
        src=&quot;/static/7488ede1948c5e53e151b625a7a5cfb4/2e8d1/LoadIncomingFiles.png&quot;
        srcset=&quot;/static/7488ede1948c5e53e151b625a7a5cfb4/4edbd/LoadIncomingFiles.png 175w,
/static/7488ede1948c5e53e151b625a7a5cfb4/13ae7/LoadIncomingFiles.png 350w,
/static/7488ede1948c5e53e151b625a7a5cfb4/2e8d1/LoadIncomingFiles.png 365w&quot;
        sizes=&quot;(max-width: 365px) 100vw, 365px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;It connects to the shared folder, reads files, creates a record in the &lt;strong&gt;Incoming messages&lt;/strong&gt; table with &lt;strong&gt;Ready&lt;/strong&gt; status, attaches a file content to this message and moves the file to an Archive directory. If &lt;strong&gt;Run processing&lt;/strong&gt; is selected, after the load, the file will be processed.&lt;/p&gt;
&lt;p&gt;Internally the processing takes a file and run the same function that the user may run for a manual import in the Data management module&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/a14a0026611eabb7f61986af2baf1f83/cd7c1/ImportNowFunction.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 16.571428571428573%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAADCAYAAACTWi8uAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAlUlEQVR42kWOWwrDMAwEc/9jtoTGlvxM5JRYztZ2of0YBq0E2uW1EULMCD4jEsNsBkQEZoJzPM19JmthrZkO3iHnhJwGcTqECEMRy3NlrFRA8Y1cFPsh2HfB3RRtoPXrVqE60P+u1d/NyAaL1gv3jc49yUmwPnpTFiRp4FDg4tmfNVgvk3QoqOcUBC6dvUyBzxeME3wA+VLmsk8aLTwAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;ImportNowFunction&quot;
        title=&quot;&quot;
        src=&quot;/static/a14a0026611eabb7f61986af2baf1f83/8c557/ImportNowFunction.png&quot;
        srcset=&quot;/static/a14a0026611eabb7f61986af2baf1f83/4edbd/ImportNowFunction.png 175w,
/static/a14a0026611eabb7f61986af2baf1f83/13ae7/ImportNowFunction.png 350w,
/static/a14a0026611eabb7f61986af2baf1f83/8c557/ImportNowFunction.png 700w,
/static/a14a0026611eabb7f61986af2baf1f83/e996b/ImportNowFunction.png 1050w,
/static/a14a0026611eabb7f61986af2baf1f83/2cefc/ImportNowFunction.png 1400w,
/static/a14a0026611eabb7f61986af2baf1f83/cd7c1/ImportNowFunction.png 1547w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The sample code for this is below. You can find the same samples in several places in the system&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;c#&quot;&gt;&lt;pre class=&quot;language-c#&quot;&gt;&lt;code class=&quot;language-c#&quot;&gt;//read a file..
//change the company from the file name...
//find a linked DMF definition import and path the file into it..
    
DMFExecutionId executionId = DMFUtil::setupNewExecution(definitionGroupEntity.DefinitionGroup);
//...
    DMFStagingWriter::execute(
        executionId, //_executionId
        0, //_batchId
        true, //_runOnService
        false, //_calledFrom
        DateTimeUtil::getUserPreferredTimeZone(), //_timeZone
        false //_compareData
    );
//...
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As the process is synchronous, we can check the status after the import and update the Message table with results.&lt;/p&gt;
&lt;h2 id=&quot;error-types-and-how-to-handle-them&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#error-types-and-how-to-handle-them&quot; aria-label=&quot;error types and how to handle them permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Error types and how to handle them&lt;/h2&gt;
&lt;p&gt;Let&apos;s discuss typical errors and how users can deal with them. Also I will compare them with a custom made import.&lt;/p&gt;
&lt;h3 id=&quot;file-share-connection-errors&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#file-share-connection-errors&quot; aria-label=&quot;file share connection errors permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;File share connection errors&lt;/h3&gt;
&lt;p&gt;If our batch job can&apos;t connect to a File share or read and move files, a batch job exception will be generated. It is a configuration error and it requires system administrator attention. Notification will be done using a batch job status. After troubleshooting the error system administrator can use the &lt;strong&gt;&quot;Test connection&quot;&lt;/strong&gt; button to validate that the system can now connect to the file share.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 465px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/9d49e272cba6dae222cf112b3c84f3b2/9ff85/TestConnection.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 31.428571428571427%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABSklEQVR42j2Q2Y6bQBBF+f9PizKWM4wZD6sNBrN0szYNBuOTNpFS0tGt7aFuWd9+iRdeELLfNUlLHDc1uCTRBedw5Hy0+fo4kAQh4eWK50dcrzH2ycH1A0rRGFrqtsP6kyh+exWf1wa3eBA1EMgNv944+xX2R4B9vPB5CHBOKYF4EjYvTpnCyTRB+yJsIer+YdVqI68Vt7KhaBSin6g6jegm5LhQzxtyelJPRvW699/zN3k9GLpds6rlLs2FURAhqhI9DgxDx7rMbM9lZ31MLLP+z7t+bSvzpJn1SC0ryjylLHPye0aeJlie61EUBUIIxnFEa20WCrNwN/nItj1Z12XXvu+53VKUUjweM99n80P3hySOkVKQ53csTMS54tdXhp/NO7eiJTcWRKuoe4009lo18RMP2GFPmE2o0Vi+p0jjrm8bc61ADT1/AYUhwbXxDy1kAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Test connection&quot;
        title=&quot;&quot;
        src=&quot;/static/9d49e272cba6dae222cf112b3c84f3b2/9ff85/TestConnection.png&quot;
        srcset=&quot;/static/9d49e272cba6dae222cf112b3c84f3b2/4edbd/TestConnection.png 175w,
/static/9d49e272cba6dae222cf112b3c84f3b2/13ae7/TestConnection.png 350w,
/static/9d49e272cba6dae222cf112b3c84f3b2/9ff85/TestConnection.png 465w&quot;
        sizes=&quot;(max-width: 465px) 100vw, 465px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h3 id=&quot;file-format-errors&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#file-format-errors&quot; aria-label=&quot;file format errors permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;File format errors&lt;/h3&gt;
&lt;p&gt;The next error type is a wrong file format, so we can&apos;t even read the file content.&lt;/p&gt;
&lt;p&gt;To test this case I renamed one of the columns&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 559px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/fe791a2b185bed4616e1961c2b28dde1/a65ce/WrongColumn.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 27.42857142857143%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAYAAABFA8wzAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABD0lEQVR42kVQy3KDMAzk/z8ql5zbQoEEbB4lhPAICaFgkwJhK/mSnfFotNLsrmVFkUSaJJBSQoQhhBBomgZaTygvFxwOB8NJIZHQXiRCBLYN8e2izk5QvwOUVijLC4IggOX4NvIix9/zSSIa0zRhnmcwiuKMmES6roPv+wjJVLou7N0O7n6PwvOgaMao6xr37sGCDsq6NOTrtWHbNqov07NrxinUiCiKkP1kZJCiud3QDwPufY+RQjDa9opRaVifzgfKpjLksixY19VURp6fEMcJHo8OHiVM0hTH4xHttTXzjYx5n1Kgqir09H3L9r/Qdjci34L8OC278qKmG53znBJXdIbCcG/z1QjzWZTW+AcIk3amgt4PrgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Wrong column&quot;
        title=&quot;&quot;
        src=&quot;/static/fe791a2b185bed4616e1961c2b28dde1/a65ce/WrongColumn.png&quot;
        srcset=&quot;/static/fe791a2b185bed4616e1961c2b28dde1/4edbd/WrongColumn.png 175w,
/static/fe791a2b185bed4616e1961c2b28dde1/13ae7/WrongColumn.png 350w,
/static/fe791a2b185bed4616e1961c2b28dde1/a65ce/WrongColumn.png 559w&quot;
        sizes=&quot;(max-width: 559px) 100vw, 559px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;This file caused a 1 minute delay for DMF and then an internal error&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 309px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/1d3900978937297ed918cecf6056d044/532e8/WrongColumnError.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 57.714285714285715%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAA7EAAAOxAGVKw4bAAABqElEQVR42qVTf2/aMBDN9/9ShUlF2qqpVbdJ0BIgCYTYSYjzG+Ikb8+mZfxBK22zdDrf5fx8ee/slGUJpQp0XWftdDqhqRvUVQ0pYywWr/ib5Tw9P2Ny9wXfH58wmU4x+/aA+XyByWSK+/sZZl8foLW2xeM4XuxDwOtAd5pd6kv82cEPAVWWoygKVFWF2vxq29p9VddIkhSHLLNxUZS2zpjKc0vNTcD1aoP5ywt+/PqJ1dt+6boIwh2WqyXc9Rqet4GQEr7vw/MD+EGAsqxuA+6jCK67ZtEWIpYICbThAa17/Mtyhq7F2GsM5GsYBvqz9UNP0M56k+/7/myMO4r0J2dqB7yz7dTBAq3coiB/kRTYhiH2IsJBKcRJAiEkfYo0JZ+HDHGa8G923KcIWZdZL1CScwtY+BtU4R7N8UghKExTW5+TeJUrlEYgmuHMiFa9fa8J0LQNrT3XUyzNjp3c81DuIhQc8IS3ZSqFTGLIOGZ3grwmBFcQkTh3TJ6llHboM+bT7ECwHBHzRyp/mUNz246dGuD/WQQcL0NsSL5+Ddev4lZ+vPF6fgNGWZ74z+c7SQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Wrong column error&quot;
        title=&quot;&quot;
        src=&quot;/static/1d3900978937297ed918cecf6056d044/532e8/WrongColumnError.png&quot;
        srcset=&quot;/static/1d3900978937297ed918cecf6056d044/4edbd/WrongColumnError.png 175w,
/static/1d3900978937297ed918cecf6056d044/532e8/WrongColumnError.png 309w&quot;
        sizes=&quot;(max-width: 309px) 100vw, 309px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;DMF uses a data integration component that connects to an Excel file and that is probably why the error is not verbose.&lt;/p&gt;
&lt;p&gt;This message is stored in the Messages table, users can view the error log, then download the file and check the reason for this error.&lt;/p&gt;
&lt;h3 id=&quot;data-errors&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#data-errors&quot; aria-label=&quot;data errors permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Data errors&lt;/h3&gt;
&lt;p&gt;The file has a correct structure but contains a wrong data(e.g.. values that don&apos;t exist)&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/d88ef39c28746d6ae8462289b260ce18/5ebd7/WrongData.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 18.285714285714285%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAYAAACOXx+WAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAA1ElEQVR42h2PyW7DMAxE/f+/FjTNoT7ELrRHsiWj3nJobUtTigQGIMDBm2HjnEWVlBLGGIzjiIGkaVdKQZKGYUCMkZVSYk+Vsw5CCITgobWGJm/T9R0iHUMIbM65YFlmfLUtAz8fD7S0G2vhfcC+7zjPk3yZCmgOe3ZP9EIipohGGok6FVRNpRBwXbjhtq0E1ZyuSDW0tnwT9LpOTNOEfBwQ9w90txs259BYb4ECHJRaTRW4riu/P88//FJ9xb0830rJ5Lu4ZZoSDgKq7x6R2l9/v/gHxHIrEOKf1NsAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Wrong data&quot;
        title=&quot;&quot;
        src=&quot;/static/d88ef39c28746d6ae8462289b260ce18/8c557/WrongData.png&quot;
        srcset=&quot;/static/d88ef39c28746d6ae8462289b260ce18/4edbd/WrongData.png 175w,
/static/d88ef39c28746d6ae8462289b260ce18/13ae7/WrongData.png 350w,
/static/d88ef39c28746d6ae8462289b260ce18/8c557/WrongData.png 700w,
/static/d88ef39c28746d6ae8462289b260ce18/5ebd7/WrongData.png 704w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;In this case, a Status of our Message will be &lt;strong&gt;Error&lt;/strong&gt; and an Error log will be generated.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/a1b40e3ca6c4b21195af9b449ed14110/0955e/WrongDataError.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 30.28571428571429%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABE0lEQVR42l2Q626DMAyFef+n66S2GlXLJkGhDeTiOCHAVp2Z9DJtPz7ZPvE1hTYEZy0CE56+pzX2GIYeRg+w1sCoC9ryHd2hhL506HuFGCLGGJHGX4opTeivV2w2b9httziUJT6qCvv9Dkr0wCwDCOQcyOiMF59lYNb+UczTCOcISjtYxzCCpYBeYuIRIc7gOGUbxjtr/NIe9qlJwyQnWXzWHbR1GIwFyynMAeQZjvwDztCqCzn2/PLXXPJBGqYRJML5avOGHBL6Qf4wJoxp/kOQN6W0LOCR0gJjSWruvjZO6gyKRU5uFaNqI2o14zx841h7HBuP05lxajjbY005p+pmNPoLrbmh6Rc0w4JW33LNmvsDO53HwnLVDvQAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Wrong Data Error&quot;
        title=&quot;&quot;
        src=&quot;/static/a1b40e3ca6c4b21195af9b449ed14110/8c557/WrongDataError.png&quot;
        srcset=&quot;/static/a1b40e3ca6c4b21195af9b449ed14110/4edbd/WrongDataError.png 175w,
/static/a1b40e3ca6c4b21195af9b449ed14110/13ae7/WrongDataError.png 350w,
/static/a1b40e3ca6c4b21195af9b449ed14110/8c557/WrongDataError.png 700w,
/static/a1b40e3ca6c4b21195af9b449ed14110/0955e/WrongDataError.png 901w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Users can view the error detail using the standard DMF Execute history form, that displays invalid lines&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/d2ffef1508faa35eabc142c1f2710e18/d4b10/WrongDataErrorStaging.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 22.285714285714285%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAYAAACOXx+WAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAyUlEQVR42k1QQY7CMAzs/w+Ive7+CyRQORaKSNLEiUPatLOOQQhLI9vxzNhKV0rB7Tqg73uMtyucNbjfR1jz0FrhDCIFUPAgP31qza13FvRGV54Z0+QQI2m2YjAMA4IQg4hcI4agmVNUvJZYhKZjhqsVtG1Igu6ZGT4QkhCtMWrsvQdzErGAo7xFjA8LY2VJZJ0luY6XGXQ6we52yD975L9fdFmG81wg5kpc1xXLsuA7al3lWkL7nq0RJRqnSl3FuBwPwPkMXC74B6qWMRQ+5EXzAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Staging error&quot;
        title=&quot;&quot;
        src=&quot;/static/d2ffef1508faa35eabc142c1f2710e18/8c557/WrongDataErrorStaging.png&quot;
        srcset=&quot;/static/d2ffef1508faa35eabc142c1f2710e18/4edbd/WrongDataErrorStaging.png 175w,
/static/d2ffef1508faa35eabc142c1f2710e18/13ae7/WrongDataErrorStaging.png 350w,
/static/d2ffef1508faa35eabc142c1f2710e18/8c557/WrongDataErrorStaging.png 700w,
/static/d2ffef1508faa35eabc142c1f2710e18/e996b/WrongDataErrorStaging.png 1050w,
/static/d2ffef1508faa35eabc142c1f2710e18/d4b10/WrongDataErrorStaging.png 1394w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The main difference from the custom import is that you can&apos;t implement &quot;all or nothing&quot; principle as DMF doesn&apos;t support transactions, lines from this file that passed validation were processed successfully.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/5d79425240793f8eee887fa7d256139a/09e48/DMFImportStatus.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 51.42857142857144%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABmElEQVR42nWSy27UMBSG86SsWCBeBIkFvAMbXoBNF1SgqhsWSCAxk7jTzDC3zq0ZX+PEjvP3OElbVZ050qfYJ/bncywnWim2ms9ZmmVsmk9ZlqVsNpuxmFdSMh1Rcpjzk2glxkqKlRTHr4l3Nfb7HRaLBYwxMFqjpK+jfOMdpOD0f4vi/oC6rk9SVVUDChpfJVKIIAQPttTBO0tUwRoZujzngeTBexeccwHwhDsBndxF+JlQqVjvFPK1wXiuMZpLZEuFgktQO/F0tP1qjI4tLpYtLtfEqsX3ARo3lxvgzwZXiVIKk3yH32OO65HGdSrw69ZgVyjoKLQWPhZG8eXiDm8+jPH+M8O7T8+8/Zg231JgpqKQKrxZGvzNS/z7X2KyJTYGh6PohGVZwtqKpA7bO4lJtsd0co/85vDELds3QxO9kO4LYkDKnj4fW7Z4jNC2aE/TCUMIvfAc9Ay6O4wRNzahjZte0VA8CemN4RxRWg/C1xVGQYNArhcVUlv+HIIX3lrraW2HKoyvtOo48tILXXlO1JV9PPXHA0yg9BnL381YAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;DMFImportStatus&quot;
        title=&quot;&quot;
        src=&quot;/static/5d79425240793f8eee887fa7d256139a/8c557/DMFImportStatus.png&quot;
        srcset=&quot;/static/5d79425240793f8eee887fa7d256139a/4edbd/DMFImportStatus.png 175w,
/static/5d79425240793f8eee887fa7d256139a/13ae7/DMFImportStatus.png 350w,
/static/5d79425240793f8eee887fa7d256139a/8c557/DMFImportStatus.png 700w,
/static/5d79425240793f8eee887fa7d256139a/09e48/DMFImportStatus.png 974w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h3 id=&quot;posting-documents&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#posting-documents&quot; aria-label=&quot;posting documents permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Posting documents&lt;/h3&gt;
&lt;p&gt;We don&apos;t have a posting code in this example, but it can be implemented by modifying the processing class after the successful file load.&lt;/p&gt;
&lt;p&gt;We can see this architecture in a lot of projects, where DMF is used only to load the data in staging tables that don&apos;t contain any business logic and the chance of error is minimal.&lt;/p&gt;
&lt;p&gt;Then in order to process these staging records(create business documents) a custom code is executed. In this case you rely on DMF only for reading the file and implementing posting via a custom code(with a proper transaction handling).&lt;/p&gt;
&lt;p&gt;In some cases it may be a valid choice, but as we saw file parsing is not a big advantage of DMF and in some cases implementing your own reader can produce better results.&lt;/p&gt;
&lt;h2 id=&quot;summary&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#summary&quot; aria-label=&quot;summary permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Summary&lt;/h2&gt;
&lt;p&gt;In this post I provided a sample implementation for a File-based integration for D365FO via DMF. In some ways it is very similar to &quot;Recurring integrations scheduler&quot; but based on X++. It is not complex: the main &lt;a href=&quot;https://github.com/TrudAX/XppTools/blob/master/DEVTutorial/DEVExternalIntegration/AxClass/DEVIntegProcessDMF.xml&quot;&gt;class&lt;/a&gt; that takes a file and passes it to DMF contains about 100 lines of code. Also an advantage of this solution that it can be used as a starting point(for example for prototyping) and then can be easily converted to a custom X++ import when the requirements become more complex&lt;/p&gt;
&lt;p&gt;I uploaded files used for this post to the following &lt;a href=&quot;https://github.com/TrudAX/XppTools#devtutorialintegration-submodel&quot;&gt;folder&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I hope you find this information useful. As always, if you see any improvements, suggestions or have some questions about this work don&apos;t hesitate to contact me.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Monitoring the most problematic performance problem in Dynamics AX - parameters sniffing]]></title><description><![CDATA[The blog post describes a monitoring solution for SQL Server parameters sniffing issues]]></description><link>https://denistrunin.com/performance-snifmonitor/</link><guid isPermaLink="false">https://denistrunin.com/performance-snifmonitor/</guid><pubDate>Wed, 09 Jun 2021 22:12:03 GMT</pubDate><content:encoded>&lt;p&gt;One of the complex and probably most common problems in Dynamics AX performance tuning is SQL parameters sniffing. I recently wrote how to &lt;a href=&quot;https://denistrunin.com/performance-sniffing&quot;&gt;fix it&lt;/a&gt;, but in this post, I want to focus on a sample approach of how to implement a monitoring solution for such types of problems.&lt;/p&gt;
&lt;h2 id=&quot;parameters-sniffing-example&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#parameters-sniffing-example&quot; aria-label=&quot;parameters sniffing example permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Parameters sniffing example&lt;/h2&gt;
&lt;p&gt;Let&apos;s consider an example from the recent project. One of the critical system processes was a Production journal time posting. After the general optimization, it worked within acceptable time(around 5 seconds) but then on Friday at 3 pm it suddenly slowed down (like 30-50 seconds to post the journal, which affected a lot of users)&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/87182cfa15a61d95227b90f519f5879a/8efc2/PostingTimePanic.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 64%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABzElEQVR42n2TTW/bMAyG/e933a8YdtllGFAIAwpsh6HAsO6wHoq0SJPYjR1nbmv5S5JFvSPteMjcZAIIySL9iHxFRYvF4styHV88bBIVx7FKkkTlea6eikIVxV45IgVAYZpn1rat0loPa+KYCCHg1JDtnnjR9zgXI8OzX9cV6qaB9x4R79Gxkcx8lPVEuurp8u0bSq6+jT7vaR7vrKNst6NtllLbdhR5QRxndpi1AzLtcfvhHfYPy0PW4aiCcV2WJR7TFLv9Hlz+kOGs1DGwWGdYffwMd3+H8wUDLZcqwC2bMQaRtfa1eDx+fb/H9c/NuEXnkZKAgNqugyfW0HTmZKBi1uVmFOE/PBjrkBfPqI1DWXWIhDzXz7Gs728CrpJwnPRpoLEonkvUnUXVsIZy1XOg4a1Pd8CPFCeB8k1nDohEgyl+Kq3l1ks0sC7/BYYZNBw0nGzoQwr0N3CaBdhw2zzq1yAZctBNDliP8UK4XQTWc5NHNf+4euGeq4Hly5hZrEfg7W9uH5Y4b8bvbQU8tcBXubAVr9nX8WUISLqFnyCizgUUHNTxaWnpOCv5JljnoDnVVV5jpy0si5axvzLETzKwzw6VBBoe1mBS8h/NXfFMsOoTiQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Posting&quot;
        title=&quot;&quot;
        src=&quot;/static/87182cfa15a61d95227b90f519f5879a/8c557/PostingTimePanic.png&quot;
        srcset=&quot;/static/87182cfa15a61d95227b90f519f5879a/4edbd/PostingTimePanic.png 175w,
/static/87182cfa15a61d95227b90f519f5879a/13ae7/PostingTimePanic.png 350w,
/static/87182cfa15a61d95227b90f519f5879a/8c557/PostingTimePanic.png 700w,
/static/87182cfa15a61d95227b90f519f5879a/8efc2/PostingTimePanic.png 828w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/TrudAX/TRUDScripts/blob/master/Performance/AX%20Technical%20Audit.md#get-top-sql&quot;&gt;TOP SQL&lt;/a&gt; for the server looked like this(one TOP1 statement with considerably larger logical reads)&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/b6e77e46c1011c99ca7ce6b4666c874a/d54e4/TOPSQL.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 22.285714285714285%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAYAAACOXx+WAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAA2ElEQVR42kWP4Y6DIBCEff9H6fu0ioBoeieIImgsWBM7XbkfN8lmSch8M1uEEOC9xzBY/Dx/aQ8w2uSxdsxba41lWTGNI1JK9F4Qgsdrf2PvezyFgOo6bFtEsa4r9j3BGIOyZGgaBSkkasYgaAsuwGuOaXI4zxOXZufgqAQRsN1uEI87Zip2qbjSYozoKamqGJRSUARl7II3BBV5nJtxHEc2TaOFI99Brd52QNO19O/+gYmAute4P0pIKcE5z0BO7WpWU1CVz48pZtN17kbt/vRB2yr4sGTgF9ZTKtHliC3xAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Top SQL&quot;
        title=&quot;&quot;
        src=&quot;/static/b6e77e46c1011c99ca7ce6b4666c874a/8c557/TOPSQL.png&quot;
        srcset=&quot;/static/b6e77e46c1011c99ca7ce6b4666c874a/4edbd/TOPSQL.png 175w,
/static/b6e77e46c1011c99ca7ce6b4666c874a/13ae7/TOPSQL.png 350w,
/static/b6e77e46c1011c99ca7ce6b4666c874a/8c557/TOPSQL.png 700w,
/static/b6e77e46c1011c99ca7ce6b4666c874a/d54e4/TOPSQL.png 747w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;When I checked the plan for this TOP1 statement it was the following&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/8757e220f45b59d2c059664f2b36c4dd/471ef/BadPlan.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 28.57142857142857%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAA4klEQVR42oVQ23aEIAz0/z9yW9cuyEXcooDIZRp4qe2Lc04OkzCZBIaJPfGYPjHxF8bXiAcFUwzCSMyLgloVZONagGsJvWqqS+KcNALqrXrOFIexBkMuJzV9Q78tSs34mL5g9w3W7ZhmCecdzjNS7iHXDTEGjEzAbqTZLYxZ8GRkriR88BhqBXJOFBmVkuB95zllHMeBlH7vSim9HqgxnYm0AZ4GzXLBRgNKLhhwg27eDImXNv2CGCNtaMBn0c+muzVsW1lLX7IYMKFpE9sb/+Ay6NawIYQA51x/VuP136ZX/ACinNIuP9WNnwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;bad plan&quot;
        title=&quot;&quot;
        src=&quot;/static/8757e220f45b59d2c059664f2b36c4dd/8c557/BadPlan.png&quot;
        srcset=&quot;/static/8757e220f45b59d2c059664f2b36c4dd/4edbd/BadPlan.png 175w,
/static/8757e220f45b59d2c059664f2b36c4dd/13ae7/BadPlan.png 350w,
/static/8757e220f45b59d2c059664f2b36c4dd/8c557/BadPlan.png 700w,
/static/8757e220f45b59d2c059664f2b36c4dd/e996b/BadPlan.png 1050w,
/static/8757e220f45b59d2c059664f2b36c4dd/471ef/BadPlan.png 1185w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;This is a &quot;classic&quot; example of wrong InventSum-InventDim join, where InventDim is used as a leading table.&lt;/p&gt;
&lt;p&gt;The solution was quite simple, a custom plan was created with the OPTIMIZE FOR UNKNOWN hint, that ensured that SQL Server would not use first passed location/site values to build a plan&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;sql&quot;&gt;&lt;pre class=&quot;language-sql&quot;&gt;&lt;code class=&quot;language-sql&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;EXEC&lt;/span&gt; sp_create_plan_guide &lt;span class=&quot;token variable&quot;&gt;@name&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; N&lt;span class=&quot;token string&quot;&gt;&apos;[AX_InventSumLoc]&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;@stmt&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; N&lt;span class=&quot;token string&quot;&gt;&apos;SELECT SUM(T1.POSTEDQTY),SUM(T1.POSTEDVALUE),SUM(T1.PHYSICALVALUE),SUM(T1.DEDUCTED),SUM(T1.RECEIVED),SUM(T1.RESERVPHYSICAL),SUM(T1.RESERVORDERED),SUM(T1.REGISTERED),SUM(T1.PICKED),SUM(T1.ONORDER),SUM(T1.ORDERED),SUM(T1.ARRIVED),SUM(T1.QUOTATIONRECEIPT),SUM(T1.QUOTATIONISSUE),SUM(T1.AVAILPHYSICAL),SUM(T1.AVAILORDERED),SUM(T1.PHYSICALINVENT),SUM(T1.POSTEDVALUESECCUR_RU),SUM(T1.PHYSICALVALUESECCUR_RU) FROM INVENTSUM T1 WHERE (((T1.PARTITION=5637144576) AND (T1.DATAAREAID=N&apos;&apos;dsg&apos;&apos;)) AND ((T1.ITEMID=@P1) AND (T1.CLOSED=@P2))) AND EXISTS (SELECT &apos;&apos;x&apos;&apos; FROM INVENTDIM T2 WHERE (((T2.PARTITION=5637144576) AND (T2.DATAAREAID=N&apos;&apos;dsg&apos;&apos;)) AND (((T2.INVENTDIMID=T1.INVENTDIMID) AND (T2.INVENTSITEID=@P3)) AND (T2.INVENTLOCATIONID=@P4))))&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token variable&quot;&gt;@type&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; N&lt;span class=&quot;token string&quot;&gt;&apos;SQL&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token variable&quot;&gt;@module_or_batch&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token variable&quot;&gt;@params&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; N&lt;span class=&quot;token string&quot;&gt;&apos;@P1 nvarchar(21),@P2 int,@P3 nvarchar(11),@P4 nvarchar(11)&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token variable&quot;&gt;@hints&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; N&lt;span class=&quot;token string&quot;&gt;&apos;OPTION (OPTIMIZE FOR UNKNOWN)&apos;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The correct plan after this became the following:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/05c4b795c2f100d367ec8da2485c51aa/44fd6/GoodPlan.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 29.714285714285715%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABF0lEQVR42o1Qa2vDMAzM39+v6a/Yx41RKO3W1GniPMjDiR3n5dTJTTZsg8FgB4d0sjjJCl5f3vAeXnE5n8FuIRhj4Jwjju+4R4xi7LVoajTEqqpR1y5WKMsSjcspOu0YpBXH0PcQbYcrr9F1HZSSEBTDOCfdQkmJSkhEvKReBUn9iqiJSdEgLWpoTTWlEDw9a/QGmEaNW1JgHCc4NELgdPlAT00OSZohilMsjxWGhmW0eZbn4FRn7I4sSzEMA4Ko3bFawD4eMGaBtdYbGGPIfPzW8zz52nA8ojscYOlto7rsB0wzbYQd+74jcMkXfrK/YZcF67r6LwvRIMlK2j7393UDg/0/Lr+wbZu/l9bam7atgKQ7z/OMT+G+ygpMNQh0AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Good plan&quot;
        title=&quot;&quot;
        src=&quot;/static/05c4b795c2f100d367ec8da2485c51aa/8c557/GoodPlan.png&quot;
        srcset=&quot;/static/05c4b795c2f100d367ec8da2485c51aa/4edbd/GoodPlan.png 175w,
/static/05c4b795c2f100d367ec8da2485c51aa/13ae7/GoodPlan.png 350w,
/static/05c4b795c2f100d367ec8da2485c51aa/8c557/GoodPlan.png 700w,
/static/05c4b795c2f100d367ec8da2485c51aa/44fd6/GoodPlan.png 789w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;After the hint creation, the posting time returned to normal.&lt;/p&gt;
&lt;p&gt;As I wrote in my &lt;a href=&quot;https://denistrunin.com/performance-sniffing&quot;&gt;previous&lt;/a&gt; post the insidiousness of such cases is that sometimes people start using reindexing or statistics updates to resolve them, and its slow down the whole system without actually fixing the root of this problem. Such maintenance tasks can lead to &lt;a href=&quot;https://www.brentozar.com/archive/2017/12/index-maintenance-madness/&quot;&gt;Index Maintenance Madness&lt;/a&gt; and even Microsoft recently published some notes &lt;a href=&quot;https://docs.microsoft.com/en-us/sql/relational-databases/indexes/reorganize-and-rebuild-indexes?view=sql-server-ver15#index-maintenance-strategy&quot;&gt;about this&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Let&apos;s discuss how we can monitor such issues&lt;/p&gt;
&lt;h2 id=&quot;top-queries-monitoring-solution-implementation&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#top-queries-monitoring-solution-implementation&quot; aria-label=&quot;top queries monitoring solution implementation permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;TOP Queries monitoring solution implementation&lt;/h2&gt;
&lt;p&gt;Such problems are quite easy to fix, the main complexity is that they can hit your system unexpectedly. But the pattern is always very similar: a new TOP SQL statement that uses a non-optimal execution plan. Also, you can&apos;t monitor it using standard performance counters(for example CPU load) on SQL Server, as in most cases they may not hit critical levels(for example it may change from 20% to 50%).&lt;/p&gt;
&lt;p&gt;I tried to google a monitoring open-source solution that could handle such situations but could not find anything. So to be notified on such events I created the following Dynamics AX query performance monitoring &lt;a href=&quot;https://github.com/TrudAX/TRUDScripts/blob/master/Performance/Jobs/SQLTopQueryMonitor/dbo.AXTopQueryLogMonitor.StoredProcedure.sql&quot;&gt;procedure&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;sql&quot;&gt;&lt;pre class=&quot;language-sql&quot;&gt;&lt;code class=&quot;language-sql&quot;&gt;msdb&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;dbo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;AXTopQueryLogMonitor&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;@MinPlanTimeMin&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;@MaxRowToSave&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;@SendEmailOperator&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;axoperator&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;@DaysKeepHistory&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;62&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The idea is very simple. Every 30 minutes this procedure obtains 3(&lt;strong&gt;@MaxRowToSave&lt;/strong&gt;) TOP records from the current SQL Server TOP SQL view and if they exist in this log for more than 30 minutes(&lt;strong&gt;@MinPlanTimeMin&lt;/strong&gt;) saves them to a table. If any of these 3 statements is new, it sends an e-mail about this to a specified operator(&lt;strong&gt;@SendEmailOperator&lt;/strong&gt;). To prevent this log from growing it deletes records older than 62 days(&lt;strong&gt;@DaysKeepHistory&lt;/strong&gt;)&lt;/p&gt;
&lt;p&gt;To compare with previous statements both SQL plan and SQL text are used, so if one query is executed with different plans it appears twice in this log.&lt;/p&gt;
&lt;p&gt;As the result, if you have a new TOP statement that you have not seen before, Dynamics AX Administrators should get an email like this&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/a07ea394974c0c19293430911da0d9f9/a1dd2/Email.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 37.714285714285715%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABDklEQVR42qVSCWrEMAz0/3+X5s52E7IpbWznvo8lU0ttISxsoVQwyJLt8UiyiKILpmmC1hpVWaKqSjRNg3EcGW3bom1a9H2PYRj47HEceGYilxKFLlAaMkJRFHxxv9+xbRv2fWeCM34zsS4zpnnGsiyMdV2xmJiUzJxf8RcTXNI3ntmjwrPSR8WClBAZ+TiOWdV/TFCZdV1zr4iYhkN9VEp9ea1MzqxNXsocykAryfsEaWbAPTf3qV2CBkFEXdfxC1mWwbZteJ4H13XhOA688AI3vOLFi8w6hutHCHyf9yzLQhAE8E1MXhDzuRf0AJWepimTJ0mC1/QdYSpxfdPGKxN/4HZLkec5C6Ev9TOHT33TZxgaNl5HAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;E-mail&quot;
        title=&quot;&quot;
        src=&quot;/static/a07ea394974c0c19293430911da0d9f9/8c557/Email.png&quot;
        srcset=&quot;/static/a07ea394974c0c19293430911da0d9f9/4edbd/Email.png 175w,
/static/a07ea394974c0c19293430911da0d9f9/13ae7/Email.png 350w,
/static/a07ea394974c0c19293430911da0d9f9/8c557/Email.png 700w,
/static/a07ea394974c0c19293430911da0d9f9/a1dd2/Email.png 838w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;UPDATE 30/07/2021&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Sometimes in a “TOP query log” there were some queries that are not heavy at all, but they exist in the TOP log because the overall server load is low(for example less than 5%). To view this, I added a new section in the alerting e-mail that displays &lt;strong&gt;CPU Utilization&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/5767208b9b722b62b96f75470f99407a/4b446/CPUUsage.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 73.71428571428572%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABqklEQVR42p2Th27CQAyG8/4vB4i9CWE1jAyygATX36mH0gqKRCTL45z//Ns+Z7PZSBiEcj6fJQxDCYJA4jiWTz+nLEu5XC5yu92kqqrHwf1+/wyQao7Ho6xWK9lut0+T6uDY1+v1NWCe54YmdAFGn04nozmjcgDQsEFzRqwet7ZTR8+yTLrdrvR6Pen3+zIajWQymchwOJTxeGxkMBiY2GKxMP5sNjOanPl8Lg7IVEL/6CWJJFkB1AKip9OpySGODbjNw3eSJDGUAQaQoK2ERG61gJxhA0LcVo1vtkVb8YsygFBuNpvSarWM8AM+0mg0pN1uS6fTEc/zzCDRvu9LmqamKANoZ0jA9sbezE9Uig0tbIYGKzSDZIcfU2YQucp/a2L9uv1qtRxPy3dVfO3PTvsTHg4S6W7GUSSRCqtQFIV5PX+Bn13gRLud5Nq7RKv0l0v5Uol1UIBR/UEvYABQpl/s3L8vpdDJ2C/XvqTaFx6g/ZE+rddr84pc130PmGlT5afsdL+XVP1S/VKp8tF8VsLKW8BYaRQKhERKN1WqVQ2QCqFKlUs9fwf4DYkGfARrTw4BAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;CPUUsage&quot;
        title=&quot;&quot;
        src=&quot;/static/5767208b9b722b62b96f75470f99407a/8c557/CPUUsage.png&quot;
        srcset=&quot;/static/5767208b9b722b62b96f75470f99407a/4edbd/CPUUsage.png 175w,
/static/5767208b9b722b62b96f75470f99407a/13ae7/CPUUsage.png 350w,
/static/5767208b9b722b62b96f75470f99407a/8c557/CPUUsage.png 700w,
/static/5767208b9b722b62b96f75470f99407a/4b446/CPUUsage.png 877w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Then they can connect to SQL Server and try to analyse/optimize this statement&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/18f59c67d74423fe6560811b89e791a0/79e48/TopLineAnalysis.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 15.428571428571427%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAADCAYAAACTWi8uAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAoElEQVR42k2Pyw6CQAxF+f+/8gPY60ISFZR5dB7AEIiR4zBRY5Pb29zFaVuJXwnDE60c5t5jeo3qHhgliFtwfmBZV/bati0LXrm9yrz98q9XWima5sz1cmFMiSkrzTMxRoJ3xBAQEawVnHNZwhDDJ3cl//dKGeFQn6iPHW2+0BpbYNZavA8ForUhZEAcJs43QyeJmBbati2QfeE9fzVOE2/bu+P7I7GjZAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Top line analysis&quot;
        title=&quot;&quot;
        src=&quot;/static/18f59c67d74423fe6560811b89e791a0/8c557/TopLineAnalysis.png&quot;
        srcset=&quot;/static/18f59c67d74423fe6560811b89e791a0/4edbd/TopLineAnalysis.png 175w,
/static/18f59c67d74423fe6560811b89e791a0/13ae7/TopLineAnalysis.png 350w,
/static/18f59c67d74423fe6560811b89e791a0/8c557/TopLineAnalysis.png 700w,
/static/18f59c67d74423fe6560811b89e791a0/79e48/TopLineAnalysis.png 865w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;If the statement can not be optimized, for example, &lt;strong&gt;Execution count&lt;/strong&gt; is aligned with the current business logic and &lt;strong&gt;Execution plan&lt;/strong&gt; is optimal you can mark this query as approved&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;sql&quot;&gt;&lt;pre class=&quot;language-sql&quot;&gt;&lt;code class=&quot;language-sql&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;Exec&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;AXTopQueryMarkAsApproved&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;  &lt;span class=&quot;token number&quot;&gt;111&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Query is good, used in planning process&apos;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;examples-from-real-life-projects&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#examples-from-real-life-projects&quot; aria-label=&quot;examples from real life projects permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Examples from real-life projects&lt;/h2&gt;
&lt;p&gt;I ran this monitoring on several projects where all Dynamics AX performance tuning was made during the previous &lt;a href=&quot;https://denistrunin.com/performance-audit&quot;&gt;audit&lt;/a&gt; and got the following results:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Number of queries that need to be analysed&lt;/strong&gt; was within 100-200 queries. Basically, if you want to support Dynamics AX performance you need to be ready to analyse your system’s top heaviest 200 queries.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Duration of initial analysis&lt;/strong&gt; - it was about 2-3 calendar weeks, more than I had expected. In this period I was getting several new emails per day&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Number of fixed queries&lt;/strong&gt; - for one project it was 8. 4 queries had an incorrect plan and 4 required new indexes creation. These numbers may not seem high, but keep in mind that previously most performance issues on this project were fixed by the performance &lt;a href=&quot;https://denistrunin.com/performance-audit&quot;&gt;audit&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;What is really great about this solution is that it gives a certain level of confidence during the Dynamics AX performance optimization project. If a new SQL query appears at the TOP log you will be notified about this.&lt;/p&gt;
&lt;h2 id=&quot;some-thoughts-about-d365fo&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#some-thoughts-about-d365fo&quot; aria-label=&quot;some thoughts about d365fo permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Some thoughts about D365FO&lt;/h2&gt;
&lt;p&gt;If you have an on-premise version the monitoring will be the same. For the Cloud version, you don&apos;t have a direct access to a Production SQL Server. But the production database has a &lt;strong&gt;Query store&lt;/strong&gt; enabled and information like &quot;TOP queries for the given time&quot; can be obtained using the SAT restore with a read-only flag. The process is described in the following post &lt;a href=&quot;https://community.dynamics.com/ax/b/axinthefield/posts/using-query-store-for-performance-tuning-with-d365-f-o&quot;&gt;Using Query Store for Performance Tuning with D365 F&amp;#x26;O&lt;/a&gt;, but it looks quite complex from a practical point of view(SAT often is used for some other tasks and this restore will take some time)&lt;/p&gt;
&lt;p&gt;Probably another option is to implement the same monitoring logic in X++ and run it as a periodic batch job.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#conclusion&quot; aria-label=&quot;conclusion permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Using the described solution you can monitor your Dynamics AX SQL performance and get a notification when some new workload appears in a TOP SQL list. This is extremely useful for the cases when you have random performance problems that can&apos;t be replicated on a Test version. You can find and fix exact queries that causing problems instead of wasting time by running reindexing/statistics update.&lt;/p&gt;
&lt;p&gt;The code for this can be found in the following &lt;a href=&quot;https://github.com/TrudAX/TRUDScripts/tree/master/Performance/Jobs/SQLTopQueryMonitor&quot;&gt;folder&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I hope you find this information useful. Don&apos;t hesitate to contact me in case of any questions or if you want to share your Dynamics AX/D365FO SQL monitoring approach.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Implementing of Dynamics AX business operations performance monitoring]]></title><description><![CDATA[The blog post describes a sample implementation for Dynamics AX business operations performance monitoring and performance analysis]]></description><link>https://denistrunin.com/performance-operlog/</link><guid isPermaLink="false">https://denistrunin.com/performance-operlog/</guid><pubDate>Thu, 27 May 2021 22:12:03 GMT</pubDate><content:encoded>&lt;p&gt;Business operations monitoring is used when you have some important processes in your Dynamics AX system and you want to control/measure the performance of them. It is an activity that may be done after the main Dynamics AX &lt;a href=&quot;https://denistrunin.com/performance-audit&quot;&gt;performance optimization project&lt;/a&gt; and usually it happens when some processes show unstable behaviour. Usually, the reasons for this are the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Parameters sniffing&lt;/li&gt;
&lt;li&gt;Some external processes that overload hardware&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Also, you can get a wrong input from the users, who  are complaining that the system is slow, but refering to a wrong process. So having and discussing some numbers instead of general words like slow/fast can greatly improve the communication process.&lt;/p&gt;
&lt;h2 id=&quot;performance-log-implementation-detail&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#performance-log-implementation-detail&quot; aria-label=&quot;performance log implementation detail permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Performance log implementation detail&lt;/h2&gt;
&lt;p&gt;I will describe the implementation for Dynamics AX 2012, but probably for all other systems (AX2009 and D365FO) it will be the same.&lt;/p&gt;
&lt;p&gt;First you need to create a setup table that defines which Operations to monitor and logging threshold:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 416px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/6f40bbe99ed1958ac6fbd0f76050fe7b/b0122/LogSetup.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 57.14285714285714%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB3ElEQVR42oWS3W7UMBCF87QIngepD4EQL8ANN4gLuuWi0CJBN7ub/d84jvNrJ7EPZ9zdFgkQlj55Yo+Pz0ycvP8wM7e392aXrcxysTSnk6oB1N6jJGaavOF3qZSum7arGBtZ/xfJy6tveHV1hxevvyJTFoEnnA+YGAz+T9x/SN58XIe35N2nTUi3RTgWJuyVCYeyCcey5XxGN7/F7d9jkmitkKU/YfsWm80OLBub7Q5l75G3AUUfUDpEiu451vYMY8Uc1T2S6MZBFRpFaWBMBVPVqJsG1g0YJ4+2s8hVAfYWnXWMdUQzv9AGSpdxfRh9JKm6AZUxKLXGYX+AyhUPnzCOI2Q453A6HLHf7TEOIzQvz08554K5ObasxlLwMpLWTZimCW3bout60qHve/TWoqoq1HUdRWVu6Fxi5yxFbIzjOfIk2PHXyeb15xlubr5gdj3D3f13KJaZ062UNp+nmKcpNCuRNWmBUNDlnu4lR4bn64gOpbw0XWBB1tka2TLDdr3BmrCNUVzaIE/Kc0EOCkGeFttg7RAF5ZuCPvZmtcqwWqxYVhs3+KB50RQTxdWRghcXsi/IkJyePzBeFsJZkA7F1cOPB2zZ/Mtt4XxKShOXj+vPgoIIOjc+OfwFaKpJou7F140AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Log setup&quot;
        title=&quot;&quot;
        src=&quot;/static/6f40bbe99ed1958ac6fbd0f76050fe7b/b0122/LogSetup.png&quot;
        srcset=&quot;/static/6f40bbe99ed1958ac6fbd0f76050fe7b/4edbd/LogSetup.png 175w,
/static/6f40bbe99ed1958ac6fbd0f76050fe7b/13ae7/LogSetup.png 350w,
/static/6f40bbe99ed1958ac6fbd0f76050fe7b/b0122/LogSetup.png 416w&quot;
        sizes=&quot;(max-width: 416px) 100vw, 416px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Then you create a table that stores performance log data(like Start/End time, Duration, Number of lines, User, etc..)&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/3dfed4e3eef09b7cd95e1800cc34ed30/4c42d/LogData.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 28.57142857142857%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABIElEQVR42m2Q6VLCQBCE8/4Pp6IiqEA4AmyyOffIReLncP6w3Kqu7tnundqZYLJIsM5jfEvdneiG8YH29L/+i7NnXM0xKQhmK8UhTkldT2qv0KZD2+6m26sW/36XXvgKfWfJHYuaoHaWtmkwlaERHscBZy3WmIu2RrTU4zBgygrnHN47au/pu07eVTKhYx2uUXFC8LJJeIsynkPF8zrmdZfytNwLayY3b6YqgWFZdsy1E+6ZHkqmx5KP2JEZh04UaZYTzJcRy23M+zwkli+XfuAzjIjikp3KWe0S9rrikBrcict4VjhKxJeMKjxZXnI+w/hD8L3YsI0U4ToizQ1ZYflaSHNZsIozwk1Eogt0ViG7l+W39AOX+pw3rsH5+tHwF0T4yBJHcpDRAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Log data&quot;
        title=&quot;&quot;
        src=&quot;/static/3dfed4e3eef09b7cd95e1800cc34ed30/8c557/LogData.png&quot;
        srcset=&quot;/static/3dfed4e3eef09b7cd95e1800cc34ed30/4edbd/LogData.png 175w,
/static/3dfed4e3eef09b7cd95e1800cc34ed30/13ae7/LogData.png 350w,
/static/3dfed4e3eef09b7cd95e1800cc34ed30/8c557/LogData.png 700w,
/static/3dfed4e3eef09b7cd95e1800cc34ed30/4c42d/LogData.png 896w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;And you need to write a code that actually creates log data(using a helper class):&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;c#&quot;&gt;&lt;pre class=&quot;language-c#&quot;&gt;&lt;code class=&quot;language-c#&quot;&gt;    DEV_ProcMetrics     procMetrics = DEV_ProcMetrics::construct();
    ;
    procMetrics.beginTrace();
    // HERE MAIN OPERATION;
    // can use procMetrics.incLineCount();
    procMetrics.endTrace(DEV_BMLogOperation::SalesInvoicePost,
                 int642int(salesParmLineLocal.RecId), // or procMetrics.getLineCounter()
                 &amp;quot;document ref&amp;quot;);&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;practical-examples&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#practical-examples&quot; aria-label=&quot;practical examples permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Practical examples&lt;/h2&gt;
&lt;p&gt;Creating the log is quite a simple task, the main difficulty is how to analyse this data to get some valuable insights. And for this purpose Power BI is a great tool, that allows you to view the data from different angles. Let&apos;s check some practical examples:&lt;/p&gt;
&lt;p&gt;The first one is the case where the users complained about slow production journal posting. To examine this problem we implemented a log and then analysed average posting time. There was some slowness around 1am and it happened almost every day:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/404a35946ceb8193cea00e7101ce10ec/5b4a1/DailyPosting.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 79.42857142857143%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAYAAAAWGF8bAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACcUlEQVR42pWU22/TMBTG+zfzCjwxiQeQeEFCCBAIIZ54ADRt2kVjElBtjJZt7NZ162VZ2qZpkuae2Ek/zrFXOnEZw5LbxLF/5/uOj10xTROGYeDM6KHfH8CyLPDYyLbhuC68IIDrOAjDEFe1QhYQQqAipUCaCYSRUB8ml2dlGSZRhP9pFf6JYgHHywCRQVpD5McNRBsb8KtVpK2WnjmZXB8YJCX6zR7ilSUE9TqidhuSlJVFcS1IeSmYAnrjjPIX/S6EXy4GrhLouBnKcjIDjv0cAyvWC4vyn/aSVKIoZnOM8xBSlhpYyFwrHFwA/wJjwFTFyE2R57N0nLb9GTCOQyX5vBf9ETh9tZ0UcSLVs2UnVBkaKESB3X1nZjnPEnTOQnSN8Eqg2Y/hB7q02E0QUrmlhVK6d+Tg3IyU8kqaxiriVOE00mUY2+mcBQrCbXtvhA4JaDQ9nJDd2vYQ9V0bBw1Xb0pCVhyi/5qrqdqBlWD/yCWFOSRt2vPXR5hf7uLJywMsrHbxdqGN5Q8Gqpt9DcwpD62OrxcPk5+nhsFs8xtF5358OsZmzcLtu19w49ZnzN2vYX6pg5tzm3j49DsWCV5hFWxpqz5UCpqtMYZ2CovAuSiVjdqOjY2tAU5avgI/e3WIO/e+YnXdwOMXB3i32MaDRzt48/5UKxS0sNEcKyAD2B4HGY4StYM8xp3fuSLWP5lkuUOBEyyv0cVCdbj20VSBtWXaKY+Kmxsn//DYU8+8gAGzCqDgdKu0uz71QOe8LFVqSvpnt8oyn8XpYBxntGhCmyOR5TrIyPEoBRYiOt+50LcTb15O34WUFxdTRmMFfgDkicbFWJ2d0QAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Posting journals&quot;
        title=&quot;&quot;
        src=&quot;/static/404a35946ceb8193cea00e7101ce10ec/8c557/DailyPosting.png&quot;
        srcset=&quot;/static/404a35946ceb8193cea00e7101ce10ec/4edbd/DailyPosting.png 175w,
/static/404a35946ceb8193cea00e7101ce10ec/13ae7/DailyPosting.png 350w,
/static/404a35946ceb8193cea00e7101ce10ec/8c557/DailyPosting.png 700w,
/static/404a35946ceb8193cea00e7101ce10ec/5b4a1/DailyPosting.png 831w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Further analysis showed that during this time a complex SQL Agent SSAS cube update job was &lt;a href=&quot;https://github.com/TrudAX/TRUDScripts/blob/master/Performance/AX%20Technical%20Audit.md#sql-agent-jobs&quot;&gt;executed&lt;/a&gt; and this slowed down journal posting.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 506px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/c4c95f39ecaf299bc91527b5f0be4a0d/29f4e/AgentJobTimes.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 14.857142857142858%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAADCAYAAACTWi8uAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAu0lEQVR42k2MTU/CQABE+///jolevAloPJBI2sBu9wubursCZUtDysV9LhfjJG9mDpOpUhrx3rPZ1IQQGccLY7qQUmKaJnQrUFLQii3fwXObr/R9T900aG3pug5rHG6/53RKVDFGhmFASlkGmlYqjLElJa7zPL8Lnl4bHleFZc3DokZ/9gixY55n/ivnTBV8IJ3PmHLmnEMrg1Ka4+HIdL3x9tGyKrystyzWO5alf8UDztq/w5x/7n4v/AIl1twbUkwQVQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;SQL Agent job&quot;
        title=&quot;&quot;
        src=&quot;/static/c4c95f39ecaf299bc91527b5f0be4a0d/29f4e/AgentJobTimes.png&quot;
        srcset=&quot;/static/c4c95f39ecaf299bc91527b5f0be4a0d/4edbd/AgentJobTimes.png 175w,
/static/c4c95f39ecaf299bc91527b5f0be4a0d/13ae7/AgentJobTimes.png 350w,
/static/c4c95f39ecaf299bc91527b5f0be4a0d/29f4e/AgentJobTimes.png 506w&quot;
        sizes=&quot;(max-width: 506px) 100vw, 506px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Another interesting case was when the users complained about slow Dynamics AX Sales order posting. This coudn&apos;t be replicated on Test system and we implemented a log for 2 main processes that took place when the user pressed a &lt;strong&gt;Post&lt;/strong&gt; button. It was the actual posting and a printing report to a printer. Analysis showed that most of the time system was busy printing documents and this time increased during some hours (like 9am on the graph below)&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/179feff2b857930ddb19fb64bb8113ea/5d36b/PrintTime.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 52.57142857142857%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABhElEQVR42p2TyUvDQBjF5/8WPHrQ1g0Ft5OCJxFB8CYepChuB7dSabQKrqUzmSyTNNvzm2kSaWw9OPDjSyaTN9+blzDf96CUgi09cOFBCEnVRa/HwTlHmqYYNfQ7UtqIoggqUEiSxKxlK2v7qM/t4vP1Bko+wOXXcEULQeCZxeNGlmVGQOP7PjzPhe95YLtbE7g8nEC3NQ1hzYC3qT4tIo16+YvJSEHdURzHpXgxx06vAvxnBGTTcRwjWgjqyg52psAfF6irZWKpxO6sQNB8IM4Lk0OChV1HSri5sB6scdxA6Nyh797/InRukfS/RgoWXWlRbVXf6xl2eNREEgmksV1BEq45yyR8Jz6GiNQbYtosy9KBWA5rns1DtGsUCFVrroS364QOqQZuVamb8OznVWTp8JfAuo+b5oH9sp6zAdFZog46ubf0z3AK66Xg3vYkerQbt2bznWsmjKTfLc+usDM4x8zY/LmuCCpxQUmeEKdQnCoRygso34Z0XJOg/iuqCY/r8BvkLkEzM23b2QAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Print time log&quot;
        title=&quot;&quot;
        src=&quot;/static/179feff2b857930ddb19fb64bb8113ea/8c557/PrintTime.png&quot;
        srcset=&quot;/static/179feff2b857930ddb19fb64bb8113ea/4edbd/PrintTime.png 175w,
/static/179feff2b857930ddb19fb64bb8113ea/13ae7/PrintTime.png 350w,
/static/179feff2b857930ddb19fb64bb8113ea/8c557/PrintTime.png 700w,
/static/179feff2b857930ddb19fb64bb8113ea/e996b/PrintTime.png 1050w,
/static/179feff2b857930ddb19fb64bb8113ea/2cefc/PrintTime.png 1400w,
/static/179feff2b857930ddb19fb64bb8113ea/5d36b/PrintTime.png 1467w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;This allowed us to switch a conversation from &quot;AX performance&quot; to &quot;Network printers performance&quot; and involve proper people to resolve this.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#conclusion&quot; aria-label=&quot;conclusion permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In this blog post I provided some samples on how to implement performance monitoring in Dynamics AX and analyse performance of Dynamics AX operations with Power BI. Sample files(xpo that contains log table, form and a helper class) can be found in the following &lt;a href=&quot;https://github.com/TrudAX/TRUDScripts/tree/master/Performance/Jobs/TimeLogTable&quot;&gt;folder&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I hope you find this information useful. Don&apos;t hesitate to contact me in case of any questions or if you want to share your Dynamics AX/D365FO operations monitoring approach.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Improving Dynamics AX2009 / AX2012 logistics performance by denormalizing InventSum table]]></title><description><![CDATA[Describes a sample approach of improving Dynamics AX 2009/2012 performance by downgrading D365FO InventSum table change]]></description><link>https://denistrunin.com/ax2012-inventsumfields/</link><guid isPermaLink="false">https://denistrunin.com/ax2012-inventsumfields/</guid><pubDate>Thu, 15 Apr 2021 22:12:03 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;InventSum&lt;/strong&gt; table(Oh-hand inventory) is one of the frequently used tables in AX2009, AX2012 and D365FO logistics module. It is also often one of the top reasons for various performance problems due to the structure of the related tables. All quantities and an Item code are stored in &lt;strong&gt;InventSum&lt;/strong&gt; table, but the actual dimension values are stored in &lt;strong&gt;InventDim&lt;/strong&gt; table&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 569px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/1ab6e9dbb4b4859f8c017084c3ce4d36/854dc/InventDimStructure.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 34.285714285714285%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAAA7EAAAOxAGVKw4bAAABJElEQVR42m1S2WqEQBD0/7/LxSdhxeNFAyK4Gu/71spUZyUJRGhGe6qrqrvV9n3HsiyY5xnruuI4TuyHyql3CXVHzHme2LZNMIzfuTvPnJZ8Zt9E14Wu6+AHH4iiCJMSmOcFfd9jVqSdOsuqwjRNGMcRQRDAsiwURSHfxDVNA+2VpAjDENbziTRNkec5KlV4O6YIyZjzPA+O48AwDCGs61pISEZcWZbQ4iSB67rQdR22bcsl26Qq3RBI0TiOxY1pmng8HnKSkO1SnDVt20KjepZleKkCulvfc2MQPAyDOKQTktMZXfq+L7lLjYrBhwa0uu2EqCgrAXB2jFFdyuwUST9OAqbDW+jugkFRnjLDdd3eoP3PFpflZ8ub2t79N/wXd1es/wIaDxYOZm894wAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;InventDimStructure&quot;
        title=&quot;&quot;
        src=&quot;/static/1ab6e9dbb4b4859f8c017084c3ce4d36/854dc/InventDimStructure.png&quot;
        srcset=&quot;/static/1ab6e9dbb4b4859f8c017084c3ce4d36/4edbd/InventDimStructure.png 175w,
/static/1ab6e9dbb4b4859f8c017084c3ce4d36/13ae7/InventDimStructure.png 350w,
/static/1ab6e9dbb4b4859f8c017084c3ce4d36/854dc/InventDimStructure.png 569w&quot;
        sizes=&quot;(max-width: 569px) 100vw, 569px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;A typical system request is to get on-hand data for an item with some dimensions, for example, the quantities of Item AA1 stored on warehouse WW1. And depending on the selectivity of these values, the system may use different execution plans. Very often executing such queries can lead to parameters &lt;a href=&quot;https://denistrunin.com/performance-sniffing&quot;&gt;sniffing&lt;/a&gt; and not optimal plans.&lt;/p&gt;
&lt;p&gt;A typical resolution is to use literals in the query(the query will be slower and you need to maintain statistics) or to provide a plan hint, but these actions require time and constant monitoring from DBA.&lt;/p&gt;
&lt;h2 id=&quot;the-solution-from-the-cloud&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#the-solution-from-the-cloud&quot; aria-label=&quot;the solution from the cloud permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;The solution from the cloud&lt;/h2&gt;
&lt;p&gt;In D365FO Microsoft finally decided to resolve this problem and added all dimension fields into the &lt;strong&gt;InventSum&lt;/strong&gt; table.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 288px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/1e3a451d711d073cc40928942492a8c1/477c9/D365FOStructure.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 228.00000000000003%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAuCAYAAAAoaDnGAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAFz0lEQVR42p1XW49TVRSumvgv9NEHnzVGgoZHExPj9cnLo/HFRAigkWCiIQ4SESM4YSDcRCRBBMQEIzAyMDKXttN7z/3ec9qeXmam7cx0Or18rr07DI7DDHNosrrPaZvvrG+vb317NXTi7H788edxXLh8BOcvfofzvx3CzxcO4tyvB/k6dOYbDJ4cwJETA/j++AB+PPk1vx88xa4H+tcUx346wCP0/ocf4/a1L/HX73tx9/ouhP/eAzm2D0ZyHyZHvsAr7+3A869+gm3v7Kb4FNve2oWX396Nl97cia2vb8eWN3bixde24+kXPsBTFKGvDhxGxRtG2RtBJT+KRnUC7YUYus0YFmpRjEfHMDoxjvHIJCanIpiIhjFG8U94AmMUE7EoIvEIbtwewXWK0OETl2BYRRSK06hMz6O11MXCYpfWHjpdoNdjQW/oX6+8lq/739//ODR46jKai4srH6RSCaiqDF3XkE4lkc1kkYjFkU5nEJ+KoTE3x3/X6XTogV0e3eWVRWjo9BUCbK0AxuNxqJIEy3aQcxw4Tg4L85R5q4V5AuutSnPtK3T0zJVVGcZiMQIUISsqNEWBphtoNObWUl4fcDXlTCYDQ1UgiDLEbBayrMB185wWi8CA4XAYqizxDA3DgmlZEAUBQlbEQrP/OwbMqN+LDQHT6XSfsqpB03RIggTHtmER8OJ/9nrDDBsLTXSWHzRFRdE1DYKkUKVNSLTGYkkomgHb9pDPF6hgObiFIjTDhOsV0Gp30O72eKzJUMik4NoGSjkLniYjp6uoVUpoTJdRp7VeLmDGz6NW9TFTouuyv2pvQ98ev4ir6RKGtTpuGvM4ez2Mq5MyTt+RMXQtil9GJdx1W7hjzeOWtcBjxG7iljmPEXZNcUOtU9R4hD7afw6hHWN4cm8MoT0JvHvkBrYdDuOZQzK2DCnYekzGc4Minj2YxmOfhfH451GKyKr1iT1TKxH64eQlpL0a9OkWrFoXt8ajGIkIuCu5uBkRMRxTMRyVMZo26fsO1EoTWnVx3Vi7h6Q9h6rrFzzYtH8a3ecMg/ZS552yqSrPNZu4t60pko1GGvSKRaowE7cIRdVJ4PRZ3qd+JdPorR9rMmStpxNgznMhixJMErdGMmIPMTWT93SgThGoK0yiXPB9aKoKhTJzyCQ0mbSZFlDyS8t93dscYDKZhEkU84UCz1AhIIkeIlNvZ8jK/FJAQNZ6jLLreZBEkfpao6CuoVas1+ewtLQUjDIDtDjlIoGoyJKxKoqGUtHfMLMN7et+UURkUmkC1B9ajHUBmWMbRK9ULsMi7Wm0n7pqbsppHgiYZVUmQDvn8L3LJFPcxmzTof1rBwdkVWYZsmoqsswpM9f2yLUfmbJOAHYuB5kOKzErQCT5MP11Oo9wBPSFrXFhW9TDoiDCIXCVsi351YdW+sHCpmK4yxkKJOZkkrRJxWm3H3EPbcvmGbFD3iOBq+xIpRaslCvBAZmwc1RhiagmaFJglNPpLBd2s7m4CUA2OTRbqwANomzTKaeQfQkZVhQZc40GOkS5TQdSIMBEIgGDKPokbGZZ7Bj1XJe6ReUPatTnHmIO/wMURYHr0CEQRlvIiPxYZeJmgPV6IxhgP0ONZ8goS4LMhyaTJMQO+5nZWjDAVCrFzcFxc9wPGSAzWl5pWqdnZoIBZulQsmhKKFUrfPpilPMkHYfGOzaSzMzMBgNM0pCp8dZzSIcZXmXW0xJ3bwWztYCUuWyoKEVqPeY2MlF2bAuWadGso6M6PR0MkBksO6RcMlhmDJkU3dPQyRxHowfN1urBi8Io54sF3susKKzCBoGaNI3VGwF1GE/EuWwYINs7dtDbRJcBMqFXqtVggDKBMEAvn+enHptcmaB1TeeUA+9hJBLhBlss+STsPmUmFwaYc2wKl+bBXrBe5rKh7uBunRG5lcnUNcwnS8UyNvpLsAZQpW7w6L/JbL2OHIlZJfrVShU+2ZdP++rfA1wnw38BzmIrZpGCByIAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;D365FOStructure&quot;
        title=&quot;&quot;
        src=&quot;/static/1e3a451d711d073cc40928942492a8c1/477c9/D365FOStructure.png&quot;
        srcset=&quot;/static/1e3a451d711d073cc40928942492a8c1/4edbd/D365FOStructure.png 175w,
/static/1e3a451d711d073cc40928942492a8c1/477c9/D365FOStructure.png 288w&quot;
        sizes=&quot;(max-width: 288px) 100vw, 288px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;So SQL Server doesn&apos;t need to decide which table to scan first - &lt;strong&gt;InventDim&lt;/strong&gt; or &lt;strong&gt;InventSum&lt;/strong&gt;, you can apply all filters on one table. You probably need to tune the proper indexes, but it is a less complex task compared to choosing a proper execution plan.&lt;/p&gt;
&lt;p&gt;Let&apos;s discuss how we can use the same approach to increase AX2009 or AX2012 performance.&lt;/p&gt;
&lt;h2 id=&quot;improved-version-of-inventsum-table&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#improved-version-of-inventsum-table&quot; aria-label=&quot;improved version of inventsum table permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Improved version of InventSum table&lt;/h2&gt;
&lt;p&gt;To add new fields to &lt;strong&gt;InventSum&lt;/strong&gt; table you need to change the following objects:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Object&lt;/th&gt;
&lt;th&gt;Change description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;InventSum table&lt;/td&gt;
&lt;td&gt;Add new fields. Override insert and update methods. Add required indexes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;InventUpdateOnhand class&lt;/td&gt;
&lt;td&gt;Change updateInventSumSimple and sqlUpdateInventSumStr methods that use direct SQL to update InventSum records&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;InventSumDelta&lt;/td&gt;
&lt;td&gt;Add new fields, Override insert and update methods&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;InventSumDeltaAggr ..views&lt;/td&gt;
&lt;td&gt;These views are used to create InventSumDelta aggregated records&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A new job&lt;/td&gt;
&lt;td&gt;Create a new job to fill the initial data&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;(D365FO used SQL Triggers to fill these fields, but probably it is not the best solution)&lt;/p&gt;
&lt;p&gt;After that, you need to find places where &lt;strong&gt;InventSum&lt;/strong&gt; is used and change the filter using the following macro.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/efd0b67a729088a9ce82c173651f0f4e/748b0/FilterMacro.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 25.71428571428572%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAYAAABFA8wzAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABHElEQVR42lWQ206DQBBA+/+/ZIw1adVEqw+tILaWAgsLhQLltqVcjtsaY9zkJJu5nJnMZPpiM311eFh63N4tmL1umS0djasRzFYeN8877t/WPBoe8+WO6eJT96yZr1yeTF/Hhca//if7MET6AVIIwtAlyDycg42XOsjcx8tcRCpIyoisTqjaI825RnUNJ41qK6pTQdOWKB2fjOPI5SVxTHrMSOuUIA+Iy5hCFxb1kaK5UGhZrZsralXRnTv6c88wDFf40fwJYy2s6opcb7yxNji2Q9Mowq2NZVq4O5eu66nLiuBri/lhYb4bRFFEmmV0ffdfmCQJmU5I18U0DOJ9zDiMHKIQIXzyLL8u0aoTiZTIQBLoUyml9KCOX8835VJ11EB23dAAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;FilterMacro&quot;
        title=&quot;&quot;
        src=&quot;/static/efd0b67a729088a9ce82c173651f0f4e/8c557/FilterMacro.png&quot;
        srcset=&quot;/static/efd0b67a729088a9ce82c173651f0f4e/4edbd/FilterMacro.png 175w,
/static/efd0b67a729088a9ce82c173651f0f4e/13ae7/FilterMacro.png 350w,
/static/efd0b67a729088a9ce82c173651f0f4e/8c557/FilterMacro.png 700w,
/static/efd0b67a729088a9ce82c173651f0f4e/748b0/FilterMacro.png 868w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;There is no unified framework for this, so I suggest running a Trace Parser for critical system operations and replacing only them.&lt;/p&gt;
&lt;h2 id=&quot;testing-the-performance-change&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#testing-the-performance-change&quot; aria-label=&quot;testing the performance change permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Testing the performance change&lt;/h2&gt;
&lt;p&gt;I tried to test the performance change on the standard AX2012 DEMO VM with the following job that calculates Item quantities per Location:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/8735cdf11f4b4a2d4dea2e2addf934d4/97655/TestPerfJob.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 54.85714285714286%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsTAAALEwEAmpwYAAABuUlEQVR42pWS627TQBBG8/7vw0VFBKoKqoo7FRCSNna86107rhPHXt+THMYOEj8qoB3p847s0fHMfDt5+UEx/RSKVry4+M70nTfm048rXn/WvPqiOHu/4vnVkrOrGU/ffOPZ2x88ubg+5ZczeT/n/Drk/KtmspjdopTBhiH+coanPfxI4dkVP82ccGtwZUOW7Wibin2/p+/7++q6UZM0TXHOoQJFVlSEJiHdOnJXEicRhSt4TEyGx/AHYw1t2+HfetwlyfhRK83N/Iayqui6UyeSwPH4H6AUR5GlaTrW6y15XpPcubHzpmlo6lqgJbWAj3khvOMDOjRmLLQmx1umLBZL4iimFmBdNfRt+8iRBXgQYLJ2+J4mFJOiKCKOE3ay06G7w+FwktQdf+ufwCE2m4rAX2NCQyg71ErMyjIqVwm0ljWU4nb7sA6HKEuHNgplpEsboq0m0AFBGGDXRtzPKaqCLJddl3KV+pZu39HuW/pDfx+YFzm+8gkiwypcoawisAG+Hs5ohGQuY5tv2BZbXCvr6MS0Tkzrmz9Aa+14Ma2JSWJHolPq3Y4i3dAVjl7GrMp6HHvQ33z+Bew5SC1uqdD8AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;TestPerfJob&quot;
        title=&quot;&quot;
        src=&quot;/static/8735cdf11f4b4a2d4dea2e2addf934d4/8c557/TestPerfJob.png&quot;
        srcset=&quot;/static/8735cdf11f4b4a2d4dea2e2addf934d4/4edbd/TestPerfJob.png 175w,
/static/8735cdf11f4b4a2d4dea2e2addf934d4/13ae7/TestPerfJob.png 350w,
/static/8735cdf11f4b4a2d4dea2e2addf934d4/8c557/TestPerfJob.png 700w,
/static/8735cdf11f4b4a2d4dea2e2addf934d4/97655/TestPerfJob.png 819w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The VM doesn&apos;t have much data and in order to compare the difference I measured the number of &lt;a href=&quot;https://github.com/TrudAX/TRUDScripts/blob/master/Performance/AX%20Technical%20Audit.md#get-top-sql&quot;&gt;logical reads&lt;/a&gt; to perform the original(with &lt;strong&gt;InventDim&lt;/strong&gt; exists join) or improved version(just &lt;strong&gt;InventSum&lt;/strong&gt; table) statements&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/889097b3d907ba58f3c7b19ae4d4a3f0/77800/TestPerfResultSQL.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 46.857142857142854%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABgUlEQVR42nVSi07DMBDb//8UEtIYA8Rzk8ZgMFjfHUmb5tEmbc0lDAQCIlnnplfHF3dydLHB9HqHs1WK6cUa0/kKp8sY8+UO56sM5/cpZssUx1dbnNw8Yr7YYXa3xekBs1uqi1dcrvOAyWq9BSv3yPIMknN0skHBC5QVoS5QSR6ekzIFF294E3s0SqA1Bs45YBwxDsMXJjkT8CuKYyilAs+LGlGUI04i4gUYY9AkoLWGIhjivtdaGwS/r0lxEMyyDPogaO1IgiWeNs+IdhHiKAkiOfXUVY2BnDjXo+97WPqm67rAfwkao+nFCGU6tJ1BJSqwioFxFjivOUQjAhop0bYfroVoSNT+JWjInUNclJCdhLI01uDQ9obQErfQTof63/o5MjkchhEv2xKbh2ekSQpRN2E8S2MpqX4r+GD+FST7dMvgvEKSJLSXIqawSvoLCgonSekAIUIgfkxJY2s6pGlk2Pd3+00wD41t21P9SNI3jJSir5/oyZEPwB3qJ/fwve+VSbA+a0PqSgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;TestPerfResultSQL&quot;
        title=&quot;&quot;
        src=&quot;/static/889097b3d907ba58f3c7b19ae4d4a3f0/8c557/TestPerfResultSQL.png&quot;
        srcset=&quot;/static/889097b3d907ba58f3c7b19ae4d4a3f0/4edbd/TestPerfResultSQL.png 175w,
/static/889097b3d907ba58f3c7b19ae4d4a3f0/13ae7/TestPerfResultSQL.png 350w,
/static/889097b3d907ba58f3c7b19ae4d4a3f0/8c557/TestPerfResultSQL.png 700w,
/static/889097b3d907ba58f3c7b19ae4d4a3f0/77800/TestPerfResultSQL.png 855w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;I got the following results:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 663px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/d9b7e9980ffbfc3d2721f4beca2b6f66/0786c/TestPerfResult.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 17.71428571428571%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAYAAACOXx+WAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAA40lEQVR42jVQy46DMAzk//+nh91j/2B7MYQmBBoakpbXagEFU3mdqLU00nhkj8bOhmGgeZ4plq403RpDz/5J4zhS3/fknKdpmt7c8ewvbdvKsxU5/6CR9fJ8psvXN1mtKROFQGNa3BHRO4elKBHyAtkccwDMc4GVqlAIkSClwnXdMISAnCHBXH7wkRdH5FlT36g1LXW2S0mUUlTXdUoQueLUWtfERlSxxua0LCun3OhTA1+0/C2JZ7wE1nZwHAjee9BaJxhjQEoJV0bkUYv9/W6BzYDfBLwPrxBAnk7XhvHad/gHAlIlSd1d84AAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;TestPerfResult&quot;
        title=&quot;&quot;
        src=&quot;/static/d9b7e9980ffbfc3d2721f4beca2b6f66/0786c/TestPerfResult.png&quot;
        srcset=&quot;/static/d9b7e9980ffbfc3d2721f4beca2b6f66/4edbd/TestPerfResult.png 175w,
/static/d9b7e9980ffbfc3d2721f4beca2b6f66/13ae7/TestPerfResult.png 350w,
/static/d9b7e9980ffbfc3d2721f4beca2b6f66/0786c/TestPerfResult.png 663w&quot;
        sizes=&quot;(max-width: 663px) 100vw, 663px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;On the DEMO VM &lt;strong&gt;InventSum&lt;/strong&gt; and &lt;strong&gt;InventDim&lt;/strong&gt; tables have similar size, and even in this case the performance difference is 4x. But if you have a &quot;growing&quot; dimension(like Batch, Pallet, Serial number, LP) and run a  periodic &lt;strong&gt;InventSum&lt;/strong&gt; cleanup, &lt;strong&gt;InventDim&lt;/strong&gt; table will have more records and the difference will be bigger. Another important advantage is that filtering by just one table may resolve some parameters sniffing issues caused by joining these 2 tables.&lt;/p&gt;
&lt;p&gt;As for drawbacks, you need to create several new indexes on &lt;strong&gt;InventSum&lt;/strong&gt; table. But these indexes will be updated only when a new dimension is created and not during regular quantities updates.&lt;/p&gt;
&lt;p&gt;So I don&apos;t see any major drawbacks, except the one, that this modification is not a part of the standard AX2012 application(that could have saved thousands of hours spent on various performance tasks by developers, DBA and managers)&lt;/p&gt;
&lt;h2 id=&quot;summary&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#summary&quot; aria-label=&quot;summary permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Summary&lt;/h2&gt;
&lt;p&gt;Adding fields to &lt;strong&gt;InventSum&lt;/strong&gt; table may improve AX2009/AX2012 performance and resolve some parameter sniffing issues. It is not a simple, first-priority modification and probably takes a week to implement, but may be considered if you plan to continue to use AX2009/AX2012 application(after the main &lt;a href=&quot;https://denistrunin.com/performance-audit&quot;&gt;perfromance audit&lt;/a&gt;). Also it is quite important that it uses a solution from D365FO, so it will not cause any problems during the upgrade.&lt;/p&gt;
&lt;p&gt;A sample code for AX2012 used in this post can be found &lt;a href=&quot;https://github.com/TrudAX/TRUDScripts/tree/master/Performance/Jobs/InventSumFields&quot;&gt;here&lt;/a&gt;, it may be used as an initial template for a similar modification.&lt;/p&gt;
&lt;p&gt;I hope you find this information useful. As always, if you see any improvements, suggestions or have some questions about this work don&apos;t hesitate to contact me.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Implementing Dynamics AX 2009/2012 database cleanup]]></title><description><![CDATA[Describes a custom framework for performing a periodic database cleanup]]></description><link>https://denistrunin.com/ax2012-sqldelete/</link><guid isPermaLink="false">https://denistrunin.com/ax2012-sqldelete/</guid><pubDate>Thu, 11 Mar 2021 22:12:03 GMT</pubDate><content:encoded>&lt;p&gt;One of the tasks in Dynamics AX 2009/2012 system performance maintenance is performing a periodic database cleanup. In this blog post, I describe a new framework for implementing such tasks and provide some examples.&lt;/p&gt;
&lt;p&gt;First, let&apos;s discuss why we need a custom code and what are the pitfalls of standard cleanup methods.&lt;/p&gt;
&lt;h2 id=&quot;a-standard-way-to-delete-from-a-large-table&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#a-standard-way-to-delete-from-a-large-table&quot; aria-label=&quot;a standard way to delete from a large table permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;A standard way to delete from a large table&lt;/h2&gt;
&lt;p&gt;There are a lot of standard cleanup procedures already implemented in the system. A good overview for the latest D365FO version can be found here &lt;a href=&quot;https://community.dynamics.com/ax/b/axinthefield/posts/f-o-data-management-reviewing-large-tables-and-database-growth&quot;&gt;Reviewing Large Tables and Database Growth&lt;/a&gt; and &lt;a href=&quot;https://docs.microsoft.com/en-us/archive/blogs/axsa/cleanup-routines-in-dynamics-365-for-finance-and-operations&quot;&gt;Cleanup routines in Dynamics 365 for Finance and Operations&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In these procedures you will usually see the following code to perform a &quot;delete from table&quot; operation:&lt;/p&gt;
&lt;p&gt;A &quot;&lt;strong&gt;while select&lt;/strong&gt;&quot; loop:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;select&lt;/span&gt; MyBigTable
   &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MyBigTable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;CreatedDateTime &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; cleanupDate
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    MyBigTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;delete&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;    
&lt;span class=&quot;token comment&quot;&gt;//you need to add ttscontrol here, for example, a commit on every 100th record&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This approach can work for small tables, but if we need to delete a lot of records, it takes a lot of time, producing a load to the SQL server.&lt;/p&gt;
&lt;p&gt;Another way to implement a delete is by using a &lt;strong&gt;delete_from&lt;/strong&gt; command:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;delete_from MyBigTable
    &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MyBigTable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;CreatedDateTime &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; cleanupDate&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This statement is fast, but the command &lt;strong&gt;delete_from&lt;/strong&gt; can &lt;a href=&quot;https://denistrunin.com/understanding-sql-blocking&quot;&gt;block&lt;/a&gt; the table while running, so you need to run it only during a system downtime.&lt;/p&gt;
&lt;p&gt;Both these methods work only per one company, so you need to run a separate cleanup job for each company and that creates a setup overhead.&lt;/p&gt;
&lt;p&gt;In a lot of performance audit projects, I asked people why they didn&apos;t run standard cleanup procedures and the typical answer was: &quot;We tried to run it a year ago, then it hung, users started complaining about system performance, and we cancelled it&quot;.&lt;/p&gt;
&lt;h2 id=&quot;improved-version-of-delete-from-a-large-table-operation&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#improved-version-of-delete-from-a-large-table-operation&quot; aria-label=&quot;improved version of delete from a large table operation permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Improved version of &quot;delete&quot; from a large table operation&lt;/h2&gt;
&lt;p&gt;So, in order to run cleanup procedures without affecting users, we need a fast and non-blocking way to delete records. Below you can find a sample implementation for this.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;sql&quot;&gt;&lt;pre class=&quot;language-sql&quot;&gt;&lt;code class=&quot;language-sql&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;IF&lt;/span&gt; OBJECT_ID&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;tempdb..#recordsToDelete&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;IS&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;NOT&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;NULL&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;DROP&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;TABLE&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;#recordsToDelete&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;IF&lt;/span&gt; OBJECT_ID&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;tempdb..#temp_hash&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;IS&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;NOT&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;NULL&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;DROP&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;TABLE&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;#temp_hash&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;CREATE&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;TABLE&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;#temp_hash (RECID   BIGINT)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;declare&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;@step&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;declare&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;@isLastStep&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;WHILE&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;@isLastStep&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;BEGIN&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;select&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;top&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100000&lt;/span&gt; RECID &lt;span class=&quot;token keyword&quot;&gt;into&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;#recordsToDelete&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;dbo&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;MyBigTable &lt;span class=&quot;token keyword&quot;&gt;AS&lt;/span&gt; hashtbl            &lt;span class=&quot;token comment&quot;&gt;--TABLE HERE&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;WHERE&lt;/span&gt; hashtbl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;CREATEDDATETIME &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;GETDATE&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;IF&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;@&lt;span class=&quot;token variable&quot;&gt;@ROWCOUNT&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;SET&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;@isLastStep&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;CREATE&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;NONCLUSTERED&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;INDEX&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;##_RECID] ON #recordsToDelete (RECID ASC)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;@step&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;WHILE&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;@step&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;BEGIN&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;SET&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;@step&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;@step&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;TRUNCATE&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;TABLE&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;#temp_hash&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;INSERT&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;INTO&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;#temp_hash(RECID) SELECT TOP 5000 RECID FROM  #recordsToDelete;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;IF&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;@&lt;span class=&quot;token variable&quot;&gt;@ROWCOUNT&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;--------------------------------------------------------------&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;delete&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;dbo&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;MyBigTable &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;dbo&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;MyBigTable  &lt;span class=&quot;token keyword&quot;&gt;AS&lt;/span&gt; hs  &lt;span class=&quot;token comment&quot;&gt;--TABLE HERE&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;INNER&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;JOIN&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;#temp_hash AS JN ON hs.RECID = JN.RECID&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;----------------------------&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;delete&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;#recordsToDelete from #recordsToDelete as dt inner join #temp_hash as dl   on dl.RECID =dt.RECID&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;END&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;DROP&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;TABLE&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;#recordsToDelete&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;END&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;DROP&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;TABLE&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;#temp_hash;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It performs &quot;delete&quot; in 2 steps. First, it selects a large number of table clustered keys(100K) into a temporary table. Often these Keys are a set of RecIds. Then splits them into smaller sets(5K records) and performs the main table &quot;delete&quot; using a clustered key condition.&lt;/p&gt;
&lt;p&gt;This approach gives the following advantages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Delete command is not blocking other processes(as we are using clustered key condition and performing &quot;delete&quot; for a small number of records)&lt;/li&gt;
&lt;li&gt;It is much faster than a one by one record delete&lt;/li&gt;
&lt;li&gt;It doesn&apos;t require additional indexes (by CreatedDateTime) as the number of &quot;large&quot; selects is low&lt;/li&gt;
&lt;li&gt;You can stop it in any time without losing the progress&lt;/li&gt;
&lt;li&gt;It works for all companies&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In my tests the speed of this method was only 40% slower than a  standard &lt;strong&gt;DELETE FROM&lt;/strong&gt; command and it can be executed without blocking users even for highly used WMS tables in the middle of the day.&lt;/p&gt;
&lt;p&gt;The overall performance depends on many factors(number of indexes/hardware/etc..) but on average it may be 30-40 seconds per 100K records.&lt;/p&gt;
&lt;h2 id=&quot;user-interface-to-control-a-cleanup-procedure&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#user-interface-to-control-a-cleanup-procedure&quot; aria-label=&quot;user interface to control a cleanup procedure permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;User interface to control a cleanup procedure&lt;/h2&gt;
&lt;p&gt;Let&apos;s discuss the typical requirements for a cleanup procedure.&lt;/p&gt;
&lt;p&gt;Cleanup consists of several tasks, and we need to specify a cleanup period for each task. Also, it is nice to have some statistics about the last run duration and the number of deleted records.&lt;/p&gt;
&lt;p&gt;To control all this I created a &quot;Cleanup settings&quot; form.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/45a4b63701a94b7719c3152a2bf53644/fd84e/CleanupSettings.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 23.428571428571427%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAYAAABFA8wzAAAACXBIWXMAAB2HAAAdhwGP5fFlAAABTklEQVR42lWPSy8DYRhG5+f5AZbWFrYSO0uCaBt3dYtRTaujRFybMFVR6WfaTjvaMXdG2JG4bayOT3cWJ++T8zybV1lTj1jNHLOiHpJWz5jbOGRh85hF9YRltUR664L1XAW1cM2WdkOmWCO7J/6R2b8lf2Ag6jZK5/QE/6qMUz7H0S+JhM6DUSa61YlFhWcheG23ee90+Oh2+bq/59txJQ6ftsyuw0/L4t2yeGu0UZoNgWXUcNpNuqaBbTa4qxu0xJ8zCWwLq17DFFXcuxZ2q85NuURVL/V8U3ozq6Hv71HZLaIk0kUmZnJMzO5INCbnd5leKJBYzJNc0kgsFZia32Fy7u9qcpNnLJWTZBlPFcifXvG0vE08MEI8OIriRyGufMHzPAI/IIqiXvY9nygM8X0fz5VdEBAGcivz42Pc24YS7znmJbnOd98Qn/3D/AJi0ELwYU9YewAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Cleanup settings1&quot;
        title=&quot;&quot;
        src=&quot;/static/45a4b63701a94b7719c3152a2bf53644/8c557/CleanupSettings.png&quot;
        srcset=&quot;/static/45a4b63701a94b7719c3152a2bf53644/4edbd/CleanupSettings.png 175w,
/static/45a4b63701a94b7719c3152a2bf53644/13ae7/CleanupSettings.png 350w,
/static/45a4b63701a94b7719c3152a2bf53644/8c557/CleanupSettings.png 700w,
/static/45a4b63701a94b7719c3152a2bf53644/e996b/CleanupSettings.png 1050w,
/static/45a4b63701a94b7719c3152a2bf53644/fd84e/CleanupSettings.png 1056w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 568px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/4792d34217e4502c6e44cb06b48ccc52/10e91/CleanupSettings2.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 37.714285714285715%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAB2HAAAdhwGP5fFlAAACCUlEQVR42iWQ+0/TcBTF+8/6C48YI4gYo8RolKg/+ZOJQiA8R/dCtsHe3da1Xbu267aOPWAiYQoR8QHRGMzH78YPJ/eee27OvTnS3YfvePxilUfPV5gT9cn8mqjrPH21ydz8JrfuvGVs6j3jUwuMTS8wPr3I5L0lJmeWGZ9ZZOL+MrcfLDExK2azy0itps2R73DYbXLU7+A3bPo9l267xmBwxPnZMZ8venz52eX81ye+XR5zennIV9H/ubrg79Up339c8u/6N3CNZC9t0FmTaW6E8QPbHIRj9ILbdIIfaAWitLeiOPIGdmiVZkTGjwapRdaph7foheK0AzLuWoyTRJ6ztIqkpJOUU0lKe3E8rUTHseh7Nh/rNl3RD/mBYws4NDQNt1jEK6kjtKum0Kv0XJN9y6Bl6kjRxA7hoEwum8IyVXRhGtvNspPIYlbKVPQihoDrGGjlArIcIBIJEY2G0AW3qzpWRcOrWbT8GpJuqZRyKbLpBJlkjIKS4/WbFZ69XKCQz7Ebj7KzHULJJdlvuhTErlrIUMynyGf2MA2Vet2j7rm0Gg5SSVPIp3ZHoq4qVLQCuXQMzy4LAwfH0rHNMg3xgS9iULLJkWlJyZBNxTG0IoOTAe19f6RLpq1jiqFllGiILNyqIQw02r43Whh+NcTwetOrUjVvYnAsDaOsUBWxnJ0O6B92Rvp/v5wKUDpVzp8AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Cleanup settings2&quot;
        title=&quot;&quot;
        src=&quot;/static/4792d34217e4502c6e44cb06b48ccc52/10e91/CleanupSettings2.png&quot;
        srcset=&quot;/static/4792d34217e4502c6e44cb06b48ccc52/4edbd/CleanupSettings2.png 175w,
/static/4792d34217e4502c6e44cb06b48ccc52/13ae7/CleanupSettings2.png 350w,
/static/4792d34217e4502c6e44cb06b48ccc52/10e91/CleanupSettings2.png 568w&quot;
        sizes=&quot;(max-width: 568px) 100vw, 568px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Every cleanup task is visible in this form(providing some default values for the settings).&lt;/p&gt;
&lt;p&gt;A cleanup task is a class that extends a base class and may implement 3 actions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Estimate&lt;/strong&gt; - calculating the number of records to be deleted&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Display SQL&lt;/strong&gt; - instead of executing SQL, displaying it into infolog(used for debugging and validation)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Execute&lt;/strong&gt; - executing a delete operation&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In a class hierarchy it looks like this:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 414px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/57a7ff27bdcd7f12985b367eca61348c/b910a/ClassStructure.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 52.57142857142857%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACQUlEQVR42m2SC4/SQBSF+etuookmxhg38U8YV80al13XDbSlnZmWR7fCgpHCsjwWKNDy6gM43g4uMYZJpp3e6T1zz9wvU6/WcOc4qN3VMZ/P4fu+nDN/htlsJmNBEBxi0+kUwTxAnGyw3W4QxzGSJMFut0M6MuNxF93mbyiqDssyoes6cvk8NE2BoqgolUrgQlC8AK2gQdU0+V+z6aLT6chDPc9DGK4RRREyk1TQbYJzC7Zd2QtwjiIlmZYFh6qv2Lcolmj/1pb7gg4QgsNttQ6u0sqXqxUy3qiLXsuFwQQlFakaTpXoYMyAbjDYFRvCtEiAUZUGVFWRLtqdBwR+cBALw3BveeL10G+3YHIGUchBMBXMUGFxssZ1lIUBrqsomzoqFoNTtjAcdBGt5lgvA6wWPjZJhKchLXdcFxdKBd/UCs6uBT5cGTjPmfhyU8TnH/SdLVCc49M1w8erAr6LBpqjNVqjkCa9xxHCeLMXjNYBGm4Pr7IjnFx4eHbew8vsECdf+zih9fPLCU6VBV5cTvH6xsfbXIA3ygqnhTXeaSHe66FcD2b7KjPpYzz2YNBF/6o5sIscdtlEteqg3Wyg/9DGIqA7IovbeI0kDv+a2+HY2At6E2icRH46hI+GXC5PgjW07++piwvibi67mV78E2+7f2R3/wt6Ew8q47KzKTIKddJgTGJTr9dJvIrB45C6SaAT5MvFgoBOjlcY+GM8druUXCIObckbo46n8ApTQFNVeUjLbWO5XEqQU0xWxNwxwT8gDxoH9WQhqgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Class structure&quot;
        title=&quot;&quot;
        src=&quot;/static/57a7ff27bdcd7f12985b367eca61348c/b910a/ClassStructure.png&quot;
        srcset=&quot;/static/57a7ff27bdcd7f12985b367eca61348c/4edbd/ClassStructure.png 175w,
/static/57a7ff27bdcd7f12985b367eca61348c/13ae7/ClassStructure.png 350w,
/static/57a7ff27bdcd7f12985b367eca61348c/b910a/ClassStructure.png 414w&quot;
        sizes=&quot;(max-width: 414px) 100vw, 414px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;A cleanup class may implement the following logic:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A &quot;delete from a large table&quot; logic described above&lt;/li&gt;
&lt;li&gt;Run a standard cleanup class for all companies for complex operations.&lt;/li&gt;
&lt;li&gt;Can run X++ code do delete records in order to execute &lt;strong&gt;delete()&lt;/strong&gt; methods and standard delete actions&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example of SQL based cleanup:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/bb781818722011d501aeaf9831f0db5c/3f3b9/SQLSelectDelete.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 38.857142857142854%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABiUlEQVR42mWSW2/UMBBG9///HR54YekCqlYthQrQUqEFddNk14njOLHjpDSXnk6MKm4jnczEHn8az3i1vjxwvlO8vfzGevOJ1x9v2Vzf8u5LxrmwuU54sfnMyzdXnL2XnO1XXgnr7Y71xQ2bD3vOrvZsd0cubhSr5JBwOp0IrkZnGWlyx1F8flJUsl4eFxQmS2m0xglDFxiFeRrh8THyOE+R1TSOFIUkOs8wzEzTxLgwjIyyF+PFjxOD+Ifh19qftmg+22r5GGNo25Z5nlGlIlMZh2PCnVAURaQstVBQ2Yq+75+l+NeiYFmWUVAKp3QaZZWQ04YW5x2+9dRNi7Eh/teuwcteCIFeCN7TdV28yV+Ci7ngsN5iGqlEkrog9B0mrzj+yMnTlHT/Hb30VvrpbU1TGcnpefh5/79gE2oqb0RQ2iCNDyLa3/do7UkOdRxgmiQoGZoWQVPZOKxai0bwvwW9lL1YLdWVjYtDChIPbWCSCoN18goMlVJx8rUusCrH5jm9nA8Sd5XlCZwgXDg0X8FKAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;SQL delete&quot;
        title=&quot;&quot;
        src=&quot;/static/bb781818722011d501aeaf9831f0db5c/8c557/SQLSelectDelete.png&quot;
        srcset=&quot;/static/bb781818722011d501aeaf9831f0db5c/4edbd/SQLSelectDelete.png 175w,
/static/bb781818722011d501aeaf9831f0db5c/13ae7/SQLSelectDelete.png 350w,
/static/bb781818722011d501aeaf9831f0db5c/8c557/SQLSelectDelete.png 700w,
/static/bb781818722011d501aeaf9831f0db5c/3f3b9/SQLSelectDelete.png 870w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Example for X++ cleanup(running a standard &lt;strong&gt;On-hand cleanup&lt;/strong&gt; for multiple companies):&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/31cc355e4f3296715e8959cbf65d7bc6/227ba/XppSelectDelete.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 32%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABPElEQVR42k2QWW/CMBCE8/9/UR9bNSmIh0KgOSiEI8RO4xxGBJLmcKbrlFas9Mkra2c8XuNlfoC1OGK2TmC9b2FOXLzZR5grunMZpi7H1GN4tU94shw8zxxY9h7mnGbnAczFlvTB2E9IY7h+gN1mB8Y5iiTGReQ4BCnCMMd+x3A8pLhcSgiRosglVN9gGAZCAf8MI4NSMEIu0LbfJBDIsgy68rwCYyWS5IxUGxUFJHGWEk3TjoaqV+i7nrQd0aLrOig1wDiX9d2kQH431ANRxMFZjDgW1AuExxNYxOhOgEfx2Mc8xu12Q6WpKjLtYcgHw7+EXdfC93xsN3v4/ieWtg9ntYbrOFjZS3iuB/fDodNH8pWMv8jSFOX1+pgwH9HVU3z9TZ04va9CC2QhaY+/D2skrUAn09R1Teto8ANbaL/hiBig+QAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Xpp delete&quot;
        title=&quot;&quot;
        src=&quot;/static/31cc355e4f3296715e8959cbf65d7bc6/8c557/XppSelectDelete.png&quot;
        srcset=&quot;/static/31cc355e4f3296715e8959cbf65d7bc6/4edbd/XppSelectDelete.png 175w,
/static/31cc355e4f3296715e8959cbf65d7bc6/13ae7/XppSelectDelete.png 350w,
/static/31cc355e4f3296715e8959cbf65d7bc6/8c557/XppSelectDelete.png 700w,
/static/31cc355e4f3296715e8959cbf65d7bc6/227ba/XppSelectDelete.png 769w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;To run these tasks I created a new batch job. You can select one or all tasks using a standard query filter and run them periodically(e.g. weekly).  So the whole cleanup process can be implemented with just one batch job, without doing a complex setup of various jobs in different companies.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 572px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/6cddef3750b6501c8e84fbd4109f3dcf/a805e/CleanupRun.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 52.57142857142857%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABWUlEQVR42p2Ry07CQBSG+9xCogtEH8CFiW+ga9dGFkaDG0wLaIq2WHudDpRilWmnv2eG4MIEBCb5cmZOzvznZrSfM7RNhraV4qSf4rTPcWymaHQGaNwuObgx0ewMNYcPLloWR4v+KHt0/4bmnY2Ly2tcnZ3D8OI5Yv4FPykQsE+4QQ5RSmx76rpGLSUE2W96G1HM4Djv8P0Qi4UgSsiqoqAVciOkuJIGfYQxy2ZIEoY05agqiYqCShL8pSzJX62F8QyvVNBHmECIEobv+3BcF6ORjSiKIGWNUggtJMhKubn9iHEMXmw4XoAFxRuTyQRxHENZz/MQBAHCMNSoZCrrtrNURVDLGabUtnKMx2NdZZqmYIzRKBId9O9SCNWJFlwXsGKXbWtBpbwPfxMrn15KURTYh0yNajpFnuf6zjmn+3y5lF1QIowlGA4HeOr1YNs2LMtEt/sI13HxA9xKSMu/qpIRAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Cleanup execute&quot;
        title=&quot;&quot;
        src=&quot;/static/6cddef3750b6501c8e84fbd4109f3dcf/a805e/CleanupRun.png&quot;
        srcset=&quot;/static/6cddef3750b6501c8e84fbd4109f3dcf/4edbd/CleanupRun.png 175w,
/static/6cddef3750b6501c8e84fbd4109f3dcf/13ae7/CleanupRun.png 350w,
/static/6cddef3750b6501c8e84fbd4109f3dcf/a805e/CleanupRun.png 572w&quot;
        sizes=&quot;(max-width: 572px) 100vw, 572px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h3 id=&quot;progress-indicator&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#progress-indicator&quot; aria-label=&quot;progress indicator permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Progress indicator&lt;/h3&gt;
&lt;p&gt;Every cleanup task has access to a related record in the Cleanup form and this makes it very simple to implement an execution progress indicator. For SQL based tasks this is done in the base class, for every main loop &quot;Deleted records&quot; field is updated and you can estimate how many records are deleted and how many are left.&lt;/p&gt;
&lt;p&gt;Also, and it is very important, you can view last execution statistics for all tasks in one form and this allows you to quickly identify problems with a particular task.&lt;/p&gt;
&lt;h2 id=&quot;summary&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#summary&quot; aria-label=&quot;summary permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Summary&lt;/h2&gt;
&lt;p&gt;In this post, I described a custom cleanup framework. If you set up it in a correct way it provides the following advantages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Fast deletes that don&apos;t overload SQL Server and don&apos;t block users&lt;/li&gt;
&lt;li&gt;Easy to maintain procedure with just one cleanup batch job&lt;/li&gt;
&lt;li&gt;Easy to set up and troubleshoot with all settings, statistics and actions in one form&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A sample code for AX2009 and AX2012 can be found &lt;a href=&quot;https://github.com/TrudAX/TRUDScripts/tree/master/Performance/Jobs/DataCleanup&quot;&gt;here&lt;/a&gt;, but please note, that it is not a “ready to install and use” solution, all queries should be validated and tested for your environment.&lt;/p&gt;
&lt;p&gt;I hope you find this information useful. As always, if you see any improvements, suggestions or have some questions about this work don&apos;t hesitate to contact me.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[D365FO Performance. Periodic import of one million ledger journal lines]]></title><description><![CDATA[The blog post describes some steps for performance testing for file-based integration in D365FO using X++]]></description><link>https://denistrunin.com/xpptools-fileintegledgerperf/</link><guid isPermaLink="false">https://denistrunin.com/xpptools-fileintegledgerperf/</guid><pubDate>Wed, 20 Jan 2021 22:12:03 GMT</pubDate><content:encoded>&lt;p&gt;Sometimes you may come accross the following question related to D365FO performance: &quot;Our customer has X transactions per day, can D365FO handle this?&quot;. The problem is that currently, Microsoft doesn&apos;t publish any D365FO performance tests and the current answer is: &quot;You need to test it with your specific setup&quot;. In this post, I try to provide some steps to run a D365FO performance test. It will be for a standard Demo database, so it can be executed without big efforts.&lt;/p&gt;
&lt;h2 id=&quot;test-description&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#test-description&quot; aria-label=&quot;test description permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Test description&lt;/h2&gt;
&lt;p&gt;This test is based on my previous post - &lt;a href=&quot;https://denistrunin.com/xpptools-fileintegledger/&quot;&gt;How to implement file-based integration in Dynamics 365 FinOps using X++&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;It loaded 1000 files with 1000 lines each, so 1 million ledger journal lines were created.&lt;/p&gt;
&lt;p&gt;To generate such test files I created a new form in the &lt;strong&gt;Tutorial integration&lt;/strong&gt; module:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 579px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/822d8d776a215cae7683b0171fef4f8a/c08bc/PerfTestingMenu.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 90.28571428571429%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAYAAABb0P4QAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACx0lEQVR42oWUSW8TQRCFzXJACJCQSDhxCYEbEkjcOCDghyHIImUhQSyX4ED4Q5EiOSwSiWzssWffZ7pn60dVO4GE2NDSc/XYM99UVddz68rNB7h0/R5m7zzFtVuPMDP3GLN3n+HG/BNcnnmI1vnbaF2Y/7/OzeHi1ftoPV95j+XXbay/+4yVNztYZb3d0fuFtS28WN3C0qs2ljY+ai3qfRuLG9tY2uTrbSyst/Fy7QOWNz+hVUgBVl1KLaUaHC+llI5JAQhZoJQ5irJEStdlISBFjqqqcHK1JMFGoyEMY4DBoI84ivSNIs8ghNAPuKFEf+hgYNjwwxxeJOF4EWw3RBgLxPSGiJSJapxhGPjwXAeOY1N0UZWcDcNK/dY4q2GYLvqGhTSvUFBSshxLFAr5kTKp0CoL+QdoWzpyhvz9MZCXnzRwogZuVGPo1wRTmLQ0MPA92JYJk0q3zBGyNDkDDHMFP1WIKbpxA4+kpgE5KwZxZCjDTwL5cEa2D5NlubpXXK6aQNQ99Llcy0IcBmjqSqsqTwOjKNQKggB1XWPaavGHRzfZnqdjGEcISEJKDTrOwonHpQ59hVTwaE3pofR9GJ199Dsdre7eHg52dxH0elBNc6KHQJCN++ilanqGOZU5OjzA8OCHjt2vX/Q+83h8xiU3BHYdi3prwafvR8MhInruqB+ngdyngH50qI8h9aghp9RNrZXQdUGHwytIBKJMIhEFwiRHys5RZwv/PTYuDTUrof5JcgkfjE0nn6Yp6jhGb7+L3jdy03cDfdJP2h92eoho2CeODcPM0YjKMfQcMtCxTaRZioZKN7uHSHwHqNjIAiAvK/J2I+VZIPeFXWJSRiLPtfVqaoUGElw7JW30SfOAOwkNuPiHUxjIGTKUy9f/Pn8BvbjW9vOSsUs4Vo2aDGQvM4jBrDGwOgXMyfisVI6zS3I+vLPAX8IPJbu58wr+AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot; PerfTestingMenu&quot;
        title=&quot;&quot;
        src=&quot;/static/822d8d776a215cae7683b0171fef4f8a/c08bc/PerfTestingMenu.png&quot;
        srcset=&quot;/static/822d8d776a215cae7683b0171fef4f8a/4edbd/PerfTestingMenu.png 175w,
/static/822d8d776a215cae7683b0171fef4f8a/13ae7/PerfTestingMenu.png 350w,
/static/822d8d776a215cae7683b0171fef4f8a/c08bc/PerfTestingMenu.png 579w&quot;
        sizes=&quot;(max-width: 579px) 100vw, 579px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/0fdb98a4beb7df8f1cf09e1fa9de30f3/078fe/PerfTestingForm.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 21.714285714285715%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAYAAACOXx+WAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAA1UlEQVR42mWPzW7DIBCE/f4PVakvULXHJP2RUjlgzALGgHHc6CtxeuthNDs72llNJz7inGCMQQ8GoxXq/YQ+HVHHA9K0iGWOkZxmSr4j/UP+467WSnAWL4YYPK4d5zixtMM0BVIMLSju2MPu8/zQeZ52Tnduu5Imum1d0GOkNxHxE6VupFwx1hFTIZVKLiuueUq3BqNgXcBKe97a6WFsDTyjBLQNdNwWnt88T68RZReU21BypR/Xfdb+hyHcOOvM4cvy8R242JXePvzPy4yRhJ6uvJwTv3OnL5mYKadOAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot; PerfTestingForm&quot;
        title=&quot;&quot;
        src=&quot;/static/0fdb98a4beb7df8f1cf09e1fa9de30f3/8c557/PerfTestingForm.png&quot;
        srcset=&quot;/static/0fdb98a4beb7df8f1cf09e1fa9de30f3/4edbd/PerfTestingForm.png 175w,
/static/0fdb98a4beb7df8f1cf09e1fa9de30f3/13ae7/PerfTestingForm.png 350w,
/static/0fdb98a4beb7df8f1cf09e1fa9de30f3/8c557/PerfTestingForm.png 700w,
/static/0fdb98a4beb7df8f1cf09e1fa9de30f3/078fe/PerfTestingForm.png 934w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;It allows specifying a link to the Azure file share, a template for a file name, a number of files and a number of lines in each file.&lt;/p&gt;
&lt;p&gt;When you press &lt;strong&gt;Create ledger journal files&lt;/strong&gt; button it creates the specified number of files in the &lt;strong&gt;Incoming&lt;/strong&gt; Azure file share folder.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/2cac25064e71217a6548d983a71fb10a/30c92/FilesInAzureStorage.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 35.42857142857142%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAAA7EAAAOxAGVKw4bAAABGUlEQVR42pWQPU/DQAyG8/9/QBESAzMbO1QsCDGysSCVNsmd7yO5S/N1aasXx6mgEiwMj17br23dOXv7MHh5t1BVj+PxhHE6IjFjOkg8piWea9PhJJoOS99PPs8stUxrC60MlCKoklAWWihm5Xz283Ne5DNK+jeb7XfvblfyvAGRQ2aIQFpjVmetYA3BWyPqjEHlHWIIiHUtGqoK3jmue6YSfx+jxBm5CPItXBigfYfSMbYVLVh31AhUjzAhiVI1LHCsz2rZ83FAdv9a42bd4PZpj+v1gKvHiUlnJmH1MDLpov6bFXP3HPjL/KW8UPjc5gj87K7r0bbdb7oL/vBi08BYvqE1lg9eIM95Id+n73te2v2bhhc65/AFamsKU/Ce7lMAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;FilesInAzureStorage&quot;
        title=&quot;&quot;
        src=&quot;/static/2cac25064e71217a6548d983a71fb10a/8c557/FilesInAzureStorage.png&quot;
        srcset=&quot;/static/2cac25064e71217a6548d983a71fb10a/4edbd/FilesInAzureStorage.png 175w,
/static/2cac25064e71217a6548d983a71fb10a/13ae7/FilesInAzureStorage.png 350w,
/static/2cac25064e71217a6548d983a71fb10a/8c557/FilesInAzureStorage.png 700w,
/static/2cac25064e71217a6548d983a71fb10a/30c92/FilesInAzureStorage.png 874w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;For a test data all possible values combinations for BusinessUnit, Department, CostCenter are used combined with 60* Main accounts for Credit, 50* Main accounts for Debit.&lt;/p&gt;
&lt;p&gt;Even in the Demo database, there are more than 1 million different combinations, so all files will have different values for ledger dimensions.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 433px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/536d5ff9c8e886d1b273d17fd64097fa/55fc0/FileStructure.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 57.14285714285714%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABtklEQVR42nWS63KiQBCFef+n2qokWzGVizi4ARSi4Tbo/hAQEAVOuhvRmNqdqi6mZ+Dr030w1Fzh1+QOd0+/cf/8iMn0Gep9Dt/3Yds2Vus1VqsPeMslHMfBZxBgTWd8t6SzgHI+9/0PbDYbGC9vr5hYr/jjOQJ7eJtg6lj4u91CJwlijjhCFEVI6PkZhNA6Rao1wjCg+xhpmkJTHA4HGFylLCsAPVVcQFlz1HWNcVV1hbqqZN/3HcE0jseT5Pv9XlTxYlie5zBc10VRFPR2Jy0oZVGBkj7u6ahHRfsx79oTqY3RNI1AiiInYCp7FiFA27EF2HedzMI0TVHcUc5RCnAvwPbEwETU8MrzTNqVTqgLATo03IKkc8uLxQKz2UwuRSFFVQ0KebVtKzNrmuOgkABbmvWoMNvtYDCEZ0FfE9AlhT+BlUBHYKKTG+Co8DJDbrM4A13XwdSckhH1BViW3xWeEEbhZYYMGE25zpBaHhWyKeZM/VdhxwoT/cOUs8sEZC8MpRTysym2/U4zVFLtuylc8GpKfDUluzUlo1wUDi318DwP1nz4D//V8qAwuVE4msJFsmyHLyCCQk8d4xT4AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;FileStructure&quot;
        title=&quot;&quot;
        src=&quot;/static/536d5ff9c8e886d1b273d17fd64097fa/55fc0/FileStructure.png&quot;
        srcset=&quot;/static/536d5ff9c8e886d1b273d17fd64097fa/4edbd/FileStructure.png 175w,
/static/536d5ff9c8e886d1b273d17fd64097fa/13ae7/FileStructure.png 350w,
/static/536d5ff9c8e886d1b273d17fd64097fa/55fc0/FileStructure.png 433w&quot;
        sizes=&quot;(max-width: 433px) 100vw, 433px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Then I ran a &lt;strong&gt;Load messages&lt;/strong&gt; task as a batch job and measured its execution time. It created and posted 1000 ledger journals(with 1000 lines each).&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/e3ff9ac8d5d9f65d7029dc8a9c7d23a2/22c86/ResultJournal.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 40.57142857142858%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABN0lEQVR42p1R2WrEMAzM//9e2aMUtnvl9BUfcbJxkqnksrDQPpQKBgmNNTpcHA877HdvOB72qMo7bG/gnf03itu9QttJaN3De4fwyyNn+78Ltq2CVBqd1JBCQhA6IaDkdyzJS9HBaAWt5EuTn8iCvKKzBtY6aOOhCEJZGGMpdtTMIvDkwWGMA4bgc3EcfMZA+Sey4Kn0OJc9pFtxawM+7wrn2uMuRpxuGqWIaE3Cx0XgWjuUXcSFeM4Ju6KSE2r1wLUJeD8rFMP4yDec0wY/jCjrBsYGTPNC0xk8yDNXNx3KqoEPIzYAaXliw0oJ5yOUpgnneaYP0dgoOU0j3a2j9TyWZYGjFdhvRAq6K3PTNOHVmF/XFSnN+VOLlBIFPpMsbuk+XMSPYoxZjOGcyw34zasxx8Y6XPcFTm9k/T9l6+EAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot; ResultJournal&quot;
        title=&quot;&quot;
        src=&quot;/static/e3ff9ac8d5d9f65d7029dc8a9c7d23a2/8c557/ResultJournal.png&quot;
        srcset=&quot;/static/e3ff9ac8d5d9f65d7029dc8a9c7d23a2/4edbd/ResultJournal.png 175w,
/static/e3ff9ac8d5d9f65d7029dc8a9c7d23a2/13ae7/ResultJournal.png 350w,
/static/e3ff9ac8d5d9f65d7029dc8a9c7d23a2/8c557/ResultJournal.png 700w,
/static/e3ff9ac8d5d9f65d7029dc8a9c7d23a2/e996b/ResultJournal.png 1050w,
/static/e3ff9ac8d5d9f65d7029dc8a9c7d23a2/22c86/ResultJournal.png 1143w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;test-setup-and-preparation&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#test-setup-and-preparation&quot; aria-label=&quot;test setup and preparation permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Test setup and preparation&lt;/h2&gt;
&lt;p&gt;To run this test I used a standard cloud DEV VM with 16HDD and the Demo database.&lt;/p&gt;
&lt;p&gt;I did the following preparation:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Installed DEVCommon and DEVTutorial models from &lt;a href=&quot;https://github.com/TrudAX/XppTools&quot;&gt;https://github.com/TrudAX/XppTools&lt;/a&gt; repository.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Created a new Azure file share and created a ledger message type linked to it&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/0c541815c325047db705f529813bbd0f/58213/MessageTypeSetup.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 90.85714285714286%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAYAAABb0P4QAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACEUlEQVR42p1U2Y6jMBDk//9tX/ZpRtpJJoSQcITDxidHTbeJ0R6TQ2upZEjkcnVVN8m1U5BCQjCkRt+L8N42Le09yuKCsiyQpQd0bYthkFA3aCUxOkX7sP2W7D524aA1GqN38IR5nsBrHD3Swx67j1+4nHNkxwP6jkiloMMCTdPh51uG5lpD9B2hRVLT7Z/HAu/7CullwP7UI68tinaEHEhx1xCBhHMWxhhYa8Oz9xad0Pjx1oRLVoUCyeQ9Bm0hzQTjFmiCMvMKxRbQzUIExfM8b1iWBXHxc0RitMI0jvhuOVJzrWukaUreDRspL0mqj8cjrHN/kCbBu+l7Qksl9v2A8jpQmQ7LvGCapnBQKYX8dCIfm4CWAhtJWCCc7hFaE/zhdH0gvJV7U/l3uZvC+4RUMrVPfi4glYE2DoOiUPyEe+upwraTSLMCp3ONqhFUvqAQ/X8SkoeCerSqStR1RX3Wk1dNKH8mP39PPeIhodZr23RdR3sfjF9DmW9Ywr620YqnHrIiTjPPaVKyLKTLi5u8LMuQ/j9t85CQ1PGMc6/y+3jrWW52JuR3RuzPh4TeGRxoHHkkqaU3JfEytiFOTfz9JcKsGOCt3pQw2Es+xx+Sl0Nhn2TfoCovoTweN1YSCT19B6K6lwi5LB4rnuW6qjafeHG5HBJfEn19Goqh/4zmUqcQQpzjeFlNHw5WHsNixV8QsHyIXY9I3AAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;MessageTypeSetup&quot;
        title=&quot;&quot;
        src=&quot;/static/0c541815c325047db705f529813bbd0f/8c557/MessageTypeSetup.png&quot;
        srcset=&quot;/static/0c541815c325047db705f529813bbd0f/4edbd/MessageTypeSetup.png 175w,
/static/0c541815c325047db705f529813bbd0f/13ae7/MessageTypeSetup.png 350w,
/static/0c541815c325047db705f529813bbd0f/8c557/MessageTypeSetup.png 700w,
/static/0c541815c325047db705f529813bbd0f/58213/MessageTypeSetup.png 902w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;Switched off DEV VM monitoring. It was creating a lot of load to a file system for my already not quite fast VM.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;powershell&quot;&gt;&lt;pre class=&quot;language-powershell&quot;&gt;&lt;code class=&quot;language-powershell&quot;&gt;K:\Monitoring\MonitoringInstall-Uninstall&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ps1&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;Disabled Budget control. You probably will not use it for such large data loading.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/f1faec7427526dcf1ae2b70e30998f3f/c946b/BudgetControl.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 46.28571428571429%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABmUlEQVR42o1RSW7cQAzU/9/iq18Q5GoDNhDEgTXyjDSLtl7UqyRKdHVPnFxyCIEC1SBVLBaLZZkftJL8+vJCh+rA9enI56bmj4+Kq0PJR+Sua3O+3W5szMTTpHnSmrVWyDJDK4Ga5mKOsZRC8Nvbz/0EsqqquKlPfDk3nN5n5HEc+Xq9cNf3HEJg5xyHGHmeZyByjGHfaOU5BlN4Z/cYfHpw8D4V8zehYV1XHsQAhR1LpXgYBh5AegG5hkoiQg8xASv6l2WJhbNmB+5rpHWATA4lSYHHkKRogMoehEKK/E41MxnY0LJ1NvdHqE6EaLDY32RYYzNh/L1Sn9TBkqRSIKcB3jtOQRtlpdu28z32O6FPhChkwNgYfSaMmJoOkbxTkwBktqBtkyr4GOKfAdbabEEiJOcM4Xo0aUUgJSgk+ErBOxrFSFJI+v74RD+eSuqvI+EgBL9oXdacv7BtGxU+zDzqlTda8orpEPv+tcLfaI+S358bbn51/I/IP+C/tlDaHOrWlGZSpRKixHFKTCsxLQN9/4N3oAa+fQLk5rCb3gPRUwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;BudgetControl&quot;
        title=&quot;&quot;
        src=&quot;/static/f1faec7427526dcf1ae2b70e30998f3f/8c557/BudgetControl.png&quot;
        srcset=&quot;/static/f1faec7427526dcf1ae2b70e30998f3f/4edbd/BudgetControl.png 175w,
/static/f1faec7427526dcf1ae2b70e30998f3f/13ae7/BudgetControl.png 350w,
/static/f1faec7427526dcf1ae2b70e30998f3f/8c557/BudgetControl.png 700w,
/static/f1faec7427526dcf1ae2b70e30998f3f/c946b/BudgetControl.png 805w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Budgeting - Setup - Budget control configuration&lt;/em&gt;&lt;/p&gt;
&lt;ol start=&quot;5&quot;&gt;
&lt;li&gt;Adjusted a Ledger account structure setup to allow any Business Unit, Department, Cost Center values for used Main accounts.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/ab13938733dad9b5467e89d2bfdcd6c1/ec3e2/AccountStructureSetup.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 29.714285714285715%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAA70lEQVR42m3Qi26EIBAFUP//F5u67iaKIqI8BFTgdsS0W5MlOYHRmRu0Yozj+WJoO47Xs0HzqNH3DANhrCuGviv1yAf0VMtJQKvlo4qxFnX9haZ5oKawrmsRgkfwDlu4824tz926EvtRZYyBnDUWZaG0pZ2GtgP7kbDtb4HEmJBTRs5vKd1VZ6qxDpqsLpCdwvJlv/bf0DPgWvmf+6rGSYFLB7E4fDf030YF7RLUGtELAz5ZqmMhdYBcNN02YqMvCOTsGWdP/QmLjai4tBCGmk0CExaD9OV8EvrApONfPdOA3+i2B4qwg95TzzlvU/EDOGbObEsBm3wAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;AccountStructureSetup&quot;
        title=&quot;&quot;
        src=&quot;/static/ab13938733dad9b5467e89d2bfdcd6c1/8c557/AccountStructureSetup.png&quot;
        srcset=&quot;/static/ab13938733dad9b5467e89d2bfdcd6c1/4edbd/AccountStructureSetup.png 175w,
/static/ab13938733dad9b5467e89d2bfdcd6c1/13ae7/AccountStructureSetup.png 350w,
/static/ab13938733dad9b5467e89d2bfdcd6c1/8c557/AccountStructureSetup.png 700w,
/static/ab13938733dad9b5467e89d2bfdcd6c1/ec3e2/AccountStructureSetup.png 997w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;ol start=&quot;6&quot;&gt;
&lt;li&gt;Set &lt;strong&gt;Maximum batch threads&lt;/strong&gt; to 60. This allowed me to fully utilize my VM.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 678px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/ad2b97e42af56ad8a1a03e5579410d43/38cea/BatchSetup.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 47.42857142857142%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABQUlEQVR42o2R60rEMBCF+/4v4xMsiP4Q9I8gou66YLVNekl6S9M2adrjJCuyKrg78JFkSE7OzEQXVwybmy02t2+4vItxv9d4ShY8vju8JDPapoFoRnBpUdQGvTYYpwO9HqCHKcB5jrpuEV0/9Nhzix132DGHbWpJyOD5w+CVTWhbhayQSNIUWV6EhynLwIiilDDWwZgZdl7CPrJuhSPmL9wRM11SXQdZteGxkDVRoRS0FxWqqsFA7qbJkmMb1gj/xLqu6JVC17YoywJSCBI6IKVAnudo6vr77rIs5wv6XqpOQdG5JpGOnPucx59132O2Jxz6H3WvghvGGLIsC67iOEaSJJSXQczn/Ec+zhOkElMaihfxcM4hypL67H5U4zmr5J5EtdbBhXd1LPQ7Tgr6KQ+DpglOGEjU98oYmuw4Uu4vn/a6twetkrjAAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;BatchSetup&quot;
        title=&quot;&quot;
        src=&quot;/static/ad2b97e42af56ad8a1a03e5579410d43/38cea/BatchSetup.png&quot;
        srcset=&quot;/static/ad2b97e42af56ad8a1a03e5579410d43/4edbd/BatchSetup.png 175w,
/static/ad2b97e42af56ad8a1a03e5579410d43/13ae7/BatchSetup.png 350w,
/static/ad2b97e42af56ad8a1a03e5579410d43/38cea/BatchSetup.png 678w&quot;
        sizes=&quot;(max-width: 678px) 100vw, 678px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;After that I generated 1000 files and ran the test.&lt;/p&gt;
&lt;h2 id=&quot;test-results&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#test-results&quot; aria-label=&quot;test results permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Test results&lt;/h2&gt;
&lt;p&gt;I used a standard cloud DEV VM with 16HDD and the Demo database. I ran the test on 2 VM sizes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Standard D8 v3 (8 vcpus, 32 GiB memory)&lt;/li&gt;
&lt;li&gt;Standard D16s v3 (16 vcpus, 64 GiB memory)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For each VM size I decided to perform 2 tests:&lt;/p&gt;
&lt;p&gt;I started with a fresh Demo database. Loaded and posted 1 million records, then generated the same set of files and loaded them again for a different date. So totally 2 million journal lines were created. The first test generated a new ledger dimension combination for every line, so it was like an initial data load. The second test used existing dimensions combinations, so it was like a periodic load.&lt;/p&gt;
&lt;p&gt;The load operation consists of 2 batch jobs. The first reads files from Azure and puts them into D365FO tables. It is a single-threaded job and for both tests, the time was around 1.5 minute for 1000 files. Then the processing job(which is multithreaded) reads the file content from D365FO tables, generates and posts ledger journals.&lt;/p&gt;
&lt;p&gt;I got the following times for loading and posting 1M ledger journal lines:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;VM type&lt;/th&gt;
&lt;th&gt;First load time&lt;/th&gt;
&lt;th&gt;Second load time&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Standard D8 v3&lt;/td&gt;
&lt;td&gt;4h 40 min&lt;/td&gt;
&lt;td&gt;3h 40 min&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Standard D16s v3&lt;/td&gt;
&lt;td&gt;3h 6 min&lt;/td&gt;
&lt;td&gt;2h 29 min&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 460px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/44124e95263df2ce26268fe03520d63c/08a84/TestResults.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 69.71428571428572%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACKElEQVR42pWTTWsTQRjHB7+An0KqBwX15EW8+An0IPiWHvRkQUl8qRTU6kUogncroh6U1lawTWPS5KJCiyYqSBHbJrvdZmtiXnZNdje7O7N/Z6ZpmrqNLw8MzDPPzG/+8zzPkPzyMlZUDYqygmJxFXpRgaIq0DQNqqKiXquhUqlAX1tDqVRC+UcZuq7DNE1ICwJ0GxHBeslEo9nkowHHKst507Zguzb+14hPfbQ8t31ZIIewqlqHMq/Brlvco2CMdeLBb6q2AD3Pg+u6UrrYyCiTgceRMZwiA/gy/VX6Yv1vMAmklEKo3DBG1w886X+BM+QSPr98w71VUO/fnk+Meg2tlhsGRsZxllxD6s5eFDI7YFfmZP492+V7fD73t1VLROU28rcdMHmzD4txAuZmMTuSRWznLSwkvnXSEAKKKvs+7akwObwbSzOE1+UjxmKzOE4uIHMvCrNwDo6x0BbDtgL/pDA13IelBEFAc5i8nMFpMoj49f3ykp96sn12UxBxHAee7/fOoQBKhTlMRNM4Sa5gZugglDRB43sqDBT9JdsmVOVx9HM1qdt7OgonYmneSlcRHzqAQi9gwIGUsRDwYeQZTvC2SdzYhcUpDvSzeB59jWPkIl4N7kM+0ePJInc+3VwI2Dowc/8tRg6P4v3T81Dnj/Kb8ng3+gl3Dz3A3KMBaB+OwKrmwsDugnSbUG25FizHRdOhMAwTVaMG2+NrLY//dfEhwn34CzyF7Kn3/kDMAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;TestResults&quot;
        title=&quot;&quot;
        src=&quot;/static/44124e95263df2ce26268fe03520d63c/08a84/TestResults.png&quot;
        srcset=&quot;/static/44124e95263df2ce26268fe03520d63c/4edbd/TestResults.png 175w,
/static/44124e95263df2ce26268fe03520d63c/13ae7/TestResults.png 350w,
/static/44124e95263df2ce26268fe03520d63c/08a84/TestResults.png 460w&quot;
        sizes=&quot;(max-width: 460px) 100vw, 460px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;During both tests, CPU was used for 100%(about 25% for SQL Server and 75% for Batch service). Ledger journal classes contain a lot of caching and probably they are not optimized for different values for every single line as in this test.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/eb4f933308cf64134432c0697701ae10/9cab2/CPUUtilization8.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 60.57142857142858%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAA7EAAAOxAGVKw4bAAACCElEQVR42nVSy3LUMBD0T3Gn+AUuFHwTXwI3+IMccsqBC8VuJWHjXe9TlmVbL2ttNz3aJFWpBFW1ZzQetXpGU5TlGuVDCWMMpmnC+XxGSin7b615np/xtJ8IOSMoqmqL3X4PXdc4Hk84HA60R1hrXxFMk1gJviS/+JdY8fvPAjc3N1gsFlgul9jtdqhJLnakykTF0zwRyOprraEJxRzNqkzbQjcmxyVWuNahLEsoVT+WOkJ1Hnd7g1J1uD0YbBqHnQnYGI+/qsdaO1SNR1k7PNQWG+5L2tWxRRF9j3K9zj0UBbKMT6jtkO2+jUSAthF1P6Ai8Ym2cQNtzMSavmK+nClmluO8hyfSkDKhJK6UxZrK7k6WqmxWVRK3px4rKtuQaEVVspf4Q335X7x4wcev3CTliJp7dUkWJRvt8wVysGL5Er/nfivlM7amLd4YDLSBzbcJDYn3TDqw5MYllj1gy0vU479TF6k0ZF/aoVhZIX0LPuQxcc7BE7VpcdQGNo2w44wunmFsgHERuvdQfEg7nNEz3oaU/Y4QK4RzjPGZ0GXr0QeOTGcRNxXGSLLWzH3fzzEEyX+axlcoAh/icFT5hS9Tz2hqsVv8QHP9Fer7Z9j9ArwcZ47VMAwYxxH/W8WQxm8xsaTGjF1r0LNXQS+hrr7AXn+a8OsjXHX10wDvSPkhhPBewLNv4h/nUpGKdu9sbwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;CPUUtilization8&quot;
        title=&quot;&quot;
        src=&quot;/static/eb4f933308cf64134432c0697701ae10/8c557/CPUUtilization8.png&quot;
        srcset=&quot;/static/eb4f933308cf64134432c0697701ae10/4edbd/CPUUtilization8.png 175w,
/static/eb4f933308cf64134432c0697701ae10/13ae7/CPUUtilization8.png 350w,
/static/eb4f933308cf64134432c0697701ae10/8c557/CPUUtilization8.png 700w,
/static/eb4f933308cf64134432c0697701ae10/9cab2/CPUUtilization8.png 864w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Of course, this test is quite simple, you should not use results from Tier-1 machines for Production planning, as Tier-2 VMs have a different architecture(SQL Azure instead of SQL Server), but I think the behaviour for Tier-2 will be the same: the more expensive service you use, the faster system will work.&lt;/p&gt;
&lt;p&gt;I don&apos;t have access to Tier-2 VM now, also it is not clear what level of resources Microsoft gives you for Tier-5(Performance) and Production and how these resources operate comparing to local DEV boxes. If you have any information regarding this, please share it with us.&lt;/p&gt;
&lt;h2 id=&quot;summary&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#summary&quot; aria-label=&quot;summary permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Summary&lt;/h2&gt;
&lt;p&gt;The cloud has some amazing capabilities. Even in this test by just one click(changing a VM size) I increased the load performance by almost 50%. But everything has its price. The current &lt;a href=&quot;https://go.microsoft.com/fwlink/?LinkId=866544&amp;#x26;clcid=0xc09&quot;&gt;Dynamics 365 Licensing Guide&lt;/a&gt; has more than 50 pages, so the pricing structure is quite complex. And probably in the cloud world instead of asking &quot;Can the system load 1M journal lines?&quot; you should ask &quot;What will be the cost of loading 1M lines in 2 hours?&quot;.&lt;/p&gt;
&lt;p&gt;You can use the provided example for performance testing of File-based integration for D365FO. I uploaded files used for this post to the following &lt;a href=&quot;https://github.com/TrudAX/XppTools#devtutorialintegration-submodel&quot;&gt;folder&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I hope you find this information useful. As always, if you see any improvements, suggestions or have some questions about this work don&apos;t hesitate to contact me.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[How to implement file-based integration in Dynamics 365 FinOps using X++]]></title><description><![CDATA[The blog post describes a sample approach to implement recurring file-based integration in D365FO using X++]]></description><link>https://denistrunin.com/xpptools-fileintegledger/</link><guid isPermaLink="false">https://denistrunin.com/xpptools-fileintegledger/</guid><pubDate>Thu, 17 Dec 2020 22:12:03 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Update 2025-02-04: The integration was updated to a new Azure Storage DLL &lt;a href=&quot;https://www.linkedin.com/pulse/new-way-working-azure-file-share-from-x-denis-trunin-okmcc/&quot;&gt;A new way of working with Azure File Share from X++&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;There are many ways to implement integration with Dynamics 365 for Finance and Operations. One of the comprehensive descriptions of possible options can be found in this great post by Tayfun Sertan Yaman: &lt;a href=&quot;https://devblog.sertanyaman.com/2020/08/21/how-to-integrate-with-d365-for-finance-and-operations/&quot;&gt;How to integrate with Dynamics 365 for Finance and Operations&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The file-based approach is probably the oldest and commonly used integration type. Using this approach, an external system and D365FO send messages by reading/writing files into some shared network folder.
It has the following advantages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Very clear responsibility (you either have a file in the correct folder or not);&lt;/li&gt;
&lt;li&gt;It is easy to troubleshoot (you can view the file, can modify it, etc..);&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A good overview of some options how to work with files in D365FO can be found in the following video by Ludwig Reinhard &lt;a href=&quot;https://dynamicsax-fico.com/2020/05/18/mass-importing-data-in-d365fo/&quot;&gt;Mass importing data in D365FO&lt;/a&gt;. He describes the pros and cons of two solutions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Recurring integrations scheduler(&lt;a href=&quot;https://github.com/microsoft/Recurring-Integrations-Scheduler&quot;&gt;RIS&lt;/a&gt;)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;LogicApp &lt;a href=&quot;https://github.com/ganroman/D365FO_DIXF_ZipPackage&quot;&gt;package&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Both these solutions are valid for a lot of cases, but they have the following issues:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You need to install/support additional software(Cloud-based LogicApp or On-premise RIS)&lt;/li&gt;
&lt;li&gt;They use the Data Management Framework to load files, that doesn&apos;t support transactions. This can be critical for &lt;a href=&quot;https://github.com/ganroman/D365FO_DIXF_ZipPackage/issues/1&quot;&gt;errors processing&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In this blog post, I try to describe another possible solution(with &quot;Consuming external web services&quot; &lt;a href=&quot;https://devblog.sertanyaman.com/2020/08/21/how-to-integrate-with-d365-for-finance-and-operations/#Consuming_external_web_services&quot;&gt;type&lt;/a&gt;) for the File integration using X++ that is resolving these issues.&lt;/p&gt;
&lt;h2 id=&quot;solution-description&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#solution-description&quot; aria-label=&quot;solution description permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Solution description&lt;/h2&gt;
&lt;p&gt;Let&apos;s consider that we need to implement a periodic import of files and create ledger journals in D365FO based on these files. They have the following structure:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 436px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/cd3959bfed3f8957c78399f66fdaa72b/8574c/ExcelFilesTask.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 68%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAClklEQVR42o1Ta3OiQBDk//+kq7tcLlGjEiICioIvVECeijwUEumbWSup1H06qrqWnZmdnenplcIwBMP3fURRBM/3EAQBPM9DHMcIo1DYD4eDWIMwoDWkOJ980d1G8QyOkWzLhmVZ0DQNq9UKtr3AwrbxpiiwbAs2+dZkZ/98Phcxq/Va+O0FxRJ04bNEUdLD4090u10YhoHlYomH598YDPqYzWaEObr9DrovHRi6jjnt+0ofA3lIPlMkYft0OsHUNEW1Um/YgaK8IaL22luLntLDYrlA3dR4rxvoMx3aRMP1WuP28QHVeINm6Giad1RVJehqmgZJEmO/398TDgcycXKgQ1f05C5m1hx5nqPIC4wnKlRdxTk7oyorjAwFY2qxLEpkp5PgOqc4wbvrccJnyEMZPhHaUEWdwRO1MhO3cwLVGGGkjVBQguvlCkV7xUgdkf+C8/kseCvLkioN4LouJFUfwaT+N5sNYuLAXM2w3K4Rn1IcqQJzPsXY0OA4DnzPp/bHMIk/l6rZ73ZiSJyIz3OMdDgEVJ0vbtq5e8gLDb+NIX7pLxhT8jCMsF5vxEGWRXC4S4Tjv4N9YsppSpUcjzidMjGYMI6QkC1JE8REdHpMkWUZOC5JEqFNBv9/7r//S+kxx27rYEflM9FcPmuLV4faYPuadMcDu91u+KBJ88po2/v+C2STqupKpFa4XC7CyAeLohD7uq4FPn1t2wq51CQTxoWlJBK3Au8UI2VZgby84H+/gi5PTzlRdEaYZJTk9uU75yUk010SofSOg1BM0dluiYvkq6J/0VDFLBfmnfXH/9yRuCzPIP14fULvpYdBf4AePcHHxz+Q5VcxVZbCd7AsbHrnOj03VVWh03OdEFh2jrOldYK/D8MLADtV4NUAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Excel files task&quot;
        title=&quot;&quot;
        src=&quot;/static/cd3959bfed3f8957c78399f66fdaa72b/8574c/ExcelFilesTask.png&quot;
        srcset=&quot;/static/cd3959bfed3f8957c78399f66fdaa72b/4edbd/ExcelFilesTask.png 175w,
/static/cd3959bfed3f8957c78399f66fdaa72b/13ae7/ExcelFilesTask.png 350w,
/static/cd3959bfed3f8957c78399f66fdaa72b/8574c/ExcelFilesTask.png 436w&quot;
        sizes=&quot;(max-width: 436px) 100vw, 436px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;A company where ledger journals should be created is defined in a file name(text before &quot;_&quot;) and one file represents one journal.&lt;/p&gt;
&lt;p&gt;As the result we should get a posted journal in that company:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/63ff35971460f8cf7d1e6f8c2ca680de/9d5da/PostedJournal.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 58.285714285714285%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB0klEQVR42nWSiW7bMAyG/f4vtw5oUyy7kiWxY+s+fMV2/pH0nG7dJoD4JZH8RFEqdrtnPD19wG63I31CVV4QvEOK4R/mf9n7vTdfURKgqkpo1QgopyjGQTm9JW7zh/4B+g3onRVA12Z0OSEGR2CLROpJeR2DB8fx3DvziAnB/Q1USkt1xmgopUgNmobW2qCuWbXs1XUNayz5WGlPKzhr5DAGrkrAGOxaUeSKAqwNBPAwNkIbrsSThtW0Q0tX7tuEoUukQdaZcrscpR1FpTtUKsGEG3x3hw4jzlcPlyacmwTlRxjf0SEWNnQ41QQOg8S7vMBQXGVauHZBqTOKzweNl/2Z7ITTNeHbyeDjy3e8fqmwPxgcyoCvhysulxKXinyvRzx/+iE5h4vHkfzHKpIF7I81inEgulXS7GUe0dNVmroEt4KvMt166Y9zjnwtjKIe6kZyOJf9bPM0yMsXy7IgpSTGY5omuV7bduj7XvZY27YFx4YQ4UOQ+Pv9Lv55nkVvt9sKzOTMOT+A1lp03f+A9KKRHiCvQLZxHCWO/QScJYBtA/L34QMYyoN1Azr6j96vP4LXPLZK+eC1QkreKuTyPX0Vdg7DIHusDN0q3Fr0HshX/gmv3pYWjxRxoQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Posted journal&quot;
        title=&quot;&quot;
        src=&quot;/static/63ff35971460f8cf7d1e6f8c2ca680de/8c557/PostedJournal.png&quot;
        srcset=&quot;/static/63ff35971460f8cf7d1e6f8c2ca680de/4edbd/PostedJournal.png 175w,
/static/63ff35971460f8cf7d1e6f8c2ca680de/13ae7/PostedJournal.png 350w,
/static/63ff35971460f8cf7d1e6f8c2ca680de/8c557/PostedJournal.png 700w,
/static/63ff35971460f8cf7d1e6f8c2ca680de/9d5da/PostedJournal.png 871w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The integration will be based on two of my previous posts: &lt;a href=&quot;https://denistrunin.com/xpptools-readexcelfile/&quot;&gt;How to read CSV/Excel files&lt;/a&gt; and &lt;a href=&quot;https://denistrunin.com/xpptools-createledgerjournal/&quot;&gt;How to create ledger journals in X++&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In order to copy files to Azure storage from the local PC the &lt;a href=&quot;https://docs.microsoft.com/en-us/azure/storage/common/storage-use-azcopy-files&quot;&gt;following&lt;/a&gt; command may be used&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;powershell&quot;&gt;&lt;pre class=&quot;language-powershell&quot;&gt;&lt;code class=&quot;language-powershell&quot;&gt;azcopy &lt;span class=&quot;token function&quot;&gt;copy&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;C:\AAA\CCC\Files/*&quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://f365vmstorage.file.core.windows.net/ledgerinterface/TestUpload/SASToken&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; used in bat file need to replace &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; to &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; in SASToken value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;proposed-solution&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#proposed-solution&quot; aria-label=&quot;proposed solution permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Proposed solution&lt;/h2&gt;
&lt;p&gt;In the following section, I provide some code samples that can be used as a starting point to implement a periodic file import and processing.&lt;/p&gt;
&lt;h3 id=&quot;file-share-connections-form&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#file-share-connections-form&quot; aria-label=&quot;file share connections form permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;File share connections form&lt;/h3&gt;
&lt;p&gt;As D365FO is a cloud-based system we need to put our files to some network location that is accessible from the cloud. Probably the simplest way to achieve this is to use &lt;strong&gt;Azure file share&lt;/strong&gt;. It can be created with several clicks from Azure portal and you can even map it as a network drive in Windows(or use Azure Storage &lt;a href=&quot;https://azure.microsoft.com/en-au/features/storage-explorer/&quot;&gt;Explorer&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;For this post I created a new account with the following folders:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 608px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/e7a8fe7eeffd20528bf84856040dc76b/18872/StorageDirectory.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 50.28571428571429%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABX0lEQVR42o1SXU/DIBTl//+xJb5pfNBEN426shVKB4XSQnu83LVx2TTxJif3C845NBXdMKPrR7hxQu0z6i5DukQ5wYTMs4r6MgtjRkOzA9UuZgAzrkM8+wmbp1c8PtzDdYGHaZqR6SwlzEueqOCamvP+lowJ92FE1Tqo+oBhiMt4YVq73++yv3U3L1dE7wNaY2CahtH3PSOEgBjPAiHNaGjnA+3o2cY00FrDxwGmi2gbjdaPUDZAvMgjdm87fH2842Q0bGtIQDNMo4i0h3MWSilGIWuIoAiexeNSR+6FspHVdF2jro+o1ZEWAeM4MKZpgtKGHZYL3nvOOWeklBiXtYis4Hm4Yr76aNFuyWnAf0JIUt9XFdsubgpZyWtdIp/u0LkWfYzsvjhcz1xDnEb6D+kZzrkbZ2ukdoOD/ISUB1QkLqXkp1+K/xDSR5ayYtW/IoctCbaEDtZaFi8v+o3wG2OWCvwrmgcxAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Storage directories&quot;
        title=&quot;&quot;
        src=&quot;/static/e7a8fe7eeffd20528bf84856040dc76b/18872/StorageDirectory.png&quot;
        srcset=&quot;/static/e7a8fe7eeffd20528bf84856040dc76b/4edbd/StorageDirectory.png 175w,
/static/e7a8fe7eeffd20528bf84856040dc76b/13ae7/StorageDirectory.png 350w,
/static/e7a8fe7eeffd20528bf84856040dc76b/18872/StorageDirectory.png 608w&quot;
        sizes=&quot;(max-width: 608px) 100vw, 608px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;To store connection details I created a simple form in D365FO&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/ddcb75b81bd1ebfee131ffc89d5bab5c/cecac/ConnectionTypesForm.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 40.57142857142858%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABU0lEQVR42o2RyW7EIBBE/f9fN7lEySFKZvECZrHBNowNrpTJHCaXKEhPXQJ10RSVUA7DMMA7X6o2DkZrotD3PZxzmKcJMSy4x1DqM2GZf1ENdsSy8DBGpJSw54yUE3VGzjv2fWdjgBQd6tsNvRTomgb19Uot4cah4N0Iz1qdTi/QStJgxXqPNEgAciHnDZn7d+6LrsXlckZT12ymgXdY5gnWaAgh+Dpb9qrZjzi3I14/FN4+Ja5ygRgyOpuKfv/S0HYqUxhtGIlB4MQrX3REMHkPxWg0I/LUVVoDehtwY3PbzxDmDuXyg4RazjT0mJijUrqYKqUQYixxZEJR9BFXFcOMbVvx1zryHaxF0zaQzK3j87dtK2fFNOfCoYvhuq54XPQDntgPwwDDz7s1jKQRnNjBLxHjFLDE7dfl/5zwMHRohSH8BGkglUUnGcEw8eO2MvHBN0XFaWqgVSihAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Connection types&quot;
        title=&quot;&quot;
        src=&quot;/static/ddcb75b81bd1ebfee131ffc89d5bab5c/8c557/ConnectionTypesForm.png&quot;
        srcset=&quot;/static/ddcb75b81bd1ebfee131ffc89d5bab5c/4edbd/ConnectionTypesForm.png 175w,
/static/ddcb75b81bd1ebfee131ffc89d5bab5c/13ae7/ConnectionTypesForm.png 350w,
/static/ddcb75b81bd1ebfee131ffc89d5bab5c/8c557/ConnectionTypesForm.png 700w,
/static/ddcb75b81bd1ebfee131ffc89d5bab5c/cecac/ConnectionTypesForm.png 728w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Notes:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Another alternative to Azure file storage can be an SFTP site. Check this article that describes this in details: &lt;a href=&quot;https://dynamicsax4u.wordpress.com/2020/08/18/read-files-from-sftp-server-and-write-data-in-ax365-part-1/&quot;&gt;Read File’s from SFTP Server and Write data in AX365&lt;/a&gt;. &lt;strong&gt;Update:&lt;/strong&gt; (thanks to Tommy Skaue and Volker Deuss): SFTP connection doesn&apos;t recommended for new deployments: &lt;a href=&quot;https://docs.microsoft.com/en-us/dynamics365/fin-ops-core/dev-itpro/deployment/known-issues-new-deployment-experience#ftp&quot;&gt;https://docs.microsoft.com/en-us/dynamics365/fin-ops-core/dev-itpro/deployment/known-issues-new-deployment-experience#ftp&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Instead of storing Connection details in a D365FO table,a more secure solution is to create an &lt;strong&gt;Azure Key Vault&lt;/strong&gt; and put all secrets into it(for example like &lt;a href=&quot;https://jatomas.com/en/2020/06/02/azure-key-vault-msdyn365fo-setup-certificates-passwords/&quot;&gt;this&lt;/a&gt;) and store a reference to this Key Vault in our new Connection table.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;inbound-message-types-form&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#inbound-message-types-form&quot; aria-label=&quot;inbound message types form permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Inbound message types form&lt;/h3&gt;
&lt;p&gt;Next form to describe our integration will be &lt;strong&gt;Inbound message types&lt;/strong&gt; form&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/6f9cd71144871b7a851fa9385ac7c350/9c177/MessageTypesForm.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 94.85714285714285%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAACXBIWXMAAA7EAAAOxAGVKw4bAAACnUlEQVR42o1U2XabMBT0//9U3/qWPjRxEidObFazCAQCJLF5OsJ22rQ9dnx8jyRAo5k7A6tCKjRNg7pWKEuFSkrOKxRFAaVqlIWAlCWyLEXXdjAdS3ewxpXmXC/jpVZ5XmAYeozjAByP/M+Y52mpobdIkwOiMEQcR6xwWSeHGLLkgTy4VSUaVbFqNFyv3rZbFJI3tEHbGchKYRgJNh5hbU9mCfzAX9gGHJMkQZ4LdF0LQ0bffqQI4pzsT0pXxlo87WtsQ4XdQWPjyWX+znleGlT+HlUYQFNyS3auGjLs0gQ6TSH8GCqO0fJaE4VY9dZQ3owjcKpFtpsBPfuTUkFCMNefaZrYmhETyxpDBZYb2CKu3Q6bZSfAIwH/93OAhR8gzgrIul2uzefDDAFTAmhtCW7RTzyERv4DeGG3ANJRGUaQyqBuzG+G08m0lj1rVENzanqg2Za/GDrpwzB+Yig8j2a1C8ilHX8eemaxDENZXpc8MG+l70EUJbMoPxiNwyVi5zrvvwl4khxCti0qpWCZV933mP5+/sJQiBsMXeMf1wgeHuDf3yN+esLh+Rlyv0cbRehcXDguxbliIr4EGD4+ImI50MrzYVweCVL7PhoqcMDdgdfY76uAllIFNxWUK1nC9ZFGuZ9zW7Bnmod+tOgrpuR7n/2zy6to+hn9cHrWBV3ww+Hcd0Gf2Mebpsy2w/M6xOvBsWD2zm/TwpBBVlQwjOeYucjdMmWeBmzv1nj5fof8/icEzak3m6UqN75sPtY1DXPr65Ipp3jfInp7xcG9MWTgouTKMJOKEvtOszUaPXupac51QMopaIpwH1tu/PRaMtxFVcFwHC/BTrPbDMVuBxkESPceKhcNsmz5Paz4ufKYyff1GhnvNbxe7nb4BU9Sukb8NCfgAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Message type&quot;
        title=&quot;&quot;
        src=&quot;/static/6f9cd71144871b7a851fa9385ac7c350/8c557/MessageTypesForm.png&quot;
        srcset=&quot;/static/6f9cd71144871b7a851fa9385ac7c350/4edbd/MessageTypesForm.png 175w,
/static/6f9cd71144871b7a851fa9385ac7c350/13ae7/MessageTypesForm.png 350w,
/static/6f9cd71144871b7a851fa9385ac7c350/8c557/MessageTypesForm.png 700w,
/static/6f9cd71144871b7a851fa9385ac7c350/9c177/MessageTypesForm.png 880w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;This form contains 3 main sections:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1 - Details tab&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Defines &lt;strong&gt;Incoming&lt;/strong&gt; and &lt;strong&gt;Archive&lt;/strong&gt; folders in our File share.  There will be no &lt;strong&gt;Error&lt;/strong&gt; folder: if an inbound file fails validation then the error details will be found in the message table.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Contains link to the Class that will do processing from this folder. The class should extend a base class &lt;strong&gt;DEVIntegProcessMessageBase&lt;/strong&gt; and implement the following method:&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;c#&quot;&gt;&lt;pre class=&quot;language-c#&quot;&gt;&lt;code class=&quot;language-c#&quot;&gt;abstract void  processMessage(DEVIntegMessageTable  _messageTable, DEVIntegMessageProcessResult _messageProcessResult)
{
...
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This method will be called by the integration engine outside of a transaction, so all transaction control can be implemented per Message type. There can be different options here: one transaction per message, multiple transactions(for example if a file contains several independent journals) or a single transaction per line. The result of processing and the current stage should be written to &lt;strong&gt;_messageProcessResult&lt;/strong&gt; variable, so in case of an unhandled exception, this information can be saved for review. Also, this class will be created one time per full import session, so it can implement different caching options.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2 - Operation parameters tab&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Contains parameters that are individual for the current operation. In our case it will be:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Ledger journal name&lt;/strong&gt; reference for journal creation&lt;/li&gt;
&lt;li&gt;Post the journal(No/Yes) and&lt;/li&gt;
&lt;li&gt;A file type(Excel or CSV)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;3 - Advanced settings tab&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Contains some common parameters: If we should use Parallel processing for our incoming files and how to move files to an Archive folder(with the same name or append DateTime to the file name). Parallel processing is based on this post: &lt;a href=&quot;https://denistrunin.com/xpptutorial-batchmultithread/&quot;&gt;A simple way to implement a parallel batch processing in X++&lt;/a&gt;, so for example if we set it to 10 and have 1000 incoming messages, 10 batch threads with 100 messages each will be created.&lt;/p&gt;
&lt;p&gt;Also, this form contains two servicing operations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Check connection&lt;/strong&gt; button that tries to connect to the specified directory&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Import file&lt;/strong&gt; button that can be used in testing scenarios to manually import a file from a user computer without connecting to network file share&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;incoming-messages-form&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#incoming-messages-form&quot; aria-label=&quot;incoming messages form permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Incoming messages form&lt;/h3&gt;
&lt;p&gt;This table will store the details on each inbound file.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/6620daab7b90425f1aaca78aa204cc8f/84cc5/MessagesForm.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 65.14285714285714%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACD0lEQVR42l1T2Y7bMAzM/39cX7oLFBvHdrLN4VO35CPOlKTjpK2AgSWSHo5Iaqe0hdEKxmi0nV73BGsNuraF6js4a2HZ39Zom0rOMQQ4H6CNx+nmcG0cUvTYjcOI6+WMz4+f+Pr6haLIUZY58kOGvmvh3UrmKIFn0NlZLbbVrhHcCj7vpiFBq56yN+i6Dkop9KSqrmt47zEMA4aUBClFwbpP732MT18iwnEQsvPlJlfVhEDXYXhPaliRcyu8I5t7nTnhe29FvShU2uDWkHznEeNAZGRTmoICKRwRE9liQkfqlTKkZKQae4nhvbEOXc91d9gtU8L+2+HH3iE79fjdzjh3C85Vj1vVoqFGxWGCCRM+C4uvb4+reqCsE4oq4tIv2J80PrIG5cVQU+jukWtAP3HG+b5geQDWBeo6KaIpmBcI+CasntwSd1+2WE9TQs2jq+8GKWzEOI5UP42FI2jxWBitpYbb4nOMQfYLkxF4cS3Zx/X9h9AYg8fj8QrijnNz2MLQQhhfhH/H6mfyN+E0YZ7nlxomsjTA20+i0BgZjf+XKCSfEHINQ/A0S0myy9wRtpFggs3m7Doq832WRBv4dozXHPLz4lnkOmi1zuL2HGU2afDZvvn51UQSEYhcvk94bgoTNnWFQ7ZHmR9QEMqCn94BeZ7JEzyWJdkKnI4ljuQ78rcsJPaQZRLPz7euKvwBklDkt24rVucAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Messages form&quot;
        title=&quot;&quot;
        src=&quot;/static/6620daab7b90425f1aaca78aa204cc8f/8c557/MessagesForm.png&quot;
        srcset=&quot;/static/6620daab7b90425f1aaca78aa204cc8f/4edbd/MessagesForm.png 175w,
/static/6620daab7b90425f1aaca78aa204cc8f/13ae7/MessagesForm.png 350w,
/static/6620daab7b90425f1aaca78aa204cc8f/8c557/MessagesForm.png 700w,
/static/6620daab7b90425f1aaca78aa204cc8f/84cc5/MessagesForm.png 898w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Every message has a status field that can contain the following values:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Ready&lt;/strong&gt; – a file was read to D365FO and successfully moved to the Archive folder.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hold&lt;/strong&gt; – The user has decided not to process the file. This is an alternative to a delete option&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;In process&lt;/strong&gt; – system-generated status, a message is processing now&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Error&lt;/strong&gt; – failed validation&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Processed&lt;/strong&gt; – completed successfully&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In this form it is also possible to do the following operations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;View incoming file context&lt;/li&gt;
&lt;li&gt;Filter by different statuses&lt;/li&gt;
&lt;li&gt;View a detailed error message&lt;/li&gt;
&lt;li&gt;Change the status to process the message again&lt;/li&gt;
&lt;li&gt;View file processing statistics (processing duration, time, number of lines)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;load-incoming-file-operation&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#load-incoming-file-operation&quot; aria-label=&quot;load incoming file operation permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Load incoming file operation&lt;/h3&gt;
&lt;p&gt;It is a periodic batch job that we can run for one or multiple message types.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 485px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/fcf1db8724112b5c5d2bc3681133ae66/44c61/LoadIncomingFiles.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 117.14285714285715%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAXCAYAAAALHW+jAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACJklEQVR42qVV2XLiMBDk/39lfyJV+YJs1RYPHOaKDfjAki1bli11ZoTtLAFyEFVNyYBodc/0jCdhGGI+n2O5XCIIAsxmMywWC0ynUxRFAWMMmqb5MvhcVVWYSClhrUXXdX5v29Yf4N05h58sBp0wC0ZWSnlGDDQsBvxujIBlWSJNMxyPR4oYVV2PYLeW6+M+QwLUuqao/G5t96ks29K5WoGJ6P7y4QoPKGWBdVhgtjkheM0hyhZ1A6ja+ueB6LD/eU7x9JJB5hmBqgs1PUOFNGsRhgrJsfZA2gBV4yBUN8obAJ/+Nfi7NmiNRkdFvJLM1PkGlsrB1ebC2A+Hr3L5XzEuAFny626HcLdFRJ6Moj1WqwBJktzOoe3Z3iiaB2S7GKqDrEAS8KvVA5aotEUiyOmapHZn2RwPGZtzuNmsECznWJPUIFhiu91is15DCPGpJ+8C5nnu41biH5BMdkliSJFTD58N3pDBOYxpHgNkp7/bxP2uKDxt2CJZRv18OFA/H8g6Ifb7vf/8E9njtCmJJTOVRenb6UT5FEKCHfCQ5EIDmXLIST05B7F01H7uMclc5VprcE+XfVh33Qg8dPlynp38nyHnV/OQJfMrII5jymMK1ff2x1VVCgfKKUcURchPpxF4aIKaxtnoQ00sOe6thn5LqXi5z6/wRRT0fB4s9h3wbJuvV1kWNNnJDWk6XuyYXXtu14scfuf9wSOtNeYy6DtmxUAD4Bts2QtcHGCk6gAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Load incoming files&quot;
        title=&quot;&quot;
        src=&quot;/static/fcf1db8724112b5c5d2bc3681133ae66/44c61/LoadIncomingFiles.png&quot;
        srcset=&quot;/static/fcf1db8724112b5c5d2bc3681133ae66/4edbd/LoadIncomingFiles.png 175w,
/static/fcf1db8724112b5c5d2bc3681133ae66/13ae7/LoadIncomingFiles.png 350w,
/static/fcf1db8724112b5c5d2bc3681133ae66/44c61/LoadIncomingFiles.png 485w&quot;
        sizes=&quot;(max-width: 485px) 100vw, 485px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;It connects to the shared folder, reads files, creates a record in &lt;strong&gt;Incoming messages&lt;/strong&gt; table with &lt;strong&gt;Ready&lt;/strong&gt; status, attaches a file content to this message and moves the file to an Archive directory. If &lt;strong&gt;Run processing&lt;/strong&gt; is selected, after the load system will execute processing of the loaded messages.&lt;/p&gt;
&lt;h3 id=&quot;process-incoming-messages&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#process-incoming-messages&quot; aria-label=&quot;process incoming messages permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Process incoming messages&lt;/h3&gt;
&lt;p&gt;Message processing may be executed as a separate operation - &lt;strong&gt;Process incoming messages&lt;/strong&gt; that selects all not processed messages and calls the processing class for them.&lt;/p&gt;
&lt;p&gt;The logic of how to process the file is different per message type/class. For the simple scenario, the class can just read the file content and create some data in one transaction. For this blog post, I implemented two step processing. See the sample diagram below:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/b4abd11cc48f4c33cd57680eb7821ab0/ea7fb/ProcessDiagram.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 74.85714285714286%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB3UlEQVR42o2UiW6rMBBF+f8PTFHQS0APEmK2BIc1ganPtKZR1bcgXQ2Ymes7ix3keS5VVUtdO7zYqqrker3K7XaT8+ks8TGW4/Eocfxl+df3vXRdp/Z+v0tgzEUKUyhBVZZKXpaVQ6kOTdNoYBIn8rZ7k91up9a4mHGaZFkWeT6faud5lqCuK7HWStu20tTNpgqws3Wk4zjK4BSwKUT4T45sGIYfCJ2TdWSaWnYWczEq37ZWFQKCWWNDY8y2BiB7PB4KvoOiKNTxpspatahEDYEQEYTK/JxLlmWaDd/XT18UA96DxjWhdKTRPpJ9uJfQ1ScMw82ZwGVZVQFEfo10aSCCLi4r38gAZmqFswdKCRinUYl4t3er5UiSRNrP/9SMh/jluahvwI/VKaCoHuu6boX2he9c+lEU6figijWU4uvLok3xhCx4fO8cqqknShqXMgQ0UWN/JFz/TEjnmIRTmsnh10Fxyk6ubhfdBJ++774IYWfRtx74UfBOpAZQVbiBR4QfG8RAPDv/mbH5m0L/rrUcB+FUZSljY7dNtGGusf+V8ishilHIkRzHaSNAJXY7Kf+qIUReDakxax/KPkaKWL+pEr7eGB6vNwjpFIXRywGkNOdwkN9pqt3/ftu8A6iThGvww9ntAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Process diagram&quot;
        title=&quot;&quot;
        src=&quot;/static/b4abd11cc48f4c33cd57680eb7821ab0/8c557/ProcessDiagram.png&quot;
        srcset=&quot;/static/b4abd11cc48f4c33cd57680eb7821ab0/4edbd/ProcessDiagram.png 175w,
/static/b4abd11cc48f4c33cd57680eb7821ab0/13ae7/ProcessDiagram.png 350w,
/static/b4abd11cc48f4c33cd57680eb7821ab0/8c557/ProcessDiagram.png 700w,
/static/b4abd11cc48f4c33cd57680eb7821ab0/ea7fb/ProcessDiagram.png 788w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;During the first step, the class reads the file and writes data into a staging table. A sample code for this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;c#&quot;&gt;&lt;pre class=&quot;language-c#&quot;&gt;&lt;code class=&quot;language-c#&quot;&gt;    while (fileReader.readNextRow())
    {
        linesStaging.clear();
        lineNum++;
        linesStaging.LineNumber     = lineNum;
        linesStaging.HeaderRefRecId = tutorialLedgerJourHeaderStaging.RecId;
        linesStaging.MainAccount  = fileReader.getStringByName(&amp;#39;MainAccount&amp;#39;);
        linesStaging.BusinessUnit = fileReader.getStringByName(&amp;#39;BusinessUnit&amp;#39;);
        linesStaging.Department   = fileReader.getStringByName(&amp;#39;Department&amp;#39;);
        linesStaging.CostCenter   = fileReader.getStringByName(&amp;#39;CostCenter&amp;#39;);
        linesStaging.Amount       = fileReader.getRealByName(&amp;#39;Amount&amp;#39;);
        DEV::validateWriteRecordCheck(tutorialLedgerJourLinesStaging);
        tutorialLedgerJourLinesStaging.insert();
    }&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then based on this staging data values, a new journal is created. As I wrote in this &lt;a href=&quot;https://denistrunin.com/xpptools-createledgerjournal/&quot;&gt;post&lt;/a&gt; there are two options to create a ledger journal: either using &lt;strong&gt;LedgerJournalEngine&lt;/strong&gt; class or using a data entity. The choice between these two should be made by answering the question: if the user wants to create the same journal manually, does he use manual entry or data import?. In this case, I want the result to be similar to manual entry, so &lt;strong&gt;LedgerJournalEngine&lt;/strong&gt; class is used.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;c#&quot;&gt;&lt;pre class=&quot;language-c#&quot;&gt;&lt;code class=&quot;language-c#&quot;&gt;ledgerJournalTrans.AccountType          =   LedgerJournalACType::Ledger;
ledgerJournalTrans.modifiedField(fieldNum(LedgerJournalTrans, AccountType));

DimensionDefault  dim;
dim = DEVDimensionHelper::setValueToDefaultDimensionCon(dim,
  [DEVDimensionHelper::BusinessUnit(), tutorialLedgerJourLinesStaging.BusinessUnit,
   DEVDimensionHelper::Department(),   tutorialLedgerJourLinesStaging.Department,
   DEVDimensionHelper::CostCenter(),   tutorialLedgerJourLinesStaging.CostCenter ] );

ledgerJournalTrans.LedgerDimension = LedgerDimensionFacade::serviceCreateLedgerDimension(
  LedgerDefaultAccountHelper::getDefaultAccountFromMainAccountId(tutorialLedgerJourLinesStaging.MainAccount), dim);

ledgerJournalTrans.modifiedField(fieldNum(LedgerJournalTrans, LedgerDimension));
ledgerJournalEngine.accountModified(LedgerJournalTrans);
....
ledgerJournalTrans.insert();&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;After the journal creation, this class runs journal posting.&lt;/p&gt;
&lt;h2 id=&quot;error-types-and-how-to-handle-them&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#error-types-and-how-to-handle-them&quot; aria-label=&quot;error types and how to handle them permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Error types and how to handle them&lt;/h2&gt;
&lt;p&gt;It is not a big task to create a journal based on a file. The complexity of integration is often related to exception processing and error monitoring. Let&apos;s discuss typical errors and how users can deal with them.&lt;/p&gt;
&lt;h3 id=&quot;file-share-connection-errors&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#file-share-connection-errors&quot; aria-label=&quot;file share connection errors permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;File share connection errors&lt;/h3&gt;
&lt;p&gt;If our batch job can&apos;t connect to a File share or read and move files, a batch job exception will be generated. It is a configuration error and it requires system administrator attention. Notification will be done using a batch job status. After troubleshooting the error system administrator can use the &lt;strong&gt;&quot;Test connection&quot;&lt;/strong&gt; button to validate that the system can now connect to the file share.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/73cf6179b87b978009cc6bc408846cc7/01267/TestConnection.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 78.28571428571428%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAYAAAAWGF8bAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACUUlEQVR42o1UCW7bMBDU/19VoG2AJkjqpImSWL5iWyepk5JFndOh7Bxtg8IrDFaUzOHs7FpWnORQqkSW5cizAlGsIJYLeJc/sLu5xsvFBeSjDZmlyNIUYRggSWIcDhq61mj0n7AuVzluNgnu/RpPosOj6GHvFe6fPfwysPd4WKewoxaPYYOHQMNmfpb9p7C+zAt8c1JcrAp8dRLmHN95f+U2uJPArQBm0YjbcMTsMwTDEae1dbXKMNvEmL0kuF5G+LmOmQVsr8Qi7uDIFnNBRZHGPGomOOL0jJiL9/cGVkoPdV3TkwO6rsPQ9xiGYcq9ue8HtE0DGYXwXRe+72K/2yIMAoS+B3e/RRB4KPIMpSpgzW7voIqcmzSJOpI2NLfGOPQARmJA1zYk8LF0HLjuns1LkecpCu7L0gTLxZwH+eTJYKk8h8Ny7YUPTxywcTM8LX3sAsV1BT9ukBU1YhFiye5HVFpValJjYMRIESGWYjrI6qloG9bY+CSQesKWZLuwwotfwJUkVJqbAqzXK/gey6ZKQeKCBAZH8nwq22rqA3p6979oaEeeJVQpkLLENEmorKDv1YSa/tcm1xUJ9bEZI+2aYK5x/LAGNAfW+BWxtKZtp0PGjxjHN5yvkOVELFvQy6OAdxITSilUVHoWoWbXy7KCTEuEMRtRtf/8xoxdwFE6k1BPhGleQyTscN1S2XCcV8KEUW1UnkVoTC9LdZxXzuRIkr9Lfo3zCPlPUhyNlF+bqqrelA0n4tc4uymm5KoqIWU8+SSl5OcuQxzHk3cfFf4Gb2HMBYWMFaMAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Test connection&quot;
        title=&quot;&quot;
        src=&quot;/static/73cf6179b87b978009cc6bc408846cc7/8c557/TestConnection.png&quot;
        srcset=&quot;/static/73cf6179b87b978009cc6bc408846cc7/4edbd/TestConnection.png 175w,
/static/73cf6179b87b978009cc6bc408846cc7/13ae7/TestConnection.png 350w,
/static/73cf6179b87b978009cc6bc408846cc7/8c557/TestConnection.png 700w,
/static/73cf6179b87b978009cc6bc408846cc7/01267/TestConnection.png 713w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h3 id=&quot;file-format-errors&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#file-format-errors&quot; aria-label=&quot;file format errors permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;File format errors&lt;/h3&gt;
&lt;p&gt;The next error type is a wrong file format, so we can&apos;t even read the file content.&lt;/p&gt;
&lt;p&gt;To test this case I renamed one of the columns&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 491px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/f43817ea18d243cdef51dd43c8729945/13566/WrongColumn.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 24.571428571428573%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAYAAABFA8wzAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABE0lEQVR42i1Q2W6DMBDk//+pD31rFao0CQFzxAbJxhA1DeFqEmOma7cjrWY9ntm1HGit4Uop5VkSt+czpFTgnKMmrWkatG3rWVPVde37Rjfkkz7nzlJJBCxNfJAxhqqqIKsSvChQZBmOUQSWphBC4EQaLzn46YSE/WluQBzHKEgTokRKM4JwFyJJYnxdLhhvHfavLxBhCH04oI0O+KbXDNOEiUpI7pfO8w+u/RWsSNF1HZ1nfz+OI4L3jzdst1v0/QBgxS76xO3awZonHmRciO1q4VCpEooWOMz3Ccc0xv3+oNQKYwystQg2+w2yPMcwjD7IeIKJBjnYdfUmYxas1Jda+L90GOYBWZnj+Xj+ewyWZcEvhCRz4lJKAXUAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Wrong column&quot;
        title=&quot;&quot;
        src=&quot;/static/f43817ea18d243cdef51dd43c8729945/13566/WrongColumn.png&quot;
        srcset=&quot;/static/f43817ea18d243cdef51dd43c8729945/4edbd/WrongColumn.png 175w,
/static/f43817ea18d243cdef51dd43c8729945/13ae7/WrongColumn.png 350w,
/static/f43817ea18d243cdef51dd43c8729945/13566/WrongColumn.png 491w&quot;
        sizes=&quot;(max-width: 491px) 100vw, 491px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;After the import users will see this file with the Error status. Notification can be done using standard filtering by the &lt;strong&gt;Status&lt;/strong&gt; column.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/2fb698711688699178d0a7a6d339ab2a/e619b/WrongColumnError.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 38.857142857142854%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABYElEQVR42nWQ2XKDMAxF+f+f60MJZjNgQiAhYJsYs6Zzq7iZLtP24cyVLNm+kndgCVJegBMsKuAHMZI0Q8BixKR+ECKMUkQxd7weGMIkQ142EMcaovpOA08nKczpBFOdMNZnaFFiKEsoIZzKXKDPCxd3WQZZFFBRiIGFUIxBBgQLoEPKowie6gfUxwo8jlFwjqaq0Db1kxNk10L1V+iug6JY9x3ao8A555802UMzhzfPMwS5CuhH3z+AhQycnITk4tX3IZWEtSPMaDA+sZMlpqfaH7m3zBOkNrhKg5tdiR1m2kk3DOP6P+bv2NuWGedLS4umXfU92ksDTa7MbXDcBk2op37wdf47dw6NMVB6gNYa67o6Hqt4fDDTKPu+u7Nt29zI3bXFjR555NZa17csi+shhxOSckB8tEiI8voG0d6RnzcEuUaQKRy4pPpItTvSesNLahBXi+stLjuyZvm88w4FJlbr4WZlwgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Wrong column error&quot;
        title=&quot;&quot;
        src=&quot;/static/2fb698711688699178d0a7a6d339ab2a/8c557/WrongColumnError.png&quot;
        srcset=&quot;/static/2fb698711688699178d0a7a6d339ab2a/4edbd/WrongColumnError.png 175w,
/static/2fb698711688699178d0a7a6d339ab2a/13ae7/WrongColumnError.png 350w,
/static/2fb698711688699178d0a7a6d339ab2a/8c557/WrongColumnError.png 700w,
/static/2fb698711688699178d0a7a6d339ab2a/e619b/WrongColumnError.png 787w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Users can view the error log, then download the file and check the reason for this error. There may be two reasons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Our code that reads the file is wrong. In this case, we can send this file example to a developer to fix the logic. After fixing the problem we can run the Processing again.&lt;/li&gt;
&lt;li&gt;External system sent a file in the wrong format. In this case, the user can send this file back to the external party, then change the message status to &lt;strong&gt;Hold&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;data-errors&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#data-errors&quot; aria-label=&quot;data errors permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Data errors&lt;/h3&gt;
&lt;p&gt;The file has a correct structure but contains a wrong data(e.g.. values that don&apos;t exist)&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 524px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/950c6ca82bd32e9f207e7ca3952f3e4e/664c8/WrongData.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 26.857142857142858%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAYAAABFA8wzAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABFElEQVR42iWP2XKCMBiFef8Ha6sX9gJFRMIaLHZAVhEh8DWkZ5LJPyfJWazLxSWMIqIoJI5jkjQhSRJiw0WUZUlV1TweD6SU+L4wvMwyAiEQIjC8ED55nmMdT0c+9x94nkffPwnSiDCNqduW5+sF66rXyrIq3KtLdvthGAauoafNU/2np2kamrqm1ts6OScO9oEsu7Hh7jqI3Re/zpnpdmMeR5Zl5T2N2kwYsQ2hDCirysxqns3ZdR2WfbTZH3YEQWhI52wT6irjc6DvWpRSrFpwVhNe4NHq5Bv86Ep+v5t50oJbi7Zttso23zqhTKW5LGRK6ro0W+KmRr0GlBac5rcW8Wm73rzb0hZF8S84TbrFYsz+AHpodmxYypMzAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Wrong data&quot;
        title=&quot;&quot;
        src=&quot;/static/950c6ca82bd32e9f207e7ca3952f3e4e/664c8/WrongData.png&quot;
        srcset=&quot;/static/950c6ca82bd32e9f207e7ca3952f3e4e/4edbd/WrongData.png 175w,
/static/950c6ca82bd32e9f207e7ca3952f3e4e/13ae7/WrongData.png 350w,
/static/950c6ca82bd32e9f207e7ca3952f3e4e/664c8/WrongData.png 524w&quot;
        sizes=&quot;(max-width: 524px) 100vw, 524px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;In this case, a Status of our Message will be &lt;strong&gt;Error&lt;/strong&gt; and an Error log will be generated.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/857f80f6bf6066dbe5a1229ea73fe2b6/46e51/WrongDataError.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 29.714285714285715%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABJ0lEQVR42jVRa3OEIBC7//8DO/1Qz9M7Kwjyflo1XbmWmQzDEpLNclvHJzSb4biEZRJRLASJbByKfSNIA8UMXoOCWzSCMkgpwXmHum241on3urlF4vnV4fH5iXWaYBiDnmdYzklINkRCWiUMcTUTiFoh5wxDZs57eEKt9S1Yt4qZBO59j2Ec8Ho90d07MM6QckKMoSH87TH6tu/7D1LwVI+wzsKHgOM4SJAeyVU1t0TEK0opGYXqicj/aOcUEelhJKFj3xGMbh02M7rbKP6tlgS+CMICZ3UjB2fgyTWn0EwuEWsURbN0pnua3XmeMEpTkgVCCKzqaspeHQaMzKP/DuBmh7AnBhbRjQqPyWKSheoHPnqDgZfG8c61eRWaozb0YTRTIUWL/QuVH8pM/3rSLAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Wrong Data Error&quot;
        title=&quot;&quot;
        src=&quot;/static/857f80f6bf6066dbe5a1229ea73fe2b6/8c557/WrongDataError.png&quot;
        srcset=&quot;/static/857f80f6bf6066dbe5a1229ea73fe2b6/4edbd/WrongDataError.png 175w,
/static/857f80f6bf6066dbe5a1229ea73fe2b6/13ae7/WrongDataError.png 350w,
/static/857f80f6bf6066dbe5a1229ea73fe2b6/8c557/WrongDataError.png 700w,
/static/857f80f6bf6066dbe5a1229ea73fe2b6/46e51/WrongDataError.png 1003w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Users can view this error, display a Staging data to check the values from the File and take some actions(e.g. create missing values in the related tables if they are valid). After that, they can Process this message again.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 671px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/6e46af2c59b27b29098c854d032ff84a/d0e73/WrongDataErrorStaging.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 80.57142857142858%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAYAAAAWGF8bAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACQ0lEQVR42p1Ta7PSMBDl//8vddRPAoreeymUlkdL2zSvpq/0uEkLXMBxHDOzs8k+TnbPJrOskCgKhqqqoJWE1hKCl6i0QpFnSNMUWZZCiBKmMqiNgTE1irICExVeYo3wpKHIx5XBTAhNwQpxFGGzCbDfx4jjCLvdFtvNGuF248/nNKGYEFG0w+l0hKQL/MWqhJbj3tlmTW0gpcTLr5/4+uUzfnxfYr5YYLlcYD7/hk8fP+D17c1Xz0s2JXKf7LQ7C347z2pT+fbWQYhgG0FSQMmKMZmETfsRhN8BejCnJ7uSYgKk2xnxWDDHnSSuFIketRZk41Qh9601RlI8h3Kceh+JEt6fE9e+ZcEFDmeN05nTgDjqpoepO9R1jyiR2O4ZohMnEWDSIk4EwgNDUtRer8MU0aHA8bDHrG0MylJgFUpK1jQ9GpJqr7I+tgiODaJzh30xIM6s136fW2wOFV4jiXXMwYlLX6Gm3tu2ATDA2v5OgB5939Bz0eTunwXWi7XdOJSmHt/fLopxPmee2HFyTpifoCOd0/lRvM/ty1GmKRs/lGOSIc/ZNP5xYkrya9J4vsntyTAfd7HdWm5q+iWKQHMopTAMrn3reSnp2biLLzan27aln5RT9YIo6b3ddXoF7Do31ZqSS59wWRU9q67v8bgciPuu71el9TMgY+wK2FFARr8kWa3QUiV+Tb5/Amya5q5CpxUBdWQfrP2PCinRcXLXMlVt7fDHljUB/BXQEf0esKMKyjhGGgQwRfEEaGhQj4C/Ac8xz0knIQFvAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Staging error&quot;
        title=&quot;&quot;
        src=&quot;/static/6e46af2c59b27b29098c854d032ff84a/d0e73/WrongDataErrorStaging.png&quot;
        srcset=&quot;/static/6e46af2c59b27b29098c854d032ff84a/4edbd/WrongDataErrorStaging.png 175w,
/static/6e46af2c59b27b29098c854d032ff84a/13ae7/WrongDataErrorStaging.png 350w,
/static/6e46af2c59b27b29098c854d032ff84a/d0e73/WrongDataErrorStaging.png 671w&quot;
        sizes=&quot;(max-width: 671px) 100vw, 671px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;In some implementations(EDI), we can even allow staging data editing.&lt;/p&gt;
&lt;h3 id=&quot;posting-errors&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#posting-errors&quot; aria-label=&quot;posting errors permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Posting errors&lt;/h3&gt;
&lt;p&gt;A similar type of error is a posting error. For example, in a current implementation if the journal is not balanced the error will be generated and the message gets the &lt;strong&gt;Error&lt;/strong&gt; status:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/5f5f72709155c0961fec408507553a5d/58fee/WrongDataPosting.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 29.142857142857142%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAA/UlEQVR42nVQ2W7EIAzc///AfapKmrPdZMNhEyDX1NAqL90ijcYGM7bnZvoBQRvsziFqBzc6NB9GWCNYwn4cYPZY/IKUVpznKUDhV+c2Ni3e73cMSkEPPeauxdQO0J8jgrM/gt6DiIQZIQaEELDv+2tBrTWqSkFVFeqmFlbo+g5+YXgRyielVOIs+p/QJWitwTQ95QPJWow1RcSwwDPJHZeiQ0Q8O8xiTZ42xlgQBLlZKHnCtm1Z0GL4eiKzMeKdeJlXYuZLUBwruZZ3kkaH2PAHxdtTPJwZqndSuKAbPd5qLTmjfziZmK5V0rrBSjMjjZ0jOPqNiQqs+J2n/gYgac/3JIeD2QAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Posting error&quot;
        title=&quot;&quot;
        src=&quot;/static/5f5f72709155c0961fec408507553a5d/8c557/WrongDataPosting.png&quot;
        srcset=&quot;/static/5f5f72709155c0961fec408507553a5d/4edbd/WrongDataPosting.png 175w,
/static/5f5f72709155c0961fec408507553a5d/13ae7/WrongDataPosting.png 350w,
/static/5f5f72709155c0961fec408507553a5d/8c557/WrongDataPosting.png 700w,
/static/5f5f72709155c0961fec408507553a5d/e996b/WrongDataPosting.png 1050w,
/static/5f5f72709155c0961fec408507553a5d/58fee/WrongDataPosting.png 1051w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;A possible variation to this approach is to create a document(journal in our case), try to post it, and even if posting fails, still set the message Status to &lt;strong&gt;Processed&lt;/strong&gt; and leave the journal unposted, allowing accountants to decide what to do with it. As we don&apos;t process in transaction this will be a simple modification for our process class.&lt;/p&gt;
&lt;h3 id=&quot;wrong-result-errors&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#wrong-result-errors&quot; aria-label=&quot;wrong result errors permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Wrong result errors&lt;/h3&gt;
&lt;p&gt;That is probably the worst scenario. The file was processed successfully, but the resulting journal contains some wrong transactions.&lt;/p&gt;
&lt;p&gt;To analyse the result, users can view the staging data and check that they are correct&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/a045bef50250e1f2176ef9da96a48ac3/e9beb/StagingData.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 55.99999999999999%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAByUlEQVR42nVS2XLbMAzU/39ZnYd0fMTjU1Jr+dLJQ6JISu4WoBI3nUk4swMQ3AUBgtF6m2K92SGOUxyOCfb7Iw6HGNvdAfPlCovlW/DZrtZbHJMTkvSE9NfXiDrj0JsOTZWjLO5o6opQosivhBtkU6OuCuTk85klruu/R2RMj1YrvK0WeHn5geVygdefr8HOZjPM53NKxEkrCNFASUGYrCQrn/spFjnbw3QtdvsYWXYOB5xAkrimigRVyBcyWKCVJF+SnfwPPBN2rQ5kKTUFFLw1GFwfwC20ioiUXJPA9W3g8iWGdFNSQRwBZ7ugpYQKdSNwOGvEmUByVrg1I+7igVNusfvNMY3konGtB2RXet+yRtEYbNMKmyQnFEivOugiTy0rpZGVPQrpcSk6VOqBRv9BSbaQI6QBauFw3p2RbWLUNOU8ueBG3HvT41YZQh90ke0NuG3vqFVvMXpH7dpP6OlswuQ7WGvDuzvSjoN7gvk0FBPeJaVbeRjTA4swFPk+hOf+HeqbuBTiX4VStdQ6T1KGfzlQpYYsJ21DBy5gcB6s4S/UUZUfcU/VcfyZcBwHEksiCjweD/Di1vgS7wd8Xt77wBuG/+O8/wsfMEQxB9zvCQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Staging data&quot;
        title=&quot;&quot;
        src=&quot;/static/a045bef50250e1f2176ef9da96a48ac3/8c557/StagingData.png&quot;
        srcset=&quot;/static/a045bef50250e1f2176ef9da96a48ac3/4edbd/StagingData.png 175w,
/static/a045bef50250e1f2176ef9da96a48ac3/13ae7/StagingData.png 350w,
/static/a045bef50250e1f2176ef9da96a48ac3/8c557/StagingData.png 700w,
/static/a045bef50250e1f2176ef9da96a48ac3/e9beb/StagingData.png 730w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Another useful option to troubleshoot this scenario is a parameter in the &lt;strong&gt;Message types table&lt;/strong&gt; for our operation: &lt;strong&gt;Post journal(No/Yes)&lt;/strong&gt;. We can switch it off, manually load a test file and check the created journal without posting it. And that may give an idea of what is wrong.&lt;/p&gt;
&lt;h2 id=&quot;summary&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#summary&quot; aria-label=&quot;summary permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Summary&lt;/h2&gt;
&lt;p&gt;I provided a sample implementation for a File-based integration for D365FO. The main concept of it is to create a basic framework to simplify troubleshooting(most typical errors and all related data can be viewed in one form - Incoming messages) and provide some additional logging.&lt;/p&gt;
&lt;p&gt;This may or may not be appropriate in your case(there are different options how to implement this). Anyway I recommend to use the following checklist while designing the integration: &lt;a href=&quot;https://github.com/TrudAX/TRUDScripts/blob/master/Documents/Integration/Integration%20Data%20Flow%20Requirements.md&quot;&gt;Integration solution specification&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I uploaded files used for this post to the following &lt;a href=&quot;https://github.com/TrudAX/XppTools#devtutorialintegration-submodel&quot;&gt;folder&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Another important question when you implement a solution like this: is how fast will be your integration. I wrote about sample steps for performance testing in the following post: &lt;a href=&quot;https://denistrunin.com/xpptools-fileintegledgerperf/&quot;&gt;D365FO Performance. Periodic import of one million ledger journal lines&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I hope you find this information useful. As always, if you see any improvements, suggestions or have some questions about this work don&apos;t hesitate to contact me.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Analysing Dynamics AX / Dynamics 365FO batch performance using Power BI]]></title><description><![CDATA[The blog post describes how to analyse execution of batch jobs in Power BI Desktop]]></description><link>https://denistrunin.com/performance-powerbibatch/</link><guid isPermaLink="false">https://denistrunin.com/performance-powerbibatch/</guid><pubDate>Wed, 25 Nov 2020 22:12:03 GMT</pubDate><content:encoded>&lt;p&gt;Batch task processing plays an important role during Dynamics AX / Dynamics 365FO performance analysis.  Batch tasks are executed on a separate server but may affect system performance producing a load to SQL Server database. In this post, I show how to use Power BI to analyse batch performance.&lt;/p&gt;
&lt;h2 id=&quot;getting-the-data&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#getting-the-data&quot; aria-label=&quot;getting the data permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Getting the data&lt;/h2&gt;
&lt;p&gt;The source data for our report is a &lt;strong&gt;Batch execution history&lt;/strong&gt; table(BATCHHISTORY) where the system logs all batch runs(you need to check that &lt;strong&gt;&quot;Save job to history&quot;&lt;/strong&gt; flag is enabled for a batch job).&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/625a6ea08aab4f3cba9669a9e6ece443/142fb/BatchHistory.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 26.857142857142858%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAYAAABFA8wzAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAxklEQVR42p2QSQ7CMAxFc/8rMpQ28zwVCVYfJ4VNlyysKF/207OZ4BzrukIqCSEFYozY947e6l/Fck4T0FpHbQ3v1wvPE3Dvjer8P+qcMWsUGS64XO+w1iEGB6M1SklotaDXihA8ciLz77BzlnoNrNGUp5l5yhxlTAhFq2rElJFLI5iCFBu9Ekap2RRCnMCfzZCQgmOcy3t3ZDTHtweY8xHWRaRcCVrAhcHGLRmWw5CalbYw5hgc2YAty402e9BGfpoPwwH/AK/6eWgZ8Bw7AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Batch History&quot;
        title=&quot;&quot;
        src=&quot;/static/625a6ea08aab4f3cba9669a9e6ece443/8c557/BatchHistory.png&quot;
        srcset=&quot;/static/625a6ea08aab4f3cba9669a9e6ece443/4edbd/BatchHistory.png 175w,
/static/625a6ea08aab4f3cba9669a9e6ece443/13ae7/BatchHistory.png 350w,
/static/625a6ea08aab4f3cba9669a9e6ece443/8c557/BatchHistory.png 700w,
/static/625a6ea08aab4f3cba9669a9e6ece443/142fb/BatchHistory.png 907w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;In a lot of cases, you can&apos;t install an additional software on a SQL Server to query this data directly. So the easiest way to get the required data is to execute a query in SQL Management Studio and copy/paste its result into the local Excel file. Then this file can be used as a source data for our Power BI report.&lt;/p&gt;
&lt;p&gt;See below the sample query that I use for AX2012&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;sql&quot;&gt;&lt;pre class=&quot;language-sql&quot;&gt;&lt;code class=&quot;language-sql&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;DECLARE&lt;/span&gt;  &lt;span class=&quot;token variable&quot;&gt;@m&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;@m&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; DATEDIFF&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;mi&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;SYSUTCDATETIME&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; SYSDATETIME&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;SELECT&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;CASE&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;WHEN&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;BATCHHISTORY&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;STATUS&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;THEN&lt;/span&gt; N&lt;span class=&quot;token string&quot;&gt;&apos;Error&apos;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;WHEN&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;BATCHHISTORY&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;STATUS&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;THEN&lt;/span&gt; N&lt;span class=&quot;token string&quot;&gt;&apos;Finished&apos;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;WHEN&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;BATCHHISTORY&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;STATUS&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;THEN&lt;/span&gt; N&lt;span class=&quot;token string&quot;&gt;&apos;Canceled&apos;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;ELSE&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;CONVERT&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nvarchar&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;BATCHHISTORY&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;STATUS&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;END&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;STATUS&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;BATCHJOBHISTORY&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;CAPTION&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;BatchCaption&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;BATCHHISTORY&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;CAPTION&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;    &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;TaskCaption&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;BATCHHISTORY&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;BATCHJOBID&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;BATCHHISTORY&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;SERVERID
      &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;TOP&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Name&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;DynamicsAXProd_model&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;dbo&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;ModelElement&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt; axid &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;BATCHHISTORY&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;CLASSNUMBER &lt;span class=&quot;token operator&quot;&gt;and&lt;/span&gt; ElementType &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;45&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; ClassName
      &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;BATCHHISTORY&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;CLASSNUMBER
      &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;DATEADD&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;minute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;@m&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ORIGSTARTDATETIME&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;ORIGSTARTDATETIME&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;DATEADD&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;minute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;@m&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;BATCHHISTORY&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;STARTDATETIME&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;STARTDATETIME&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;DATEADD&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;minute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;@m&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;BATCHHISTORY&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;ENDDATETIME&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;ENDDATETIME&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;DATEDIFF&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ss&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;BATCHHISTORY&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;STARTDATETIME&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;BATCHHISTORY&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;enddatetime&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;DurationSec&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;BATCHHISTORY&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;COMPANY&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;ALERTSPROCESSED&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;BATCHCREATEDBY&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;CANCELEDBY&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;DATEDIFF&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;mi&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;BATCHJOBHISTORY&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ORIGSTARTDATETIME&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;BATCHJOBHISTORY&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;STARTDATETIME&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;StartDelayMin&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;dbo&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;BATCHJOBHISTORY&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;dbo&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;BATCHHISTORY&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;BATCHHISTORY&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;BATCHJOBHISTORYID &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;BATCHJOBHISTORY&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;RECID &lt;span class=&quot;token operator&quot;&gt;and&lt;/span&gt;
DATEADD&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;minute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;@m&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;BATCHJOBHISTORY&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;STARTDATETIME&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;CONVERT&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;datetime&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;2019-08-12&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;120&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You need to adjust STARTDATETIME filtering, limiting the number of rows to 100-200k(start with one previous week for example). For D365FO you can also create a data entity for it or just run this query for a PROD database copy.&lt;/p&gt;
&lt;h2 id=&quot;batch-analysis-reports&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#batch-analysis-reports&quot; aria-label=&quot;batch analysis reports permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Batch analysis reports&lt;/h2&gt;
&lt;p&gt;Let&apos;s see what kind of reports we can build from this dataset:&lt;/p&gt;
&lt;h3 id=&quot;--total-duration&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#--total-duration&quot; aria-label=&quot;  total duration permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;- Total duration&lt;/h3&gt;
&lt;p&gt;The first report we can build analysing &lt;strong&gt;Total duration of  batch tasks&lt;/strong&gt; from different measures&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/d0722b206a9c3c81f5c4a191d76c7e18/d6a46/Report1.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 61.142857142857146%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB90lEQVR42oVTyW4UMRD1V/ADfACfwZ9w4MIm+A0OKGcQEuIAl0iAiFgCCjkgGImgLB1As5HJTM9Mp9u9TnvpR5VnjDJNJKr1ZLvKfi7XqxZ1XcMYg6IsUVcVdqMpnp4O8Hw8xJNRHw9Pung86uHtbILteXghPhDeUPwokxDWWrCViwp5kuDWQQeXd17hyu4Wrn75iJv7HdzvHyPWCgkhVrUbk9aa46U1EJwdW7VYoJIpbhDBpfebeHTSQ02X2abBmv1n/ZdwQYSSMnzQDbA5HUE3y8yZ0Pqz7nyDZo2vTagNuI5FUWASn+FXKl3A0EaGP9C0CD1say1qpWA5S2PR0GisXbtda+3ijIZiRmm3zz2Vsz8357jQeY5ISgSk0M8iw48idQhyibCuHLEsC4RJjCjPEFMnxPSiSC0xp/mcxhmBBRKq38fG50+4tv8V9473cDv4hrvBHq4fdvCMWoft6HSEO69fUPsMyPcbW9QiO9EM39MEIXXHhDAmREQuNAnxbtBFRk9rF9nPu9MQL4NDHFDWvTJHZvQ/YnjFhRwOkY8nbgOLoKkOHr6eszRFveoGL/FSjPPfspSCg/yXSKojq82N3qzUdU1P4xnVWbEo7POqXpAh+9yfokhp7sOKCs7rki7IssxdwMZx9jPMitipv/Lx3L3QGPwB4wuU7MM5I0oAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Duration report&quot;
        title=&quot;&quot;
        src=&quot;/static/d0722b206a9c3c81f5c4a191d76c7e18/8c557/Report1.png&quot;
        srcset=&quot;/static/d0722b206a9c3c81f5c4a191d76c7e18/4edbd/Report1.png 175w,
/static/d0722b206a9c3c81f5c4a191d76c7e18/13ae7/Report1.png 350w,
/static/d0722b206a9c3c81f5c4a191d76c7e18/8c557/Report1.png 700w,
/static/d0722b206a9c3c81f5c4a191d76c7e18/d6a46/Report1.png 1008w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The first visual here displays &lt;strong&gt;Total duration by task name&lt;/strong&gt;, where we can find what are our longest tasks and then invest our time into optimizing top tasks from this list.&lt;/p&gt;
&lt;p&gt;The second visual displays how busy our batch servers were(&lt;strong&gt;Duration by ServerID&lt;/strong&gt;). In the example above we can see that the amount of work executed on AOS01 is way less than on AOS02, so maybe it is a good idea to relocate some tasks to it.&lt;/p&gt;
&lt;p&gt;And the third visual displays the number of batch tasks and their duration by company, so we can define our top companies.&lt;/p&gt;
&lt;h3 id=&quot;--delayed-batch-tasks&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#--delayed-batch-tasks&quot; aria-label=&quot;  delayed batch tasks permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;- Delayed batch tasks&lt;/h3&gt;
&lt;p&gt;There can be a situation where a batch task is scheduled for a particular time but was not executed on this time because there were not free threads available. We can calculate the delay as the differences between &lt;strong&gt;StartDateTime&lt;/strong&gt; and &lt;strong&gt;OrigStartDateTime&lt;/strong&gt; columns.&lt;/p&gt;
&lt;p&gt;One of the main parts of configuring a batch server is to specify a &quot;Maximum batch threads&quot; that it can handle. The situation where you have delayed tasks is not normal, on a properly configured system this should never happen.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;From practical experience: don&apos;t set this value too low. A modern 8-core server can handle 50-200 batch threads, so start with this interval.  There can be some specific batch jobs that mostly use AOS resources and no SQL work, only in this case it may be set lower. Check for % of AOS CPU usage.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/ab870f58a058ce94aaeda1b6b12a56af/5bb8b/BatchConfig.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 57.14285714285714%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB0klEQVR42oWTUa+jIBCF/f9/ax/27d6m7ab7sLdaba1WEBAVUOvZGdpN2uQmS3ICTIZvzoAmsrXoug7jOMDaEUIaGK3RNA00zW708G4kOXjvnuuHgnvfsxIpFR0aME8O6zoDuD+0LnEOBLmWF5zzE7LsiKoqUZZn5LQvKd5KAa3aKKMVks/NHj9/CeyKgE3q8PkVsE0DimYm3WGHACEEymuDayUg2y4acGMfIaqVVOSK6lqiMxqJ6Qb82Bt8HAlGoA8Cbo4Tfp8DDsUEYz2M6SDUAKl68BWNwxDF1zBPEyxdWW8tFaGWpymgvglcLiVOeYGqviE75VC6w0Kdex9i5aa5UUxBUott2+JGe+897vf7ixYCBo+ht7GCtY956PuoZZ6jAwZKgggpoZQioIzQltZsiEEz55KSmQL/XpVVVRW5kKjrml5+xLLMBGljjCF8b0I0sQDH2ATnzfMUFR2y9WVZ6JXX9xZozw4MOWypXUOHtTFoGK5NjEtyq8jQSvmshD8LhvFg4Kt4cBv11x+k2y2y/R7pbodst4WmbtbnGXD+d8DvxkTum8MBHX06mq5D32p4Wk+kp4u3/P8DQ4DMUuhzAVUUcdZ5jp5adcHB0d/xqr8fPkviZpEvKwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Batch config&quot;
        title=&quot;&quot;
        src=&quot;/static/ab870f58a058ce94aaeda1b6b12a56af/8c557/BatchConfig.png&quot;
        srcset=&quot;/static/ab870f58a058ce94aaeda1b6b12a56af/4edbd/BatchConfig.png 175w,
/static/ab870f58a058ce94aaeda1b6b12a56af/13ae7/BatchConfig.png 350w,
/static/ab870f58a058ce94aaeda1b6b12a56af/8c557/BatchConfig.png 700w,
/static/ab870f58a058ce94aaeda1b6b12a56af/5bb8b/BatchConfig.png 749w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The second report displays such delayed tasks.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/2072ee747b271bc0dbd955b52715aaa2/67a79/Report2.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 43.99999999999999%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABR0lEQVR42n1S7W6DMBDL+79gf00TrcSHoARKSAIBPDsTE5uqRbJy3F2cs4np+h4+RizrmuFDgB2GjF77OGJNKdfCpS9tG8618ts5h+M4YB6PB6y1mOcZnphZeL1eaNsWdV3B8kIdqOoaRVGgbprcK5wr8ULvfd5NWVXfZEwIikdOJdLAabUvy4KKfff7HQ0JlZeSc6n+fD4RqcCoaaS0K+E0TZn0jHUgEqfkndKuklV37N33HUY+BR1go6B4EhGh2Pk5S/5vJQ3SdQhUY941iCCEOUvLxJxMtwsyPoPxpp9DDGWJ4naDpS1vCdOaEF3IB/eT4EJ0sOdYIoaiROwHuKpEQ+sspzQyUt7p9p8JlxXtZ/Ob6A8hSNh9VAjjjOToM/+wnpeRoTJfv3yj0YLIAydUTiTalVMt56RCdpQNxrJG1FvV+4wRXzk+vGNcPvwcAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Delayed tasks report&quot;
        title=&quot;&quot;
        src=&quot;/static/2072ee747b271bc0dbd955b52715aaa2/8c557/Report2.png&quot;
        srcset=&quot;/static/2072ee747b271bc0dbd955b52715aaa2/4edbd/Report2.png 175w,
/static/2072ee747b271bc0dbd955b52715aaa2/13ae7/Report2.png 350w,
/static/2072ee747b271bc0dbd955b52715aaa2/8c557/Report2.png 700w,
/static/2072ee747b271bc0dbd955b52715aaa2/e996b/Report2.png 1050w,
/static/2072ee747b271bc0dbd955b52715aaa2/2cefc/Report2.png 1400w,
/static/2072ee747b271bc0dbd955b52715aaa2/67a79/Report2.png 1408w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;It allows identifying which tasks were delayed, on what server and at what time. In the example above we see that there were a lot of delayed tasks around 9 pm. It was a project case where we have found that &quot;Customer ageing report&quot; was incorrectly configured and that overloaded batch server with multiple tasks. If you see some custom jobs here maybe you need to review your batch &lt;a href=&quot;https://www.linkedin.com/pulse/batch-parallelism-d365-finance-operations-valentyn-lysenko/&quot;&gt;strategy&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;batch-tasks-schedule&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#batch-tasks-schedule&quot; aria-label=&quot;batch tasks schedule permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Batch tasks schedule&lt;/h3&gt;
&lt;p&gt;Another important part of AX performance analysis is analysing how batch tasks are scheduled during the day. Usually, it is not a problem if a large task is executed at night, but if it runs during the day it may affect users&apos; work.&lt;/p&gt;
&lt;p&gt;The third report displays how the top batch jobs were executed during the day.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/fb7308203fb2c8cc12641cc92f63f581/2e367/Report3.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 49.71428571428571%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABi0lEQVR42lVSy04CQRDczybRg0c/gpsYFUwEw2dwUB6Gx1miIbxkd2CeZXXvrsJsKt3T3dNT1TtZjBEhBDjnYE8nhN0Ongj7Pfxmg7DdIqzX8LQKxrzW7LVG67cEz6eUkGkza2GOR5wOB7jxGHY0gp18wL69w424H3LPuGPcTSbMTcr9bM7cUM94no/SEFzee1g2Fgb5Uxt5m+g8I394pN9B8dJViG/6fRTdXpljzeGuhYLWH36Q2CsTydJQJAtbWQm4sBeL9bLcbIbt1TUiVdWkAnOZMUY3J5kfrTZK6cJeXBKTxuXbNBqwg0F5Ace2ajaRaSMyswwoQ96SxBJiE+OJ7Os9Im11sem9ws8X6guZvHWPTNjJH1LJ9OVwlCZEFJ+SYlEQOdzXN5bTJcx6T0quvFAsa6WPjO//p9QMz+WJ5GpmcT7D580tFtMVZcdKfvwbizYkMn1/bFZLryWn2q8kK1ijMVFSoxpPqBnqgCsc5S0SkvTyNilVbGAz8c3R6HjOc8LK8oyclfULEXj+0YemUI8AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;BatchSchedule&quot;
        title=&quot;&quot;
        src=&quot;/static/fb7308203fb2c8cc12641cc92f63f581/8c557/Report3.png&quot;
        srcset=&quot;/static/fb7308203fb2c8cc12641cc92f63f581/4edbd/Report3.png 175w,
/static/fb7308203fb2c8cc12641cc92f63f581/13ae7/Report3.png 350w,
/static/fb7308203fb2c8cc12641cc92f63f581/8c557/Report3.png 700w,
/static/fb7308203fb2c8cc12641cc92f63f581/e996b/Report3.png 1050w,
/static/fb7308203fb2c8cc12641cc92f63f581/2e367/Report3.png 1066w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;We see that there are 2 big tasks executed after 7 pm and one big task executed around 1 pm. Then it is worth discussing whether we need it in the middle of the day and how we can optimize it.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#conclusion&quot; aria-label=&quot;conclusion permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;With the help of Power BI you can analyse 3 main points of Dynamics AX/ D365FO batch tasks performance: Longest tasks, Delayed tasks and Schedule during the day. I upload files used for this post to the following &lt;a href=&quot;https://github.com/TrudAX/TRUDScripts/tree/master/Performance/Jobs/PowerBI&quot;&gt;folder&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I hope you find this information useful. As always, if you see any improvements or suggestions, don&apos;t hesitate to contact me.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Comparing D365FO development VMs performance(VS2017)]]></title><description><![CDATA[Comparing the performance of 4 D365FO development VM configurations with Visual studio]]></description><link>https://denistrunin.com/devvm-perfv13/</link><guid isPermaLink="false">https://denistrunin.com/devvm-perfv13/</guid><pubDate>Wed, 21 Oct 2020 20:12:03 GMT</pubDate><content:encoded>&lt;p&gt;Starting from PU37 Microsoft has changed Dynamics 365 Finance and Operation development environment from Visual Studio 2015 to VS2017. This post is an updated version of my &lt;a href=&quot;https://denistrunin.com/devvm-perfv10/&quot;&gt;previous one for VS2015&lt;/a&gt;, where I try to compare the performance of 4 development configurations with the new VS2017 version.&lt;/p&gt;
&lt;p&gt;I have chosen the following VMs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Local Hyper-V Image&lt;/li&gt;
&lt;li&gt;Standard VM based on 3 HDD disks - this is a default Development setting in LCS&lt;/li&gt;
&lt;li&gt;Azure VM based on Premium SSD disks&lt;/li&gt;
&lt;li&gt;Azure VM based on 15 HDD disks - changed via LCS Advanced settings&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Detail specifications of these VMs:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Local&lt;/th&gt;
&lt;th&gt;SSD&lt;/th&gt;
&lt;th&gt;HDD15&lt;/th&gt;
&lt;th&gt;HDD3&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;VM Type&lt;/td&gt;
&lt;td&gt;Local Hyper-V Image&lt;/td&gt;
&lt;td&gt;Standard D8s v3&lt;/td&gt;
&lt;td&gt;Standard D12 v2&lt;/td&gt;
&lt;td&gt;Standard D12 v2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CPU&lt;/td&gt;
&lt;td&gt;Core i7-8700 3.2GHz, 6 cores, 24 GiB memory&lt;/td&gt;
&lt;td&gt;Xeon Platinum 8171M 2.10GHz, 8 vcpus, 32 GiB memory&lt;/td&gt;
&lt;td&gt;Xeon Platinum 8272CL, 2.60GHz, 4 vcpus, 28 GiB memory&lt;/td&gt;
&lt;td&gt;Xeon Platinum 8171M 2.10GHz, 4 vcpus, 28 GiB memory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage&lt;/td&gt;
&lt;td&gt;Samsung 970(more than 100k IOPS)&lt;/td&gt;
&lt;td&gt;3 premium disks 512GB (2300 IOPS) + build&lt;/td&gt;
&lt;td&gt;15 HDD disks 32GB (500 IOPS)+ build&lt;/td&gt;
&lt;td&gt;3 HDD disks 512GB (500 IOPS)+ build&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Run cost&lt;/td&gt;
&lt;td&gt;Box for run 3 VMs - around 1.5k$&lt;/td&gt;
&lt;td&gt;0.75$ per hour&lt;/td&gt;
&lt;td&gt;0.52$ per hour&lt;/td&gt;
&lt;td&gt;0.52$ per hour&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage cost (monthly)&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;219 USD&lt;/td&gt;
&lt;td&gt;24 USD&lt;/td&gt;
&lt;td&gt;65 USD&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;One thing to note: in Azure the &lt;a href=&quot;https://docs.microsoft.com/en-us/azure/virtual-machines/disks-types#disk-size-1&quot;&gt;performance of SSD disks&lt;/a&gt; depends on the disk size and it is different from HDD disk performance that is always 500 IOPS.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 534px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/c23fa421323ee35ccd9584b069696b25/a07a7/DiskSpeedSSD.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 74.28571428571428%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABV0lEQVR42pVUCY6DMAzk/79ctUC4E85wup60oRyWdjeSBWTiyYzjECgVU5ompLWmaZponuc/BdZu20bXEaRJQmEYUszETdPsi3+Luq5pWRZHAmJPHrRtS7Ux7mNd1xPY9z1FUeSSjziGtQOpOKaEBSmleM2bI7DDQIbtEhaegmi0lhOtIzphPMZxpLZtWOW7BH6zAIBXcB2w5m1JGDa71RCTRVGIBR5YPRKlASEoyY0QCWVZOtm+ft862Z3wih0Jj5gjNHwokjUkYaN/WYatLMtEhVDgkyQMHXJXyCpwylBz7Sn7OWWJEEJEyyDK81yUD0ya/7ZNe7dcG01xFBKeIzerHXoXeDe6Il2Vp3mPNdzIGV/Z4zwiKLKUno8fyhJFhpN1WbjAe5rwPVfRaX7H+KpGz8cNY8uTsyw1N2rUdZ1oGVhVVXJjg1Cqx8AW+l4mRJ75/AOOhC+fd5gqj3M5kgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;DiskSpeedSSD&quot;
        title=&quot;&quot;
        src=&quot;/static/c23fa421323ee35ccd9584b069696b25/a07a7/DiskSpeedSSD.png&quot;
        srcset=&quot;/static/c23fa421323ee35ccd9584b069696b25/4edbd/DiskSpeedSSD.png 175w,
/static/c23fa421323ee35ccd9584b069696b25/13ae7/DiskSpeedSSD.png 350w,
/static/c23fa421323ee35ccd9584b069696b25/a07a7/DiskSpeedSSD.png 534w&quot;
        sizes=&quot;(max-width: 534px) 100vw, 534px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;That means that in Azure world SSD disk is not always better than HDD. It is also tricky to do any tests with an SSD because they have &lt;a href=&quot;https://docs.microsoft.com/en-us/azure/virtual-machines/linux/disk-bursting&quot;&gt;disk bursting&lt;/a&gt; that can temporaly increase disk IOPS to 3500 up to 30 minutes.
I did some testing with 16HDDs(500 IOPS) and 3 SSDs 512GB, 2300IOPS max( + Build 26GB ) and got the following results: for 16HDD you will get 8000 stable IOPS, for 3 SSD you get 7100 stable IOPS and Bursting can temporarily add 3500 IOPS.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/9bb4f0b73e7e9e58bbaf8f898131cca7/d125e/IOPSTesting.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 93.14285714285714%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAElklEQVR42mVUa28bVRDdv8UvQfnCVyTEo62gVFCgagGHolBS2ipS09JCmrZO7NbETpM4jt+b+LV+Zf3eh+211xvba2/i93p9uHFbKGKk0Wjn6p6dmXvOUKIio1FvQ6opqCtNVGsNVCQZWn+IXqOJsaxgVK1jQPJjA1C1M3SIDwZDqKqKdltFv9+fgth0Ol2gCvUcopwfUqOCpqLg5ESBpmmo12qo8jzacg1aU8Gk38PpmYZKWUQsFiUeQzBI4y/bS7y02aaj0fgcc4HaEu9hOf4B5NMCTltDpFIsMmwGCgEeDEfQOn3kshzyhRKKhQIEnkM4FEIymUSExL29PYiC+G+FW/n7WAlfxLZ0Fy/qP+G25xLuPDMhncggmHTDWl/EWv4arj74EFs7NhTyBew49xGORnEUJoD7+2CSyalQqUAQhAXKXlzFvdBFOGrLsDZu4A/2azjodbCJLAJJFzZq12BTTHiVfASP3wOBZbH1+DFc5uegHXbsPn2KkMMxPdreBuPzLVAObhX345/DLi3DQgDN3A24fHvIpguIZAN4Ln0HR+sXHBdj8HkCyLJp+FwHoL1eiKUitqwWHPq801pVej1DW3YFt4OfzAEfVS6Abj8HE40j4AvCF9vDE+kKqfwH8FIekXAEbIbFYKxDn04xnkzmsT8YzGc4Pp+hrbCi3z78SLdWbuqJrl1XJ1W9ITf0w8CR7oo59N3mPb0+ZPXe4FTPHB/rNE3rqtbTyf13fYTX9j4V7drhVO4iMl5H16jNs+PJCKU8jwR3iJzhwluT5To4jiMVTvGuzWazt4kF6kwbfw8Di7oGU/+sb1I7LRPhoYkcvvaucbOnyLf63e4SYfDP/+T/6z8SX5pMJu9RvCTZT8pqgy8IXKVSJq9fFcq8KJxqmtBstYSJVBUJOcuIx8uoVsVBvy+k0ikhmUgIbCYjhMNhYdvhEIRymSc87FBsKxIPtjbBd1PGqD9B86SJ0WgEtd1Gm0hLbXegSnUYZz0itTZRUhMEDKHQESF7ETQdhMfjQV2W5z1T3pqZecR/hpBkNRRVBp3ww+Nzo8Tx6HRUNDp1xIsM/OEASDWoEAIHaBr7By7EUylsWixIkGjMZudKAeUubzIPEl9io2gy1huXsVr6GKuORcRjabi8e3ghm7B2cgnL7k8JiBNsOo2A+wD7hMhepxOHHi+i5Ac7L6ywW63ngBbmz9xVvOR+NWyNRTwpXcXa7h1yMQ8/7YG99hssynWseL6C1+9GhgAebG7A9vtDbK+twUOI7TRvIEo03SpxoA5EM/MwTcjLLRmb9eswV6/DEXyK42QWh6RNe30ZZvkbWFLLpOUjsER6x7kcyLshk8+jQGjEku98sYiJrhNAfpNZZS7DWrhlrNeuwNFcQow5Qigcgzfgxiv5Lp7IXyAs7CJMk4VAHuN8Z77h37tkxMwwQO2Lz5iV+AWs5b41hD4zP9M0FV6vH9u7DlhqP4DrReZ5QeThIRou8uX/A74xKt+OMtmBE6nOjtEeSpgRIfV6ZxBFERxfAtsjsxlWYZB8Q2kQKlahtDp4s/9gkKrO41vwvwHN0h8CT9yhfAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;IOPSTesting&quot;
        title=&quot;&quot;
        src=&quot;/static/9bb4f0b73e7e9e58bbaf8f898131cca7/8c557/IOPSTesting.png&quot;
        srcset=&quot;/static/9bb4f0b73e7e9e58bbaf8f898131cca7/4edbd/IOPSTesting.png 175w,
/static/9bb4f0b73e7e9e58bbaf8f898131cca7/13ae7/IOPSTesting.png 350w,
/static/9bb4f0b73e7e9e58bbaf8f898131cca7/8c557/IOPSTesting.png 700w,
/static/9bb4f0b73e7e9e58bbaf8f898131cca7/d125e/IOPSTesting.png 737w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;system-version-and-initial-setup&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#system-version-and-initial-setup&quot; aria-label=&quot;system version and initial setup permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;System version and initial setup&lt;/h2&gt;
&lt;p&gt;Both 4 VMs have used the same D365FO version: &quot;Finance and Operations - Develop (10.0.13 with Platform update 37)&quot;. After installation I disabled the following services:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Microsoft Dynamics 365 Unified Operations: Batch Management Service&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Microsoft Dynamics 365 Unified Operations: Data Import Export Framework Service&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Management Reporter 2012 Process Service&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;and added D365 Defender Rules:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;powershell&quot;&gt;&lt;pre class=&quot;language-powershell&quot;&gt;&lt;code class=&quot;language-powershell&quot;&gt;&lt;span class=&quot;token function&quot;&gt;Install-Module&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;Name d365fo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;tools
Add-D365WindowsDefenderRules&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;overall-system-performance-tests&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#overall-system-performance-tests&quot; aria-label=&quot;overall system performance tests permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Overall system performance tests&lt;/h2&gt;
&lt;p&gt;First, let&apos;s compare overall system performance by running a full compile and full DB sync. They are not frequent operations for Dev machines, but they are very resource-intensive and it allows us to find out VMs overall capacity.&lt;/p&gt;
&lt;p&gt;For the compile task I got the following results:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 374px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/26ff2413b777ab2aae4703c623f36f6b/52dba/FullCompileTime.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 64.57142857142857%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB/UlEQVR42pWTz0/UQBTHBz1ovCM3Nd68EU/Kv8Af4dWD0RhPJkZPXPgHjCb+iD8iRlZYXX5kwQXF6B4EBJeVRTFsVlkhCO22205n2n59M22BrZBgk09n3rzOt2/evMccx4FLCM+DVHAPgnNIIRCGIf73YcnECwLwMMINEnyN40vCb7GTeWL7tE8LqujMpo3uT1Nof5PFqbdDODGZ05w8AKfp+47CK+TXfkWCHh3P8TguzBfR+WEUXcVxnCuOpcjvsRbRRZx5P4qJ9XokqPLEKXeFVRsvVkwMVBt4mSJD63vZmZUGcjULDS5BCYfKOAsoV006drZq4e6igQdLJu4fkHsVE3cqW6hbLgnGOQxJUBK9y4u4WJrGlfIsLqdZmGmxr5Y/49rXOVxamMW0samFgrgiWNO2YRLnP46DjTzHsbEMjub79+UI0Tbch8MjfWCvH+NZ7YcWkomgevlk3K5+x/XKPG59K+FmmqUverxBY89yGTMUVckyMdcwYEihhZKaZaqA/5gmzr4bBht8iEO5p/TnJ//QpsbsIxynCDdtKxKJa1iJhbsjVOcvbKyhv17D4O+fGNiHDPmH1lfBqcjVHhnfLNKC6mIC6W+3T0gbQiF2bCk1211FZSZ2+blq1djPkpAFtZCgq1d4NPf8Vlt104axpXFdt6V/VeklEf4F9OeIHRtMvSwAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Full compile time&quot;
        title=&quot;&quot;
        src=&quot;/static/26ff2413b777ab2aae4703c623f36f6b/52dba/FullCompileTime.png&quot;
        srcset=&quot;/static/26ff2413b777ab2aae4703c623f36f6b/4edbd/FullCompileTime.png 175w,
/static/26ff2413b777ab2aae4703c623f36f6b/13ae7/FullCompileTime.png 350w,
/static/26ff2413b777ab2aae4703c623f36f6b/52dba/FullCompileTime.png 374w&quot;
        sizes=&quot;(max-width: 374px) 100vw, 374px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The compile times are longer than in previous test with VS2015 and 10.0 version.&lt;/p&gt;
&lt;p&gt;Next test is a database synchronize:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 408px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/6218010c3ba45c3e71c9c7bbe983c270/e7c18/FullSyncTime.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 42.857142857142854%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABaklEQVR42qWRzy4DURTG+xqeAJFY2QiWdjbEQ9hJhAewwEawE3tPQKKaqknaShGhqtWpSkTapp3qTGeoztz5cz/nTrWmISFxkt+d892597s554RM04RrO4DjAi7xzwgJk9ybgUijBkmtI0bfU1Xp8asmJK0Ow2YA52TYNrEipzEgHWAkeYyhRPjPDBOD8SOMnkVwqzWoQo8MLYbVxyyZhTF5EcP4eZQ4+ZEJQpwJMpaKYupSgqxr1DYHIaf9jmhVx06hir2igt1ijVACfOlNuYL1fAkbxNp9CVuFMlIvCrKvTZjUOu6JkhnD/nMFC+l7LGcfsHQnE4UAHb2YkXFYVpFTLWQ0hozKkG8ymqXXGwj3e8hsbD/lMX0lYT6dxOxN4htzxMx1HCkaiOhTwAIu79AzFItLtXfDowv884CIvn+eB5s0963g52Kva2ZZVsfQ4+JV7uNS7ga0uKQbBjS9iVar1feYyINamH8A+ct485ubM/oAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Full Sync time&quot;
        title=&quot;&quot;
        src=&quot;/static/6218010c3ba45c3e71c9c7bbe983c270/e7c18/FullSyncTime.png&quot;
        srcset=&quot;/static/6218010c3ba45c3e71c9c7bbe983c270/4edbd/FullSyncTime.png 175w,
/static/6218010c3ba45c3e71c9c7bbe983c270/13ae7/FullSyncTime.png 350w,
/static/6218010c3ba45c3e71c9c7bbe983c270/e7c18/FullSyncTime.png 408w&quot;
        sizes=&quot;(max-width: 408px) 100vw, 408px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Synchronize operation is an IO and CPU-intensive task. Local VM has a more powerful IO system, and a more powerful CPU, that explains a better result. SSD VM performed better compared to HDD in this test due to faster disks. And again for all VMs there is ~30% performance decrease compared to VS2015.&lt;/p&gt;
&lt;h2 id=&quot;daily-task-tests&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#daily-task-tests&quot; aria-label=&quot;daily task tests permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Daily task tests&lt;/h2&gt;
&lt;p&gt;To test performance for more frequent developer tasks I chose 2 tasks: time to hit breakpoint and time to display &apos;Hello world&apos; message from the job. In AX2012 both these tasks have a near-zero execution time, so you don&apos;t need to wait.&lt;/p&gt;
&lt;h3 id=&quot;time-to-hit-breakpoint-test&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#time-to-hit-breakpoint-test&quot; aria-label=&quot;time to hit breakpoint test permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Time to hit breakpoint test&lt;/h3&gt;
&lt;p&gt;Before the test I opened the D365FO main screen, to warm up the system cache.&lt;/p&gt;
&lt;p&gt;To prepare for this test I switched off &apos;Load symbols for items in the solution&apos;. Then I opened AOT, searched for a &lt;strong&gt;SalesTable&lt;/strong&gt; form and added it into the new project and marked the form as a startup object. After that I opened the code and added a new breakpoint to the &lt;strong&gt;init()&lt;/strong&gt; method.&lt;/p&gt;
&lt;p&gt;Time in this test is the time between I pressed &lt;strong&gt;Start&lt;/strong&gt; and the time when the breakpoint was hit.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/f1e913952f6a2cd0101033934b9738c7/c1eae/HitTheBreakpoint.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 30.28571428571429%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAGABQDASIAAhEBAxEB/8QAFwABAAMAAAAAAAAAAAAAAAAAAAECBf/EABUBAQEAAAAAAAAAAAAAAAAAAAAB/9oADAMBAAIQAxAAAAHVsJIX/8QAFxAAAwEAAAAAAAAAAAAAAAAAAAISAf/aAAgBAQABBQJVIwg//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAFxAAAwEAAAAAAAAAAAAAAAAAAAExkf/aAAgBAQAGPwJWFelen//EABoQAAICAwAAAAAAAAAAAAAAAAERABAhMVH/2gAIAQEAAT8hEieXUKjtp3//2gAMAwEAAgADAAAAEP8A7//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8QP//EABURAQEAAAAAAAAAAAAAAAAAAAAR/9oACAECAQE/EKr/xAAaEAEAAgMBAAAAAAAAAAAAAAABABEhMYGR/9oACAEBAAE/EFuRBbe6GXr0IOs8HP/Z&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Breakpoint image&quot;
        title=&quot;&quot;
        src=&quot;/static/f1e913952f6a2cd0101033934b9738c7/29d31/HitTheBreakpoint.jpg&quot;
        srcset=&quot;/static/f1e913952f6a2cd0101033934b9738c7/e52aa/HitTheBreakpoint.jpg 175w,
/static/f1e913952f6a2cd0101033934b9738c7/70ebb/HitTheBreakpoint.jpg 350w,
/static/f1e913952f6a2cd0101033934b9738c7/29d31/HitTheBreakpoint.jpg 700w,
/static/f1e913952f6a2cd0101033934b9738c7/c1eae/HitTheBreakpoint.jpg 949w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;For HDD03 VM this test initially failed(I got a Timeout message).&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/9c0bceee3feaf493246221695f70fcd8/62da8/VSTimeout.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 45.142857142857146%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABo0lEQVR42n1RyW7bMBDV/x/yAWmRoPVeG0luRa499dBjWjRBYbuQpUjUQpGyxEXL65CwC7coOsADh9ubN2+CyXKG6foDlg/3eLda4HY+wc1igZvlivYrvJlMcT2ZYbZZYP4PTNdzvJ0Tx2aNW/oTZBmHHQDRaPCqBucSdWugtIVWGtb2GOh+6IG+Hwnw+3GED6U7fP7yHU9ft3j6tiPCooSlh1UlUNc1WqVw7Hoc3Xo8om1baK1gjPbQdN471lMYY7Hdh9jvd4iiGAHLOWTBSVnlVSllPIztYIm4odyTUhtKG084OImnsNbiEKc+H0l2wEqBLonAwhBx/Io8y1FLeVJm0A2jf+jgiMZzr2dCUhhGF4QpKyBaBS4EpKxRcu7bz8nLHyFDKRr8L5zCMEp8PlDxoKB2SxrIIc2RpCmeX14Qv6ZoqEhCxIwKVUJCeghSrf9smRQeLhXmZUXGGmRZhqLISaX8/cHS6mD6zhM5KPKwuxiKU7jdhTTQBj8PjAgTRsa3YBm1V5ZEWpB/yss/e/eXbRfno5/4w8dPeL95xNX1HX4Bee6kDu3dd0EAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;VSTimeout&quot;
        title=&quot;&quot;
        src=&quot;/static/9c0bceee3feaf493246221695f70fcd8/8c557/VSTimeout.png&quot;
        srcset=&quot;/static/9c0bceee3feaf493246221695f70fcd8/4edbd/VSTimeout.png 175w,
/static/9c0bceee3feaf493246221695f70fcd8/13ae7/VSTimeout.png 350w,
/static/9c0bceee3feaf493246221695f70fcd8/8c557/VSTimeout.png 700w,
/static/9c0bceee3feaf493246221695f70fcd8/e996b/VSTimeout.png 1050w,
/static/9c0bceee3feaf493246221695f70fcd8/62da8/VSTimeout.png 1262w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Two tests were performed to see how the cache would change this time.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 560px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/6a80beae8bbe57f8a0e6eaf6a966c57c/b06ae/TimeToHitBreakpoint.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 50.28571428571429%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABR0lEQVR42qWSa0/CMBSG+f//Qz96Ay8fUCPeuAQWxhCRQeYCQS6KuzDKuvb1dFMzQBOJTZ425/T0Td/2ZBhjCOYBfGJOiEhACvkrruMi4hEgsLonEzJKkPkBGBWxiEMIqvzHyJAuxoNX3B1W0DiponlaQ4MwUqh8/ahClDfJlqHtF/F0ZWCxWJCgiGCRYC7/gG6pDbvW26CvW3BGM3hTh3A3cCcO5u8+PVeUCNr9KfZyGqrnOjoFA+ZNK+G2RXET7UsDjC2h3Kjxtf5oWU19umH2WEP9Qo+FOtctspAIWRUTIQ///oZqsocznOWb6BUfY4GB8Yxxd4iJOcSbPQEP+TaCEpY1xs7uPQr0MfpBCaPuCz69bf/L1Dzwlhymz+Go/iIVIVeV5FqsWiudS7dabFmqRKqAc75yIAgCeJ4Xr+rw+n4Yht/xB2KR+cpNoRlhAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;TimeToHitBreakpoint results&quot;
        title=&quot;&quot;
        src=&quot;/static/6a80beae8bbe57f8a0e6eaf6a966c57c/b06ae/TimeToHitBreakpoint.png&quot;
        srcset=&quot;/static/6a80beae8bbe57f8a0e6eaf6a966c57c/4edbd/TimeToHitBreakpoint.png 175w,
/static/6a80beae8bbe57f8a0e6eaf6a966c57c/13ae7/TimeToHitBreakpoint.png 350w,
/static/6a80beae8bbe57f8a0e6eaf6a966c57c/b06ae/TimeToHitBreakpoint.png 560w&quot;
        sizes=&quot;(max-width: 560px) 100vw, 560px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The result probably depends on IO speed.&lt;/p&gt;
&lt;h3 id=&quot;hello-world-test&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#hello-world-test&quot; aria-label=&quot;hello world test permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Hello world test&lt;/h3&gt;
&lt;p&gt;This test was performed straight after the breakpoint test, but I restarted Visual Studio. In this test, I created a new project and added a Runnable class with the following code&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token function&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Hello world&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;On the second run, I changed this text to &quot;Hello world2&quot;. On the Third run I didn&apos;t change the text, just ran the same job.&lt;/p&gt;
&lt;p&gt;I measured the time between pressing Start and the time when the message displayed in the browser.&lt;/p&gt;
&lt;p&gt;Here are the results:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 563px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/f409b4aaca20cffc1849c87dfa997d3b/7cb89/HelloWorldTest.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 48.57142857142858%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABuUlEQVR42n2SXXPSQBSG+d1eO97pv/DaG61WSmtTbAsIBIoktDQhyIe1oAmkId+PZ0N1ygzTnTxzdmd33zl53y0FQcDKW+P6AZ7v48o6zTKyPN8le7oG+faO0iYMSUQsixMimXvBA3masL2yj+dHiTyjaU54e9iiohmcVwecnSlMNM0squL0uIc+/Im1Dhn5MX4Uy9WsEMnz/IlglvLZsHnxqcr7C4NOe0S7M0YX2rpT1E7HoXZucP1jwdQPmT+IYBjJ1XSPoPzex77Nq3KDSu2G6jebr63RlqZNVarWdDiu23SdJVEUKoUdkV1B8aXct3h9WEe7GFCvWzREVFFvWDRF1NYtpj2HSddh3LJwFM1bvF+uBJTtWFsIHgxs3mhtur0Jen9G5xH9+5QrY8Z8OGNh37F07vk9XhSouXf3B3+5LtisgqLTklL90L7h5bsqB0dXVE4MKl/MLacm5ROTy6rJ7aXJWLpSHY4fOyxoDLFq18yNCeFmo1KGnr/iyF3iJjGBJCcuFQTy4DZSk61RO8/jGQ/5H78aaRyDWsuhRM2lxlGE53qsV2tJNpMcU9lLCu9U0mr/n49/AbtA7YPTnvn2AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Test&quot;
        title=&quot;&quot;
        src=&quot;/static/f409b4aaca20cffc1849c87dfa997d3b/7cb89/HelloWorldTest.png&quot;
        srcset=&quot;/static/f409b4aaca20cffc1849c87dfa997d3b/4edbd/HelloWorldTest.png 175w,
/static/f409b4aaca20cffc1849c87dfa997d3b/13ae7/HelloWorldTest.png 350w,
/static/f409b4aaca20cffc1849c87dfa997d3b/7cb89/HelloWorldTest.png 563w&quot;
        sizes=&quot;(max-width: 563px) 100vw, 563px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The problem is that for HDD based machines the test failed in the first attempt, Visual studio just hung. The solution was to kill the process and restart it again(that explained that HDD &quot;First times&quot; are better)&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/2da7a279b78dbbd65c97d7cc909ab858/e8d6f/HandWhenRunJob.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 64%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABuElEQVR42q2SCU/bQBCF/f//RKVKlVoVqUgpFSQlpmpDIGDiKwc+YscOqaqm4CRrE5+PWQcMSBBA6kif/Ha8+3Y0s8Ju8wj7bQW7ByeoN4/REDtocE1fztf6L2zviPi2f4g98fgR9QP+v4V3H/ewtfMTH76IEBhjCOJ/CFMGoEBWpERMqsBrIoquMRjacN0RJhc+hMtgjtn8Cn+DS8yCGekZFtEcbMUQpwmyPH+SNMtLw6tgCb3PzabwJ1MIwWKJNM2wiiIkSYLiQWEFLZ4jz9cb5wsG15uWOqeLhGUYVYffEnfbF8sQrv+78hDYfzQsK9xkyFNJVrxoOPZeWWFOORZnGw0Zi9A+VSH3DNQaR9RDFlblbhrCU/CI4wSfa018qol4v/UdQhheP7rxrbFaJXBup8xDULUOPUodrqOVeF4PvteHQznLUmDbCkYjrcS55W7tOjqGQwnO2F8XxYfSav+AKregq4R2CPP8BI4twzJlKEobut6BaakwDLnCNDlKyWAg0Tu8uB+K1NVw1tXROVVwJpGWqMFyD3K3D7U7gKYO0aeGG9aYjNfYtg/T9ogxzg0X3uRPZXgDWk7WdFeBJ+UAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;HandWhenRunJob&quot;
        title=&quot;&quot;
        src=&quot;/static/2da7a279b78dbbd65c97d7cc909ab858/8c557/HandWhenRunJob.png&quot;
        srcset=&quot;/static/2da7a279b78dbbd65c97d7cc909ab858/4edbd/HandWhenRunJob.png 175w,
/static/2da7a279b78dbbd65c97d7cc909ab858/13ae7/HandWhenRunJob.png 350w,
/static/2da7a279b78dbbd65c97d7cc909ab858/8c557/HandWhenRunJob.png 700w,
/static/2da7a279b78dbbd65c97d7cc909ab858/e996b/HandWhenRunJob.png 1050w,
/static/2da7a279b78dbbd65c97d7cc909ab858/e8d6f/HandWhenRunJob.png 1273w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;update-10037-local&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#update-10037-local&quot; aria-label=&quot;update 10037 local permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Update 10.0.37 local&lt;/h2&gt;
&lt;p&gt;Recently I made an upgrade for my local PC and tested the performance of the local 10.0.37 VM with VS2022.
I upgraded to a Ryzen 7 7700X CPU(not the fastest, but close to the top CPU &lt;a href=&quot;https://www.cpubenchmark.net/singleThread.html&quot;&gt;https://www.cpubenchmark.net/singleThread.html&lt;/a&gt;), and a Samsung 990PRO SSD(more than 1 million IOPS). The results are the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Full sync for the database: around 3 minutes&lt;/li&gt;
&lt;li&gt;Recompile the project: almost instant (1.5 seconds)&lt;/li&gt;
&lt;li&gt;Refresh the simple form (like CustGroup) after recompile: 25 seconds&lt;/li&gt;
&lt;li&gt;Refresh the complex form (SalesTable) after recompile: 35 seconds&lt;/li&gt;
&lt;li&gt;Put a breakpoint to SalesTable.init and attach to process: almost instant (2-3 seconds)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Local VMs may not be the most convenient options, but if you write a lot of X++ code(with change/test/fix cycles), they are worth considering.&lt;/p&gt;
&lt;p&gt;To increase response time even more, enable Preload feature &lt;a href=&quot;https://abhimantiwari.github.io/blog/Application-Initialization/&quot;&gt;https://abhimantiwari.github.io/blog/Application-Initialization/&lt;/a&gt; (thanks &lt;strong&gt;Huber Gomez Hernandez&lt;/strong&gt; for this advice)&lt;/p&gt;
&lt;h3 id=&quot;update-2024-10-17&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#update-2024-10-17&quot; aria-label=&quot;update 2024 10 17 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Update 2024-10-17&lt;/h3&gt;
&lt;p&gt;Make sure you disable the &quot;Build metadata cache when AOS starts&quot; parameter in the  &lt;strong&gt;System parameters&lt;/strong&gt; form(System administrator → Setup → System parameters)&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.linkedin.com/pulse/boost-your-x-development-vm-performance-2x-denis-trunin-krowc/&quot;&gt;https://www.linkedin.com/pulse/boost-your-x-development-vm-performance-2x-denis-trunin-krowc/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Enabling disk cache also adds some improvements. With Read it takes about 60 seconds to refresh the browser after rebuild&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/3fda1f0e97f0037e12813e26de14b70f/93582/DiskCache.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 46.857142857142854%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABUklEQVR42oWS604FIQyE9/3fUP+pidFz4bKw3Nlx2rMbjYmRhNBA+ZhpWS53gy1GtNaQSkWqHTLmnKi16rrL3PdHfKxjDL0jQ/ZSSui9Y/m4XLFtGyKh99sNYfXIadNkSfx3/MpZLuYB2PhCkjUXrDGj9YHVe1Up8FOxPJJzRhU3vCPAxDzZG8xZzLoSmBRYC2Fl4M1W5DbhrEUIUWE/gWKtMba8O+nq+vzE2FNMxfJpPQYTxHatBYmgS2gofdL+qirOugnoEQ+NpUw7wd45eO+Qa8PiaK/3poeNQJ8nXkzFVieMuWMldP+l8GyIMUbrZq2Bc2xuIdDTf6HVEILaEIXXQ2GMAYm1OS1/K5yHwqBAYUh5VKFxD2Ck5VIyVip8NYUKB+yhcP6h0B4KHS07Z/ntCLz5qM2QpDE6Apvy7psqlS5v7PwJPL/SCZRzVahAp8AvE96+CX3swSYAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;DiskCache&quot;
        title=&quot;&quot;
        src=&quot;/static/3fda1f0e97f0037e12813e26de14b70f/8c557/DiskCache.png&quot;
        srcset=&quot;/static/3fda1f0e97f0037e12813e26de14b70f/4edbd/DiskCache.png 175w,
/static/3fda1f0e97f0037e12813e26de14b70f/13ae7/DiskCache.png 350w,
/static/3fda1f0e97f0037e12813e26de14b70f/8c557/DiskCache.png 700w,
/static/3fda1f0e97f0037e12813e26de14b70f/e996b/DiskCache.png 1050w,
/static/3fda1f0e97f0037e12813e26de14b70f/2cefc/DiskCache.png 1400w,
/static/3fda1f0e97f0037e12813e26de14b70f/93582/DiskCache.png 1524w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#conclusion&quot; aria-label=&quot;conclusion permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Let&apos;s summarize the current recommendations based on these tests for Visual Studio 2017 D365FO development environment and what to do if it is slow:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;If you want maximum performance and can buy a new hardware(and now you can buy a PC that has 10-20% more &lt;a href=&quot;https://www.cpubenchmark.net/singleThread.html&quot;&gt;speed&lt;/a&gt; than mine), Local VM is the best choice, but this VM is hard to manage.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Standard Development Environment from LCS(with the default of 3 HHD disks) is the slowest and constantly hangs. If you can control the Environment creation, never use it and always change the number of disks(15 32GB HDD are cheaper and faster).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;HDD15 VM with ..V5 CPUs is the best choice in terms of price/performance. It is a little bit slower than SSD based VM, but the storage price(that should be paid even if VM is deallocated) is almost 10 times cheaper(24 vs 220 USD)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I will also try to repeat the same tests after the next D365FO release, it will be interesting to compare the progress in this area. Any comments are welcome.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[How to manage a Dynamics AX performance optimization project]]></title><description><![CDATA[The blog post describes how to organize a Dynamics AX performance optimization project, who should be involved, and how the process should be organized]]></description><link>https://denistrunin.com/performance-projmanage/</link><guid isPermaLink="false">https://denistrunin.com/performance-projmanage/</guid><pubDate>Wed, 07 Oct 2020 22:12:03 GMT</pubDate><content:encoded>&lt;p&gt;Your Dynamics AX system(AX2009/AX2012 or Dynamics 365 for Finance and Operations) is slow, the users are complaining about performance and it is not clear what to do to fix that. The solution is to start a performance optimization project. How to organize this project, who should be involved, and how the process should be managed is explained in this blog post.&lt;/p&gt;
&lt;p&gt;We recently finished quite a successful performance optimization project and I will use it as an example for this post. The similar approach described here was used on dozens of different AX2009/AX2012 projects. I also describe common mistakes to avoid.&lt;/p&gt;
&lt;h2 id=&quot;project-overview&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#project-overview&quot; aria-label=&quot;project overview permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Project overview&lt;/h2&gt;
&lt;p&gt;The client was a big retail company running AX2009 for about 10 years with 80 users and 1TB database size. With the COVID-19 situation, they saw an increase in their sales and the performance of Dynamics AX, that had been average before this, became critical.&lt;/p&gt;
&lt;p&gt;As a final result, they saw a great improvement in AX performance.&lt;/p&gt;
&lt;p&gt;System stability was greatly improved, here are some measurable results:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 559px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/30a1feb7d28ce33767485677acfbeb21/a65ce/PerfResults.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 17.71428571428571%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAYAAACOXx+WAAAACXBIWXMAAAsTAAALEwEAmpwYAAABD0lEQVR42iWMXUvCYACF96u6iCjoqsuyLOjXBHUhFIQa/QavTeemt0ET5jbnfN99qCwTYkHp1PDy6dUuDuc8h8PR8v1bFns3zA/umF9WWV5UyYsVloUy+dXTP2/7QoVVUfn1M8uTB/KzMj+nj3yfl9kc37M5LLE5KqH1hwGu38d2XRzPw1fsKR6I4a4PpMDxvR2LUOANfJUlgQh461q8WhafXxn575rFeoUWyhAZSoQQREmMVAdxHCGk3ClOEtI0JRmPmCiFUYSMQkbjCVEcY6nD9+mULMv4mM3QdL2FYRi81OvoLQOzbdJs6mz7ttnGNE2VdRqNBp1Oh7ra1Wo1Wmrb9wf0ej0cx8W2baxulz/EXAT5C6gRvQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;PerfResults&quot;
        title=&quot;&quot;
        src=&quot;/static/30a1feb7d28ce33767485677acfbeb21/a65ce/PerfResults.png&quot;
        srcset=&quot;/static/30a1feb7d28ce33767485677acfbeb21/4edbd/PerfResults.png 175w,
/static/30a1feb7d28ce33767485677acfbeb21/13ae7/PerfResults.png 350w,
/static/30a1feb7d28ce33767485677acfbeb21/a65ce/PerfResults.png 559w&quot;
        sizes=&quot;(max-width: 559px) 100vw, 559px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;In total, we did 43 different performance tasks and the project length was 3 months. So these results were quite amazing.&lt;/p&gt;
&lt;p&gt;As an AX technical consultant, I can say that the project flow and organization were great and contained all typical interaction types that exist in similar projects. The project size due to system complexity was above average(for example Technical consultant time was 45 days, that is more than usual).&lt;/p&gt;
&lt;p&gt;I want to describe the pieces of success and common mistakes that I saw on other projects like this.&lt;/p&gt;
&lt;h2 id=&quot;performance-project-team&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#performance-project-team&quot; aria-label=&quot;performance project team permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Performance project team&lt;/h2&gt;
&lt;p&gt;The main factor for success is the proper project team. A typical project team should have the following people:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;IT manager&lt;/li&gt;
&lt;li&gt;Functional consultant&lt;/li&gt;
&lt;li&gt;Infrastructure manager&lt;/li&gt;
&lt;li&gt;SQL administrator&lt;/li&gt;
&lt;li&gt;Project manager&lt;/li&gt;
&lt;li&gt;AX Technical consultant&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;One person can combine several roles but &lt;strong&gt;all these roles&lt;/strong&gt; should be a part of the project.&lt;/p&gt;
&lt;h3 id=&quot;typical-mistakes-of-organizing-a-team&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#typical-mistakes-of-organizing-a-team&quot; aria-label=&quot;typical mistakes of organizing a team permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Typical mistakes of organizing a team&lt;/h3&gt;
&lt;p&gt;Let&apos;s discuss what can happen if we don&apos;t configure a team as recommended:&lt;/p&gt;
&lt;h4 id=&quot;--no-project-manager-allocated&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#--no-project-manager-allocated&quot; aria-label=&quot;  no project manager allocated permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;- No project manager allocated&lt;/h4&gt;
&lt;p&gt;Initially that seems reasonable: the system is critically slow, you need just technical people who tell you what to do and not managers. But this became an important factor later.&lt;/p&gt;
&lt;p&gt;A lot of performance tasks are complex, have no direct impact on users and require efforts from different people to be solved.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Probably the most typical example here is a recurring batch job that tries to reserve quantity for open orders, but some orders are old, will never be reserved and the process happens again and again. Or an integration task that tries to process wrong messages every time it runs and does not mark them with an error flag.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Such jobs can produce a huge constant load on AOSes and SQL Server and are quite complex to resolve. You need to contact business users, understand the reason for such multiple processing, find a solution, develop and test a fix(this can be complex for a procedure that was developed 5 years ago and nobody wants to touch it). So a good project manager should allocate resources for tasks like this and control the execution.&lt;/p&gt;
&lt;h4 id=&quot;--only-sql-dbainfrastructure-team-is-involved&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#--only-sql-dbainfrastructure-team-is-involved&quot; aria-label=&quot;  only sql dbainfrastructure team is involved permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;- Only SQL DBA/Infrastructure team is involved&lt;/h4&gt;
&lt;p&gt;This is a typical situation in the beginning. Users complaining about performance, you ask you DBA to check servers and find the reason. Often this doesn&apos;t work and ends up with more statistics or index updates. A lot of performance problems are related to parameter sniffing issues or Dynamics AX settings/code, and it is hard for SQL DBA to fix that, without knowing what is the logical purpose of these tables and what should be the correct SQL plans for long queries.&lt;/p&gt;
&lt;h4 id=&quot;--sql-dbainfrastructure-team-is-not-involved&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#--sql-dbainfrastructure-team-is-not-involved&quot; aria-label=&quot;  sql dbainfrastructure team is not involved permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;- SQL DBA/Infrastructure team is not involved&lt;/h4&gt;
&lt;p&gt;This is the opposite situation to the previous case. Sometimes performance problems are related to SQL Server or hardware configuration.&lt;/p&gt;
&lt;p&gt;This tweet probably represents a common problem. Hardware used for multimillion ERP implementations is less powerful than a typical gaming laptop.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 583px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/89b7afd3abd36adba912e3ff1df35f29/9fc4b/SlowHardware.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 52.57142857142857%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACmUlEQVR42k2S7W/TZhTF+3fCp0kIJIb2ATGJjUkgvkxCID5AaaoqDUOFUlTEW5oCRYi1ahEaLd1S0jRpmthx89iJYztO4sR56Y9rZ0OzdHQfXz8695xzPbWzs4OmV9n7+pXcQYGNio/ZsLHsJo7n4fs+w8GAMOwT9AKCfp9+GNKTGiHo9f5XQ6ay2T0c16WsaSjTRCmFcXxMtVpFUzbVpk+l7lFULrppxwP8dgev5ePKQK/ViuF6rZh4Cnm6QUDTceIaTfLbbTqdDp1eiN8f0Ba0BOFwxGg0JBTFw+GQ4WgUYyDn8XgcUU0Im46LVW9gN5uxyqjWlElFq4hSHcsyMYxqrFwX5eWKJt8VumHE76Wjsrj0OPmPcGtrnVQqyc6XLxzk98nn89RMi3Y3wO9GuYWS4eBfhPSjHKXXi3ITdLvd2Nl3wrnELc6eOYWyGvHko3KZfFbIN9/wz/s0uY9/opdLmKK+XrdwJfO+EET2I+snJyex3e+Ez5dTXDx3mtLmawobKxyuv6KwusihwJCeXcziOE0atk0zjkNR1aM4NLGscVwzyOX2JPfWhLBeO+Dm1Z9Ymb9LOnWHzfQTirufcBsWQfTLyB3PruPVFZ702p6L7bZotLqiNMAxFX/Mz7L96e2EMJm4wc8//sDBeobt9CKfXy6w/WqBXTn/nVkiv7HG4edNqvtZVKWEKhfY3S+yVVDUZCnqqMiLZ8usZR5OCK/9ep4L589iKIvDUineXE02aOpHaNm/yL5+ytaDaT4uzJB7n8E2dMltTCccy+JkMZ7D+od3vFtdmhAuP1ngypVfmJubJZGY5t69aWZmZkjOJ3n4+DGPlpZ4dH+O2d+vkrh+mdu/XWLxfpLMyktWV9JC9oGU3F3LLPMNz8QO9nMgFycAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Slow Hardware&quot;
        title=&quot;&quot;
        src=&quot;/static/89b7afd3abd36adba912e3ff1df35f29/9fc4b/SlowHardware.png&quot;
        srcset=&quot;/static/89b7afd3abd36adba912e3ff1df35f29/4edbd/SlowHardware.png 175w,
/static/89b7afd3abd36adba912e3ff1df35f29/13ae7/SlowHardware.png 350w,
/static/89b7afd3abd36adba912e3ff1df35f29/9fc4b/SlowHardware.png 583w&quot;
        sizes=&quot;(max-width: 583px) 100vw, 583px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;If you don&apos;t include SQL/Infrastructure team into the project team, there is a high chance they just push back any recommendations.&lt;/p&gt;
&lt;p&gt;Even for the most obvious performance counters, it is quite easy to reject recommendations, let&apos;s take a CPU load as an example. If the load on AOS is 80%(that is really big) and the recommendation is to add more CPU cores, it can be argued that almost 20% are not used and everything is OK. Or if the CPU load is 100% for 10 minutes and then 20% for 10minutes - the average will be 60%. Such discussions are very time consuming and not productive, and may be simplified if all participants are within one team.&lt;/p&gt;
&lt;h4 id=&quot;--only-ax-technical-consultant-involved&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#--only-ax-technical-consultant-involved&quot; aria-label=&quot;  only ax technical consultant involved permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;- Only AX technical consultant involved&lt;/h4&gt;
&lt;p&gt;Your Dynamics AX is slow and you ask AX technical consultant to check why and give their recommendations. A typical example of this: a company hires a Microsoft Services consultant, they do a 3 days analysis with &lt;a href=&quot;https://github.com/PFEDynamics/DynamicsPerf&quot;&gt;DynamicsPerf&lt;/a&gt; tool and at the end give you a very nice looking report.&lt;/p&gt;
&lt;p&gt;This may solve simple issues, but may not work in some difficult cases.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;For example, for this project one of the problems was related to slow shipment processing. When we started analysis we have found that a shipment module was using a lot of cross-companies queries, but the actual company was always defined in the business process, so these cross-companies queries were removed and it gave quite a considerable performance boost.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Finding and fixing issues like this involves a lot of communications and may not be resolved just by a single person sitting and running some queries.&lt;/p&gt;
&lt;h2 id=&quot;the-project-flow-and-tasks&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#the-project-flow-and-tasks&quot; aria-label=&quot;the project flow and tasks permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;The Project flow and tasks&lt;/h2&gt;
&lt;p&gt;The team should meet on a very regular basis(like once a week) to discuss what &lt;strong&gt;changes&lt;/strong&gt; and tasks should be done in the system to make it faster.&lt;/p&gt;
&lt;p&gt;Quite an important point here is that each task should be testable, tracked and have a status. Don&apos;t allow email chains like in this screenshot, where one problem was being discussed for 2 months with more and more people getting involved.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/bb9d2782b06c0df527c037a1c6cb9fdd/84a90/2monthemail.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 26.857142857142858%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAYAAABFA8wzAAAACXBIWXMAAAsTAAALEwEAmpwYAAAA/0lEQVR42o2QzU7DMBCE+/6vBEcoEoeSAmqLemiD1NLShNhxEuy1k491hThjaeTZv9HszorlkkNZclyt2BcF5+2W4D1BAiEoRBBFjIn/vFndVHy1lspYLsZg+x5jLUZ5hrWGVuuuc0jMwpGUEun3jxnKYwwaj8xsFjx94F3L6Aek75hSZBoTozZPow5qs4jHaz27FhWQ4Im6hWjsdSMfdDYIs3K94fnmls3dPa/zBS/zgsOp5bMbOTcDjftWgQmvCGn6c5R5zkV1lU+S3V1X3pYHnjZ7FusdD+sjj4q394rdseZSN5i2w/SRupMrusHT61maXqic4AbNOXd1mQV/ADsuf66gXpHGAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;2month email&quot;
        title=&quot;&quot;
        src=&quot;/static/bb9d2782b06c0df527c037a1c6cb9fdd/8c557/2monthemail.png&quot;
        srcset=&quot;/static/bb9d2782b06c0df527c037a1c6cb9fdd/4edbd/2monthemail.png 175w,
/static/bb9d2782b06c0df527c037a1c6cb9fdd/13ae7/2monthemail.png 350w,
/static/bb9d2782b06c0df527c037a1c6cb9fdd/8c557/2monthemail.png 700w,
/static/bb9d2782b06c0df527c037a1c6cb9fdd/84a90/2monthemail.png 982w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The initial set of tasks usually comes from a &lt;a href=&quot;https://denistrunin.com/performance-audit&quot;&gt;Performance audit&lt;/a&gt;, here is a &quot;typical&quot; example:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/21874d39fe4d9ee2dc85247492a1b21d/4d08a/FirstRecomendations.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 38.285714285714285%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABd0lEQVR42jVS246CUAzk/3/IJxfNmmiiCOhyEVRuiqB4Nxr1YbbTXR+antB2OjPFcFwXRVGgWq9R5jma3Q47ieFwiCzL4DgO4jjGaDRCu91GFEXwfR/u/1zTNDgejzifz5qNJE3hex4Cy4I7GCBbLLTIwcvlgpR1ASDofr/H+/1WsG63i36/j+l0itVqpb2PxwPGWpgxqu0WtURZljidTrqdebPZaJ2ZQ/f7HZPJBKZpotfrIRdVXMTvCrgQRvP5HNFshiAIUNc1DoeDvtnImicK2EdJ1+tV7SCYJao+8SFgJEmiQ5TGIP2m+QMiAH2cyTIyIRhZEJCycwHhItZpEa0y6A095CAZ0WQGpVPicrlUcOatWMKh8XiMgfht2zZIiMBcSGUGgXgYDsSyjZJvtxuqqsLz+dQBbmcfwV6vlzL86nTwTdnyDoQt+6nA8OR3sOVarlzrR96hsOVGSqJ8ekkmzGEY6oEsYWi2WrCFJeUWsoy9/N1+AbM+QYBzldgqAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;FirstRecomendations&quot;
        title=&quot;&quot;
        src=&quot;/static/21874d39fe4d9ee2dc85247492a1b21d/8c557/FirstRecomendations.png&quot;
        srcset=&quot;/static/21874d39fe4d9ee2dc85247492a1b21d/4edbd/FirstRecomendations.png 175w,
/static/21874d39fe4d9ee2dc85247492a1b21d/13ae7/FirstRecomendations.png 350w,
/static/21874d39fe4d9ee2dc85247492a1b21d/8c557/FirstRecomendations.png 700w,
/static/21874d39fe4d9ee2dc85247492a1b21d/4d08a/FirstRecomendations.png 709w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Other tasks come from 2 sources:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;User complaints (e.g. an operation works slowly)&lt;/li&gt;
&lt;li&gt;Periodic servers monitoring(Top SQL queries, Blocking, missing indexes, etc..)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For user complaints, the first question that should be asked is &quot;Can we replicate this issue in a Test environment?&quot;. If we can do this it means that the task is quite simple, we allocate it to a developer for the tracing and investigating. If the answer is &quot;No&quot; then the team should discuss the plan to proceed. Probably the first thing to do in this case is to implement a tracing solution that will allow us to operate some numbers(e.g. how often the issue happens, at what time, what are the delays and so on) rather than just general &quot;the system is slow&quot;.&lt;/p&gt;
&lt;p&gt;Also, before discussing any optimizations it is worth finding what business task users are trying to resolve, maybe there is another more efficient way to do it.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The classic example here is a case where the whole accounting department complained about slow Dynamics AX2012 performance. The Client had already upgraded SQL hardware, installed a new AOS, but nothing helped. When we discussed the issue we found that a part of users daily work was to update clients information. In order to do this, they opened &quot;All customers&quot; list page, filtered it by the required customer, double clicked on it to open &quot;CustTable&quot; form, edited the information, then closed CustTable form, filtered &quot;All customers&quot; list page again by the next customer and so on... &quot;CustTable&quot; is a very heavy form that takes about 5 seconds to load and such delay was very annoying if you need to update 20-50 customers. The solution was quite simple: we just showed them that they don&apos;t need to close &quot;CustTable&quot; form to switch the active customer, there is a Grid view in this form where you can almost instantly search for it. The users were very happy.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;ready-to-change-and-forward-only-approach&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#ready-to-change-and-forward-only-approach&quot; aria-label=&quot;ready to change and forward only approach permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Ready to change and forward only approach&lt;/h2&gt;
&lt;p&gt;That is what I suggest to discuss with a customer at the beginning of the project. The only way to fix performance problems is to &lt;strong&gt;change&lt;/strong&gt; something. There is no magic flag &quot;Run faster&quot; in Dynamics AX or SQL Server.&lt;/p&gt;
&lt;p&gt;These changes can be done in multiple areas, but as with any change, there is always a chance that it can affect the system in a negative way. We try our best to avoid this, but such issues are happening on almost every project. Even a positive change(you created a new index or cleaned up some tables) can produce a negative effect due to parameters sniffing.&lt;/p&gt;
&lt;p&gt;The only correct way to deal with such issues is to continue the system monitoring, identify and fix them quickly. Not a correct way is to perform a rollback.&lt;/p&gt;
&lt;p&gt;Some practical recommendations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Have someone from the customer team to apply any changes to Production. There were a lot of situations like this: you created an index and the next day some users can&apos;t print documents(totally unlinked events). Then there were usually a lot of emails trying to find the reason and blame someone and the person who did the last change is a perfect candidate for this.&lt;/li&gt;
&lt;li&gt;Allocate a day to monitor the system after the changes were applied. This is needed to &lt;a href=&quot;https://denistrunin.com/performance-sniffing&quot;&gt;catch and fix&lt;/a&gt; parameters sniffing issues.&lt;/li&gt;
&lt;li&gt;For the first round of changes include as many as possible. The strategy &quot;one change in a time&quot; doesn&apos;t work well in the beginning. Often the first positive feedback from users creates a lot of trust, that makes the project flow simpler later.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;prepare-a-separate-lab-version-for-the-project&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#prepare-a-separate-lab-version-for-the-project&quot; aria-label=&quot;prepare a separate lab version for the project permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Prepare a separate LAB version for the project&lt;/h2&gt;
&lt;p&gt;Often the most complex problem in performance optimization is to replicate an issue. There are a lot of cases where the operation(for example Sales orders posting or some batch job) is working without any issues during the day, but becomes slow during a certain hour. The reason may be in other parallel processes that caused blocking or the high system load, but very often this depends on the particular data used in this process.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Typical example: warehouse operations where for some period you can have zero lines ready for shipment, but an hour later there are 10k lines.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;To trace such issues quickly, a database point-in-time restore(like restoring the Database at 11.32 am) can provide valuable information. So organizing a separate environment where such backups can be restored and traced can save a lot of time allowing to quickly replicate an issue and test the fix later.&lt;/p&gt;
&lt;p&gt;You don&apos;t need to replicate full Production hardware for this. In this project, we used a separate one-box environment(that included AOS, SQL and all other components) with 8 CPUs cores, 48GB of memory and 3TB drive(to keep 2 copies of database backup). Also, an important tip is to run this environment under a user that doesn&apos;t have any Production access to avoid situations of sending e-mails to the real customers or to the production integration folders.&lt;/p&gt;
&lt;h2 id=&quot;deployment-and-communication-channel&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#deployment-and-communication-channel&quot; aria-label=&quot;deployment and communication channel permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Deployment and communication channel&lt;/h2&gt;
&lt;p&gt;This process of Dynamics AX performance optimization is iterative: we fix first top current issues, then continue monitoring, provide a new set of actions and so on... It is quite important to minimize the time that is needed to deploy the changes to Production. For some customers, it is not a problem, but may be challenging for others.&lt;/p&gt;
&lt;p&gt;I suggest reviewing the deployment process and try to simplify it if possible. Ideally, we should be able to do deployments every day if needed.&lt;/p&gt;
&lt;p&gt;Also, a great role in project success plays a good communication channel(other than e-mail). A group in Microsoft Teams is probably the best solution for this, however, sometimes it is tricky to create it due to different users&apos; domains(check this &lt;a href=&quot;https://github.com/Zerg00s/MultipleTeamsInstances&quot;&gt;trick&lt;/a&gt; if you want to run multiple Teams on one computer).&lt;/p&gt;
&lt;h2 id=&quot;deal-with-external-integrations&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#deal-with-external-integrations&quot; aria-label=&quot;deal with external integrations permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Deal with external integrations&lt;/h2&gt;
&lt;p&gt;Some integration types can often cause performance problems. In AX2009/AX2012 such &quot;dangerous&quot; types are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;SQL access to the Dynamics AX database for the 3-party application.&lt;/li&gt;
&lt;li&gt;AIF or Service endpoint to query some information&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The common problem is that these 3-party applications can easily stop the whole system by calling these services or running SQL in an uncontrolled manner. The main problem here is that you can’t control or change these 3-party applications, they often belong to a different team that doesn’t care about ERP problems.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Examples that we had: SQL query to get customer information(Address, Contact info) with some missing DataAreaId field in joins, that leads to full table scan for each call, or frequently calling AX service that returns On-hand data for the whole store.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In cloud D365FO version, Microsoft faced exactly the same problems(OData replaces SQL access for the cloud) and the solution they proposed is a &lt;a href=&quot;https://docs.microsoft.com/en-us/dynamics365/fin-ops-core/dev-itpro/data-entities/priority-based-throttling&quot;&gt;Priority based throttling&lt;/a&gt;. That means when the system is highly loaded such queries will get an exception. There were some negative comments about this feature on Yammer, but when you see how the whole Dynamics AX performance is affected just by one incorrectly written query, your opinion may be changed. So throttling can help in this case(at least start the dialog about optimization).&lt;/p&gt;
&lt;p&gt;The best solution is probably not using such integration types if you can&apos;t control the external system. If you need to provide some information to the 3-party system, just unload it to the separate database(like BYOD in Dynamics 365FO).&lt;/p&gt;
&lt;p&gt;But it is very hard to change the integration process that is already implemented, so a typical approach is optimizing X++ code related to the service, and discussing call frequency with the external team(that is where you need an &quot;IT manager&quot; person).&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#conclusion&quot; aria-label=&quot;conclusion permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;So to deal with Dynamics AX performance problems you need the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Organize a team with the right people&lt;/li&gt;
&lt;li&gt;Properly manage performance issues&lt;/li&gt;
&lt;li&gt;Prepare a test version&lt;/li&gt;
&lt;li&gt;Do a good integration design&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This allows you to quickly resolve and fix any problem.&lt;/p&gt;
&lt;p&gt;I hope you find this information useful and will use it in case of any AX2009, AX2012, Dynamics 365FO performance troubleshooting. As always, in case of any problem, suggestion or improvement, do not hesitate to contact me, I will be happy to discuss it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update 08/11/2020&lt;/strong&gt; - check this article from Glen Turnbull about D365FO specific tasks &lt;a href=&quot;https://community.dynamics.com/365/financeandoperations/b/performancetipsandtricks/posts/managing-general-performance-issues-in-microsoft-dynamics-365-finance-and-scm&quot;&gt;Managing General Performance Issues in Microsoft Dynamics 365 Finance and SCM&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Execute direct SQL in D365FO database]]></title><description><![CDATA['Execute direct SQL' form provides a simple interface to execute SQL commands on D365FO database.]]></description><link>https://denistrunin.com/xpptools-sqlexecute/</link><guid isPermaLink="false">https://denistrunin.com/xpptools-sqlexecute/</guid><pubDate>Sun, 02 Aug 2020 22:12:03 GMT</pubDate><content:encoded>&lt;p&gt;&apos;Execute direct SQL&apos; is a simple form that allows to write and execute direct SQL from the browser on D365FO database. It can save time when you are debugging or troubleshooting.&lt;/p&gt;
&lt;p&gt;The original idea was introduced in &lt;strong&gt;AX Paradise&lt;/strong&gt; &lt;a href=&quot;https://axparadise.com/sql-access-on-production-in-d365fo/#page-content&quot;&gt;blog post&lt;/a&gt;, I added some improvements and included it to my list of tools.&lt;/p&gt;
&lt;h2 id=&quot;how-to-work-with-this-form&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#how-to-work-with-this-form&quot; aria-label=&quot;how to work with this form permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;How to work with this form&lt;/h2&gt;
&lt;p&gt;To use this form, you need to go to Administration-Inquiries-Database, and run &lt;strong&gt;SQL Execute form&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 673px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/2127ee6b2b25de77223304a8e67c1523/c391c/DEVSQLQueryExecute.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 75.42857142857143%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB10lEQVR42p1Ui3KjMAzk/7+ubZo0tCEBwvtlY8i7YW9lSu4yd522x8yObMlaSbaEE0dbPM+e4bouttsQWZrcUFUl+s6gM+234QSbNZ6eHvD4+ID5fI6XlzkWVi4QMcCu72Ba/X3CPC+glKaTYjYdDrse+w8I2U+ys4RRnDCbJbZhYDOZ0GplpZT8VdlmkjzvZGmMJImppCMzksyaukKe51YnxGEQIE3Tm+METVscx6jrmr5jRU7T1CjLEufzCafjEYf93h6+XM72ClI+jgQsywJaNX9ll2UZ7XxAcpwORyHUUERvFLpWoC3kTu290mnXGyv/Ve6o1xZy3j5KGKVoVItGG0oD3XY3KE20huju9Hd2/XvvlLVGWSu04lRUaLKC5V8wDMD1OvwYTtcfQN/xE5bhtvuvzzEkPL8PuLxfP/Dn+vP9iVXc60c4URThdbWGtwnwttpYrNaU3hruq2el2FfeqBe5WLpI0hxBOPq6bx5tPjl8ODXnVbN1Wt1YNNy3bA9BnqVslZotkbMTKvuKDdtHRlXmXlMn9rLI2ZOj/0goBGxSgTT1tJYfhNgqkigGlUmQgEuZc1ambCLK2icORwg+I5SDIqeglpD22WwG3/ctoejFPvn8ArFFdTIWBFczAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;SQL form&quot;
        title=&quot;&quot;
        src=&quot;/static/2127ee6b2b25de77223304a8e67c1523/c391c/DEVSQLQueryExecute.png&quot;
        srcset=&quot;/static/2127ee6b2b25de77223304a8e67c1523/4edbd/DEVSQLQueryExecute.png 175w,
/static/2127ee6b2b25de77223304a8e67c1523/13ae7/DEVSQLQueryExecute.png 350w,
/static/2127ee6b2b25de77223304a8e67c1523/c391c/DEVSQLQueryExecute.png 673w&quot;
        sizes=&quot;(max-width: 673px) 100vw, 673px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;It allows you to enter &lt;strong&gt;SQL text&lt;/strong&gt; to execute and outputs the execution results as &lt;strong&gt;HTML&lt;/strong&gt; or as a &lt;strong&gt;File&lt;/strong&gt; when you press the &lt;strong&gt;Run&lt;/strong&gt; button.&lt;/p&gt;
&lt;p&gt;You can limit the number of returned rows. Due to AX string manipulation and text formatting current output is quite slow, it can handle only about 100-1000 rows.&lt;/p&gt;
&lt;p&gt;As direct SQL execution is quite a dangerous operation, I also added a second tab to this form that logs all executed commands, so you can always check who used it.&lt;/p&gt;
&lt;p&gt;To limit the number of users who can use this tool I added a new role - &lt;strong&gt;DEVSQLQueryExecute&lt;/strong&gt;(it is required even for SysAdmin)&lt;/p&gt;
&lt;h3 id=&quot;performance-inquiry&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#performance-inquiry&quot; aria-label=&quot;performance inquiry permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Performance inquiry&lt;/h3&gt;
&lt;p&gt;One of possible use cases of this tool can be a performance troubleshooting for D365FO. Current tools for this in LCS are quite &lt;a href=&quot;https://denistrunin.com/performance-sniffing&quot;&gt;slow&lt;/a&gt; for a cloud version.&lt;/p&gt;
&lt;p&gt;You can execute commands like getting &lt;a href=&quot;https://github.com/TrudAX/TRUDScripts/blob/master/Performance/AX%20Technical%20Audit.md#get-top-sql&quot;&gt;TOP SQL&lt;/a&gt; without a direct connection to SQL Server.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/c747d5a3377acc9670b2eaa2151ddbf1/13e20/TopSQL.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 74.85714285714286%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACLElEQVR42o1TabOiMBDk//+6tyohIDdyyB1Ai33PtXdmULf8tFLVJYaaTh+J1bUtirLGMhvM04jJMIY38PqnsLquR1k16IcJZrpguazvuK6Ylium+TNYbTvA90PESYy6bmCMwdh2GJoOZhzQ5AV+r9/g537/P6y+H5FGEdqGbc9Y1xW32w23n58HvnH/c8enD1nukKe54FRUKKoa56ZHLejQdCOGcYaZL4LBzBQPuaB4eH00i6Aft8ispj6jLEuxN08GURRC2Ta0q+G6LhzHIWg42oFSCq7nQmuNOI5QFgV6EsQoihxD38Mahh6XZSa7E66XBTER/vr6wv5wgHYUFEPZ2O13hL0Q7u0DgjAgolbmWAg3zDxW1zY4VyVGIuYPvPOBCDZ1Ch4RBL4Pm1QnVBwrSZOE3hNRyM549smxEZb/CCPaWTm2KGF1zgPHoyfkHMnplFGJjRTJc2+EQ9+R1E02S46iAAeyxBkyoabsXMqM/9tq28jzNILAR56f5ELwZTDjKPaFUG7HgzCOKcPdTspQtsL+kR1DSRRaNuSCsjQRITzPhfD7i/ClMAyFRFOz6qFUKy1KmZDtu6TwlGWoq+pF+IxMCJ9NbQojOSKe54nV49GV/LhVKYisHunXp7WW8ufZN0IOtqAsnkrZMiuxSZ1D5QRBIK2mZC/LEiokRRLHMlOfK1RlIbNSEDVu8VliPBWmdDRY0daqJjiizNNbSd7rm4szEbKyLcPN6V9YoVyHdujMcQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Get Top SQL&quot;
        title=&quot;&quot;
        src=&quot;/static/c747d5a3377acc9670b2eaa2151ddbf1/8c557/TopSQL.png&quot;
        srcset=&quot;/static/c747d5a3377acc9670b2eaa2151ddbf1/4edbd/TopSQL.png 175w,
/static/c747d5a3377acc9670b2eaa2151ddbf1/13ae7/TopSQL.png 350w,
/static/c747d5a3377acc9670b2eaa2151ddbf1/8c557/TopSQL.png 700w,
/static/c747d5a3377acc9670b2eaa2151ddbf1/13e20/TopSQL.png 741w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;To return large text or the result of UPDATE statement you may update a &lt;strong&gt;SQLResults&lt;/strong&gt; field(as standard ResultSet has some limits, so large text can&apos;t be returned directly).&lt;/p&gt;
&lt;p&gt;For example, you can also download and analyse SQL plan using the following command:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/f3df172fab32da009764b98a0d1bc333/ddc81/SQLPlanOutput.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 89.71428571428571%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAYAAABb0P4QAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAC8ElEQVR42p1UaU/bQBD1H+4/6PdWLZWAXmqL+qEHkEIIV8vRQ6KIFhAgrjQkcU5f8Z3YMYntJK+zm4RDSFRlpedZjXfezvFsQSxUUNNkWKaBIAjQbrUIwZ0hBEELiiwhn8uhUinDMAz4XuPOEDpxCFWRUSwWUSiIKJaK1w54DcL/EEZhG5qmQ1EUNOouEdQ5hmRBk8G7Edj0vVsIVZWX6zoOBTeJ2IFtWZxIVi0omkEEV7Ouw6SeM8uIh+CEYbsF27ZgWTbCdhvnNJh+ZgH8hoOdtIW0qCPw3WuEek2jYWr8YhbHhjkgbMO0XLjuoAx2G2XGghoNF02vzjFsxWVLbvoYhDAMabI6lVyBqalwdB11diu1IooisPcRYZjFvyC06SArWSqVoBAs3YBd0+E5lB310/d9jiiO0e310O12b4UQRyEcU0e1WIAqSZAViYakwKAemeRnPWLWoUvrpALHsSkBm3puDqzFE7IHVmB9y4sijk8zOD3JIJ3JoVCs0nQNSHINVVnrW0lDuaLwvaRQi8iqNH32Ieg6syYfrKBTz3b2s9jcEQl5bO2K2NrL4fd+HtuEX7tn2N7LYv+ohKM0fVElG4VqHWLZJetAUl1UFQeK7sGwzyGUKlWsflvB1x9fsLG5jqWVZdwfeY8H4x/w+PkUHj2bxMOxd2Q/YuxNEqOvZjD6egZPXiYw8mIaT9+mMDaRxPjEHIdwcprG8cEqitmfyP35TmVvYGp2EdPJBUzPLmDyUwqJ5CLH/Od1zC+vYW5xhe8XCKmlNW6ZL7W0CiGTK2H78IxSttBqd2CYDh9CjybGRK9rCpdPtxvDcZuktXN04oj7Op2YwzA8sJ9MTH7hIF3AvUQGiUMdQJcIDdRINjHJpEW6MvTLfbUq8XetFmmStMn8nuehUq7QhB3SLBFmsiI8PwBbJDN64Nrq9S4dnU7nQm9s3z/fo3gfYRTz4D6h1+wHDwiuklzdXxyixUpWVY3+VCpyuTxkmSQlyfgLV6U5BjIYkecAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Get SQL plan&quot;
        title=&quot;&quot;
        src=&quot;/static/f3df172fab32da009764b98a0d1bc333/8c557/SQLPlanOutput.png&quot;
        srcset=&quot;/static/f3df172fab32da009764b98a0d1bc333/4edbd/SQLPlanOutput.png 175w,
/static/f3df172fab32da009764b98a0d1bc333/13ae7/SQLPlanOutput.png 350w,
/static/f3df172fab32da009764b98a0d1bc333/8c557/SQLPlanOutput.png 700w,
/static/f3df172fab32da009764b98a0d1bc333/ddc81/SQLPlanOutput.png 837w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;However, I don&apos;t know whether this will work for production instances(due to security rights). If you can test it, ping me with the results. If it doesn&apos;t work, probably we should create an Idea to allow this(at least until LCS views will be fixed). For a list of sample queries check Glenn Berry&apos;s monthly update of &lt;a href=&quot;https://github.com/ktaranov/sqlserver-kit/blob/master/Scripts/Azure%20SQL%20Database%20Diagnostic%20Information%20Queries.sql&quot;&gt;Azure SQL Database Diagnostic Information Queries&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;summary&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#summary&quot; aria-label=&quot;summary permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Summary&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Execute direct SQL&lt;/strong&gt; tool can simplify your troubleshooting experience. You can download it using the following link - &lt;a href=&quot;https://github.com/TrudAX/XppTools#installation&quot;&gt;https://github.com/TrudAX/XppTools#installation&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Feel free to post any comments(better as a GitHub issue) or ideas, what else can be improved.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[A tool to convert a list of values to a query range]]></title><description><![CDATA['List of Values to Range' tool can help users deal with the list of values in query range and copy-paste values from Excel.]]></description><link>https://denistrunin.com/xpptools-listvaluestorange/</link><guid isPermaLink="false">https://denistrunin.com/xpptools-listvaluestorange/</guid><pubDate>Wed, 08 Jul 2020 22:12:03 GMT</pubDate><content:encoded>&lt;p&gt;This functionality can help users deal with multiple values in a query range. You can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Copy the list of values from Excel and paste it in a query range;&lt;/li&gt;
&lt;li&gt;Easily manage the values in the existing range.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This tool was initially migrated to D365FO by Anton Kazarnovsky. Then it was slightly polished.&lt;/p&gt;
&lt;h2 id=&quot;how-to-work-with-this-tool&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#how-to-work-with-this-tool&quot; aria-label=&quot;how to work with this tool permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;How to work with this tool&lt;/h2&gt;
&lt;p&gt;To use this feature, you need to go to &lt;strong&gt;Options-Page option&lt;/strong&gt;s and press &lt;strong&gt;Advanced filter or sort&lt;/strong&gt; button(or use Ctrl + Shift + F3 shortcut).&lt;/p&gt;
&lt;p&gt;A new button &lt;strong&gt;List of values&lt;/strong&gt; was added on this form. If you press this button a new form will appear with two parts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Column view (upper part);&lt;/li&gt;
&lt;li&gt;Range friendly view (bottom part).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/a5dbc6bd7f703357f40d13383ec3b9c3/22c86/DEVListOfValuesToRange.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 42.285714285714285%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABTElEQVR42oWSy2oDMQxF5///p/uuuwu0mxBCaBqaeWX8GL9ke24lQ2igpRWIa41ljY7sTqmFYgggIqRMoFKQa0UFmkvsvIc2DotJ0CvnEefknx5jQqeto1w3EH8IxoLWFZULFOeaSqymGefzBeN0a8U4/VdPlNHZ+UaWk4M28MuC0Pfww4AwjgisnuPx/YLDfg+tFf6ynLmg+fjIwVpstTByRmVcQQ+UsG1bc6UtTscDvHf/F3QxkfMBuWxwzrdZSKy5Y2IEidVi8Pp2wOkyY8M34nbXx4L97MmsCWuoUDbChtJUhr/6whcRuDOP592CpxcD7TJcLDBO9qlpSISYMuwa0MXIcEnwGDXFhhxjhHdrW4tbHslw/cQ8DRh5rn1/xTxPTKGx8NyVUk2dXRjZ8S1zq/Js5LDYfXZihZ+N/LAym6wlR/S+/2i7o8cXcLBuADK8bkAAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;DEVListOfValuesToRange&quot;
        title=&quot;&quot;
        src=&quot;/static/a5dbc6bd7f703357f40d13383ec3b9c3/8c557/DEVListOfValuesToRange.png&quot;
        srcset=&quot;/static/a5dbc6bd7f703357f40d13383ec3b9c3/4edbd/DEVListOfValuesToRange.png 175w,
/static/a5dbc6bd7f703357f40d13383ec3b9c3/13ae7/DEVListOfValuesToRange.png 350w,
/static/a5dbc6bd7f703357f40d13383ec3b9c3/8c557/DEVListOfValuesToRange.png 700w,
/static/a5dbc6bd7f703357f40d13383ec3b9c3/e996b/DEVListOfValuesToRange.png 1050w,
/static/a5dbc6bd7f703357f40d13383ec3b9c3/22c86/DEVListOfValuesToRange.png 1143w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;In the upper part &lt;strong&gt;(Column view)&lt;/strong&gt; you can find a user-friendly view of the values in the selected range. Here you can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Edit a list of values (it will be immediately reflected in Range friendly view);&lt;/li&gt;
&lt;li&gt;Copy and insert a list of values from Excel;&lt;/li&gt;
&lt;li&gt;Convert the value from the &lt;strong&gt;Range friendly view&lt;/strong&gt; field to Column view by using &lt;strong&gt;Convert&lt;/strong&gt; button.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In the bottom part (&lt;strong&gt;Range friendly view&lt;/strong&gt;) you can find the resulting query range. Here you can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Edit a list of values;&lt;/li&gt;
&lt;li&gt;Apply text conversions:
&lt;ul&gt;
&lt;li&gt;Add &apos;quotes&apos; (“…”) at the start and at the end of each value;&lt;/li&gt;
&lt;li&gt;Add &apos;asterisk&apos; (*…*) at the start and at the end of each value;&lt;/li&gt;
&lt;li&gt;Replace &apos;_&apos; and &apos;.&apos; symbols by the question mark (&quot;?&quot;) in each value;&lt;/li&gt;
&lt;li&gt;Remove spaces (&apos; &apos;)  from each value.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;After you have finished editing of the values list, you can review the final range value in the bottom part, and press &apos;&lt;strong&gt;OK&lt;/strong&gt;&apos;. Then the query range will be updated with the values. Several new ranges for the same field will be created if the length of the value list doesn&apos;t fit in one range.&lt;/p&gt;
&lt;p&gt;The standard system allows you to paste the value list from Excel, but the resulting range is limited to 4K chars(range size). So if you filter more(on average it is 300-400 invoices for example), you range will be truncated. &lt;a href=&quot;https://docs.microsoft.com/en-us/business-applications-release-notes/october18/dynamics365-finance-operations/paste-filter-lists-from-excel&quot;&gt;Paste lists from Excel into filter fields with the &quot;is one of&quot; operator&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The approach used in this tool also has a limit - 2100 parameters. This is a technical limitation (&lt;a href=&quot;https://cloudblogs.microsoft.com/dynamics365/no-audience/2010/05/10/binding-operation-failed-to-allocate-buffer-space/&quot;&gt;https://cloudblogs.microsoft.com/dynamics365/no-audience/2010/05/10/binding-operation-failed-to-allocate-buffer-space/&lt;/a&gt;) (thanks &lt;a href=&quot;https://twitter.com/IevgenMir&quot;&gt;@IevgenMir&lt;/a&gt; for pointing on that)&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/0b74e60c78aec2f61af8bb764bf6db97/FullVid.gif&quot; alt=&quot;FullVid&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;summary&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#summary&quot; aria-label=&quot;summary permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Summary&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;List of Values to Range&lt;/strong&gt; tool can simplify your work with multiple query ranges. You can download it using the following link - &lt;a href=&quot;https://github.com/TrudAX/XppTools#installation&quot;&gt;https://github.com/TrudAX/XppTools#installation&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Feel free to post any comments(better as a GitHub issue) or ideas, what else can be improved.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[A simple way to implement a parallel batch processing in X++]]></title><description><![CDATA[The post describes how you can convert your existing batch job to multi-threaded to increase its performance.]]></description><link>https://denistrunin.com/xpptutorial-batchmultithread/</link><guid isPermaLink="false">https://denistrunin.com/xpptutorial-batchmultithread/</guid><pubDate>Wed, 01 Jul 2020 22:12:03 GMT</pubDate><content:encoded>&lt;p&gt;One of the powerful features of Dynamics 365 Finance and Operations is a Batch framework. In this post, I explain how you can convert your existing batch job to multi-threaded to increase its performance.&lt;/p&gt;
&lt;h2 id=&quot;initial-example&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#initial-example&quot; aria-label=&quot;initial example permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Initial example&lt;/h2&gt;
&lt;p&gt;Let&apos;s consider the following operation - a user dialog that processes customer transactions and performs an action at the end.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 547px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/24033c0b1452fec40b9d05be280082b5/977f7/SingleThreadBatch.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 108.57142857142857%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAWCAYAAADAQbwGAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB2ElEQVR42p1VS3aDMAzk/vfoCXqALnuDbrrpSwifgPkaCMFG1Sg1DSRpKH7o2WB5kDSS7MVxTMfjkZIkkdlJmqZUluVqqapKznlFUdB+v5cXzIfDgcIwlB+sHeM4ytw0DXlt2z5UWivWWjmjtSav6zpSStFutyPf9wnv13/dZOEwDCLuj4+GMUb0MLv1+XyeA8KiPM8lqFhDCS70p5MoXw/daCGgKHKJsSPDuTxZ6EBB0O+mntx3bmEPAuugj/muy7DkxBb1fS8zgJzyWqJmLmdZRlEUkOLcQ/4FQTCz7v+ksJclnx8sbRo3Fmrd0M6PKIpRLfFUNUtSVgOWTEaaHOUDWKvrWuReHJ+7jFQ5g4wOO/xYGq25yMrkvomh5cNg14mxnItmI+AlhjVlirtLXkguInbGcOVYu705iKtTXtkfsI0WYoFOAQEpjhi4vwkQtVlwKSHBU06ZKAo5wRNRuHfwCWBLDadbWo9UMdEtr5Xmuh3/tugafBFDrtuho67V/KEVWR5CQ4AniDfCsLR0Bjiajl7eMnp9TylOFCV5w2kztwhNA1cDahxNGA0Z4K4DoeVNgHmm6OOrpM99QWHMgKrmmFYzchBbAOFCw30DcNcPkWaun6KxfAOpe7o6ABu8VQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Single Thread Batch&quot;
        title=&quot;&quot;
        src=&quot;/static/24033c0b1452fec40b9d05be280082b5/977f7/SingleThreadBatch.png&quot;
        srcset=&quot;/static/24033c0b1452fec40b9d05be280082b5/4edbd/SingleThreadBatch.png 175w,
/static/24033c0b1452fec40b9d05be280082b5/13ae7/SingleThreadBatch.png 350w,
/static/24033c0b1452fec40b9d05be280082b5/977f7/SingleThreadBatch.png 547w&quot;
        sizes=&quot;(max-width: 547px) 100vw, 547px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The logic is quite simple - loop thought all specified customer transactions and call &lt;strong&gt;process()&lt;/strong&gt; function. In our case, it will sleep for the specified number of milliseconds. After the processing of the transactions, it runs a final function - in our case, it is just an Infolog message.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;//1. data preparation&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;strFmt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;%1 - Start operation&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token named-parameter punctuation&quot;&gt;AifUtil&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;applyUserPreferredTimeZoneOffset&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token named-parameter punctuation&quot;&gt;DateTimeUtil&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;utcNow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;//2. Query Processing&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;runQueryProcessing&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;//3.final task&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;strfmt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;%2 - %1 record(s) processed&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token named-parameter punctuation&quot;&gt;SysQuery&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;countTotal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;queryRun&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
 &lt;span class=&quot;token named-parameter punctuation&quot;&gt;AifUtil&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;applyUserPreferredTimeZoneOffset&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token named-parameter punctuation&quot;&gt;DateTimeUtil&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;utcNow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;runQueryProcessing&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;queryRun&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;CustTrans&lt;/span&gt;   custTrans &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; queryRun&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;tablenum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;CustTrans&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;processRecord&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;custTrans&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;processRecord&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;CustTrans&lt;/span&gt;  _custTrans&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;//do some job using _custTrans and transDate&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;sleep&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;taskSleepTimeMs&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Standard USMF demo company has 1700 customer transactions, so if we run this job with no filters in a user interface or in a batch and specify 200ms to process one transaction, it will take 340 seconds for the whole job.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/035c5ec91ba14e3d7aa6f4dc0a81826c/cdef6/BatchResults.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 27.42857142857143%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAYAAABFA8wzAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAA80lEQVR42nXQDUvDMBAG4P7/fyUIUyebG3M6daUfa7euXdLkkjTtoK/XgDIEDx4ul4QLl+h5m+BhHeNx/YXZyweeNjHmrwlmq08sdweWY/meYcHm2wx3ixT3qxSbfQkpJeqmhiaCdQ6uc4h2cYbJ2z5BUlQoG4WqtRCm/yVvCPJ87iG0Q9d1zMNxM+Km3ntEWRLjVBYoiwN0K0FKchYh/0/AkgJZD9m2IEOh4fRAVNcXaK3grGYULlqjA3OzDrj+2TOkMQxXNmCKcZyMiPKTxuGokFfEYwwoz4rHGnDRPdKiCbU0V5ylC3V+FGhUH/4tdPkT336jecEwSW4lAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Batch Results&quot;
        title=&quot;&quot;
        src=&quot;/static/035c5ec91ba14e3d7aa6f4dc0a81826c/8c557/BatchResults.png&quot;
        srcset=&quot;/static/035c5ec91ba14e3d7aa6f4dc0a81826c/4edbd/BatchResults.png 175w,
/static/035c5ec91ba14e3d7aa6f4dc0a81826c/13ae7/BatchResults.png 350w,
/static/035c5ec91ba14e3d7aa6f4dc0a81826c/8c557/BatchResults.png 700w,
/static/035c5ec91ba14e3d7aa6f4dc0a81826c/e996b/BatchResults.png 1050w,
/static/035c5ec91ba14e3d7aa6f4dc0a81826c/cdef6/BatchResults.png 1163w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://usnconeboxax1aos.cloud.onebox.dynamics.com/?mi=SysClassRunner&amp;#x26;cls=DEVTutorialBatchSingleThread&amp;#x26;cmp=USMF&quot;&gt;https://usnconeboxax1aos.cloud.onebox.dynamics.com/?mi=SysClassRunner&amp;#x26;cls=DEVTutorialBatchSingleThread&amp;#x26;cmp=USMF&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;solution-design-principles&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#solution-design-principles&quot; aria-label=&quot;solution design principles permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Solution design principles&lt;/h2&gt;
&lt;p&gt;It is quite obvious that we can optimize this by running the code in parallel threads. Possible options of how this works are described in AX perf blog - &lt;a href=&quot;https://docs.microsoft.com/en-us/archive/blogs/axperf/batch-parallelism-in-ax-part-iv&quot;&gt;Batch Parallelism in AX&lt;/a&gt;, but every approach from that article has its pros and cons.&lt;/p&gt;
&lt;p&gt;What should be considered while designing a simplified solution for this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A change should be simple and require minimum modifications to the original class. We don&apos;t want to create new classes or new tables to support parallel execution.&lt;/li&gt;
&lt;li&gt;We can&apos;t run a single batch thread per one transaction - it will create a lot of overhead for a batch framework, so the solution should allow specifying maximum batch threads.&lt;/li&gt;
&lt;li&gt;Execution flow in batch mode or in user interface should be exactly the same, better to avoid operations that can be run only in a batch.&lt;/li&gt;
&lt;li&gt;We should support the final task, and it should be executed only once after transactions processing.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In most cases, we(as developers) should know how to split the load. In the example above we can just split selected customer transactions by equal intervals, but the split function can be more complex(for example we may want to avoid running parallel tasks for the same customer to prevent blocking)&lt;/p&gt;
&lt;p&gt;The main idea is to introduce a new class parameter &lt;strong&gt;batchIdentifier&lt;/strong&gt; - identification for the split interval and then run our logic only for this interval.&lt;/p&gt;
&lt;p&gt;I created a base class &lt;strong&gt;DEVTutorialBatchMultipleThreadBase&lt;/strong&gt; to incorporate this logic. If we have &lt;strong&gt;batchIdentifier&lt;/strong&gt; specified - that means it is a child task that needs to perform a calculation for this &lt;strong&gt;batchIdentifier&lt;/strong&gt;. If the class is executed with an empty batch identifier - that means it is the main task that should split the load and create all tasks for each split interval and the final task at the end.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;DEVTutorialBatchMultipleThreadBase&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;extends&lt;/span&gt; RunBaseBatch
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;container&lt;/span&gt;               batchIdentifierCon&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;/span&gt;                     i&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;batchIdentifier&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;//child task&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;batchIdentifier &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;finalTaskIdentifier&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;runFinalTask&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;runThreadTask&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;runStartTask&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

            batchIdentifier &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;finalTaskIdentifier&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;processThreadItem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;//create the final task, we need a dependency, so create it in the beggining.&lt;/span&gt;

            batchIdentifierCon &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getBatchIdentifiersRangeCon&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

            &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;conLen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;batchIdentifierCon&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                batchIdentifier &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;conPeek&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;batchIdentifierCon&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;processThreadItem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;finalTask&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isInBatch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                    batchHeader&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                    finalTask&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Method &lt;strong&gt;processThreadItem&lt;/strong&gt; creates the same instance of our class and calls a &lt;strong&gt;pack&lt;/strong&gt; function. If the process is executed in a batch mode it creates a new &lt;strong&gt;runtime batch task&lt;/strong&gt;. Without batch mode, it just runs this task.&lt;/p&gt;
&lt;h2 id=&quot;multiple-threads-batch-example&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#multiple-threads-batch-example&quot; aria-label=&quot;multiple threads batch example permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Multiple threads batch example&lt;/h2&gt;
&lt;p&gt;Let&apos;s change our class to multithread.&lt;/p&gt;
&lt;p&gt;we need to implement 3 function - &lt;strong&gt;runStartTask()&lt;/strong&gt;, &lt;strong&gt;runThreadTask()&lt;/strong&gt;, &lt;strong&gt;runFinalTask()&lt;/strong&gt; to execute our tasks and &lt;strong&gt;getBatchIdentifiersRangeCon()&lt;/strong&gt; to create a list of intervals - in our case it will be ranges &lt;strong&gt;FromRecId..ToRecId&lt;/strong&gt; for the selected transactions. Method &lt;strong&gt;getBatchIdentifiersRangeCon()&lt;/strong&gt; is the most complex and new in this example, all others are just a copy of original methods.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;DEVTutorialBatchMultipleThread&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;extends&lt;/span&gt; DEVTutorialBatchMultipleThreadBase
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;runStartTask&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;//1. data preparation&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;strFmt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;%1 - Start operation&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token named-parameter punctuation&quot;&gt;AifUtil&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;applyUserPreferredTimeZoneOffset&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token named-parameter punctuation&quot;&gt;DateTimeUtil&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;utcNow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;runThreadTask&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;//2. Query Processing&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;QueryBuildDataSource&lt;/span&gt;  qBDS &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; queryRun&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;dataSourceTable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;tablenum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;CustTrans&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    qBDS&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addRange&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fieldnum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;CustTrans&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; RecId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;batchIdentifier&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;queryRun&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;CustTrans&lt;/span&gt;   custTrans &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; queryRun&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;tablenum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;CustTrans&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;processRecord&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;custTrans&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;runFinalTask&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;//3.final task&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;strfmt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;%2 - %1 record(s) processed&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token named-parameter punctuation&quot;&gt;SysQuery&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;countTotal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;queryRun&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;token named-parameter punctuation&quot;&gt;AifUtil&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;applyUserPreferredTimeZoneOffset&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token named-parameter punctuation&quot;&gt;DateTimeUtil&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;utcNow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;container&lt;/span&gt;  &lt;span class=&quot;token function&quot;&gt;getBatchIdentifiersRangeCon&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;container&lt;/span&gt;  res&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;QueryRun&lt;/span&gt;   queryRunLocal &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;QueryRun&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;queryRun&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token class-name&quot;&gt;QueryBuildDataSource&lt;/span&gt;   qBDS &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; queryRunLocal&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;dataSourceTable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;tablenum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;CustTrans&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;/span&gt;                    totalRecords&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; curRecord&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; recordsPerBatch&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;RecId&lt;/span&gt;                  fromRecId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; toRecId&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    qBDS&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sortClear&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    qBDS&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addSortField&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fieldnum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;CustTrans&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; RecId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;qBDS&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addRange&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fieldnum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;CustTrans&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; RecId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;batchIdentifier&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    totalRecords &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; SysQuery&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;countTotal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;queryRunLocal&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    recordsPerBatch &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; maxTaskCount &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;?&lt;/span&gt; totalRecords &lt;span class=&quot;token class-name&quot;&gt;div&lt;/span&gt; maxTaskCount &lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; totalRecords&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;       &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt; recordsPerBatch&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        recordsPerBatch &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;queryRunLocal&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;CustTrans&lt;/span&gt;   custTrans &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; queryRunLocal&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;tablenum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;CustTrans&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt; fromRecId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; fromRecId &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; custTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;RecId&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        curRecord&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        toRecId &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; custTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;RecId&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;curRecord &lt;span class=&quot;token class-name&quot;&gt;mod&lt;/span&gt; recordsPerBatch&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            res &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; SysQuery&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fromRecId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; toRecId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            fromRecId &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            curRecord &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;curRecord &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; fromRecId &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; toRecId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; res &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; SysQuery&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fromRecId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; toRecId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In a user interface we added a new field &lt;strong&gt;&quot;Number of batch tasks&quot;&lt;/strong&gt; to specify how many tasks to create.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 606px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/1321152569fc99ffb0b0a1e8be7000e1/4d4a2/MultipleThreadBatch.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 103.42857142857143%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAVCAYAAABG1c6oAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACTElEQVR42p1VW5LaMBDk/gfYk+Qm+YFKAQuYl238lmVbtjo9ssXikFRYVNUlYUmt1vSMWJxOJyyXS+z3e6xWK2w2G6zXa9fneY6iKP4LWaeUwvF4xKKqKmit0XWd+1jXtYOMrbV4pfl1WZZh4QnkJOn/XCgwPLTjYkMlvnfjNEXPg4eJMEmSkVBUppwsy/L59KZB9fmJ8npFdT6julxQMkwyVmEItd3CGuPWCocjFKK2be+K+r53IZA2UEHDjTEVHY4BAhJFtxsu/Ga4tuXvgXvvV5b4icIzJ4RcyJzqSa0jpLqcv2VDymtFJPMHaqqdEforSwxFskAmZgpJ6O0ZhsGZ6FtDZ58IfZOF4u4shoxPxZRS3OhRP4wV5ywPmRH6azfS82qPCpwqkvY0p6cSgZl6wcAQ+bS5m5IkGeI45rVzhGIAx99p9jFtRFVD11MlDuOt9pTYouhwOEDKMAgCllDw15x8mVA2azGHE+KiwH5D7oxQDBiGnondoGOQu45BN53Lx7cVKjqc55kzpWm0U+pT4U2FFh1Tw0jJGSm7cdzz+ysw/Xj4LWHaZIViWdUOaVYiIdKclVNptMa+hKZj3El4jZg2SVYhSaXsckRxgmsYMRdjZHkJOXjEoyI8wfTjlWPud1cuGLZLPqCoLeLCotJ0m2uaSQGjgO4OCc8XHhWG8VQpUUJTipLmlHTYzMuOGTA+8xlqV+d2wj9MkbL7+BHh568IRXaDqjVqPUKzfoVsy0d0t9u5/xn575GnTh4Ryd+KveLalq/TNQzxG3XfY6oivF7tAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Multiple Thread Batch&quot;
        title=&quot;&quot;
        src=&quot;/static/1321152569fc99ffb0b0a1e8be7000e1/4d4a2/MultipleThreadBatch.png&quot;
        srcset=&quot;/static/1321152569fc99ffb0b0a1e8be7000e1/4edbd/MultipleThreadBatch.png 175w,
/static/1321152569fc99ffb0b0a1e8be7000e1/13ae7/MultipleThreadBatch.png 350w,
/static/1321152569fc99ffb0b0a1e8be7000e1/4d4a2/MultipleThreadBatch.png 606w&quot;
        sizes=&quot;(max-width: 606px) 100vw, 606px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;if we run our function in a batch mode, we will see the following result&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/76b4bf703bd4d1d43db460e955ebc631/0b79a/MultipleThreadResult.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 57.14285714285714%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABqUlEQVR42n2S644TMQyF+/7vBlSwF37AdtBuO/eZJM5lks70YLuqoFQi0pETJ/5sJ9nVpyMOVYWqOqCuT+j7Dl3bYBpHePIsupNzDuPkYK3T9ThNCDEipYScM3bN6aSgoe9B5EDOwllzp5uP3HXuiaXWYZ4NfAiIDF0E2PcDO2eEQAjea6BkDsGrIovctZrg6brPVuBqOYZkj4G5MDAvCxbW+XzGtm3cir0e4KyeD0vmm13XVf0ySimacObWDccIQ9reFaZK7wK8XC4KNMZo1cbMdwkkoQTKkHlKUa3E3cau5HugMVfgDfpfIFf979AKBSrtCFDvzpPeqVy+c1YfS9bbtiIvSQOlANl7AHZTQjvyXVBR7b++4fP+Jz59+YH9tzcMk0HH+80QYMOGwSyIBTwv+uIPwPd6xvtxQNvNaDqDl9cKzy8HPD0f8Pr9l7Y+zh79FNgGth6TCSzih/KPwH60aAf+Lj7zIQ9LESFlUMyIeVWYcUH9lhIcS6xxkYHhETjMER8tZ6UV3RRR94TJFa4kguPQcLvH1uKj4UrZT/wmLknLf77Q38DfIm5PoEwhipEAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Multiple Thread Result&quot;
        title=&quot;&quot;
        src=&quot;/static/76b4bf703bd4d1d43db460e955ebc631/8c557/MultipleThreadResult.png&quot;
        srcset=&quot;/static/76b4bf703bd4d1d43db460e955ebc631/4edbd/MultipleThreadResult.png 175w,
/static/76b4bf703bd4d1d43db460e955ebc631/13ae7/MultipleThreadResult.png 350w,
/static/76b4bf703bd4d1d43db460e955ebc631/8c557/MultipleThreadResult.png 700w,
/static/76b4bf703bd4d1d43db460e955ebc631/e996b/MultipleThreadResult.png 1050w,
/static/76b4bf703bd4d1d43db460e955ebc631/0b79a/MultipleThreadResult.png 1331w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;In this case, we got the total execution time of 30 sec, but values less than a minute are more related to the batch processing.&lt;/p&gt;
&lt;h2 id=&quot;summary&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#summary&quot; aria-label=&quot;summary permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Summary&lt;/h2&gt;
&lt;p&gt;I described how easily you could implement multithreading in &lt;strong&gt;RunBase&lt;/strong&gt; framework and convert the existing single-threaded task to the multi-threaded one. One note for this - use this approach only after you have performed all possible optimizations for the original code, running non-optimal code in multiple threads can create some problems. Also, the described solution is compatible with Ax2009 and AX2012 so that you can use exactly the same approach.&lt;/p&gt;
&lt;p&gt;You can download all classes used in this post from the following links &lt;a href=&quot;https://github.com/TrudAX/XppTools/blob/master/DEVTutorial/DEVTutorial/AxClass/DEVTutorialBatchSingleThread.xml&quot;&gt;DEVTutorialBatchSingleThread&lt;/a&gt;, &lt;a href=&quot;https://github.com/TrudAX/XppTools/blob/master/DEVTutorial/DEVTutorial/AxClass/DEVTutorialBatchMultipleThreadBase.xml&quot;&gt;DEVTutorialBatchMultipleThreadBase&lt;/a&gt;,  &lt;a href=&quot;https://github.com/TrudAX/XppTools/blob/master/DEVTutorial/DEVTutorial/AxClass/DEVTutorialBatchMultipleThread.xml&quot;&gt;DEVTutorialBatchMultipleThread&lt;/a&gt; . If you find that something is missing or can be improved, don&apos;t hesitate to leave a comment.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Addin to generate Data provider and Controller class in X++]]></title><description><![CDATA[The post describes a utility that generates X++ code template for Data provider and Controller classes.]]></description><link>https://denistrunin.com/d365utils-generatedp/</link><guid isPermaLink="false">https://denistrunin.com/d365utils-generatedp/</guid><pubDate>Wed, 17 Jun 2020 22:12:03 GMT</pubDate><content:encoded>&lt;p&gt;One of the most common applications of X++ SysOperation framework in D365FO is to build reports. In a common scenario, you need to create three classes: Contract, Data provider and Controller.&lt;/p&gt;
&lt;p&gt;To generate all three classes, I extended my &quot;&lt;strong&gt;TRUDUtils - DataContract class builder&lt;/strong&gt;&quot; Add-ins. You run it from the Dynamics 365 - Addins menu.&lt;/p&gt;
&lt;p&gt;Let&apos;s consider the following example - a contract class &lt;strong&gt;AATestReportContract&lt;/strong&gt; with 2 fields&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/e5465d77dcfeda53532f0e0c0fbef1cd/a016c/DataContractForm.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 42.285714285714285%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABv0lEQVR42m2S6W/TQBDF/f9/R6hfKIcAIQoIghRKUemRHrRJGpI2JVdJiOM4jnPYjm8nP8ZbISTESE+zq519+2beas5ixsy2FeazGWEQkKUJge+TxJFap0lCJvA8D8dxmU4tlo7HfB5h26HkBeOxIWcOWum8wvFZmcPTSw5OvnFxdU39tqv25VqT2k1b4brVk0tjDMPg7q7HaGQyHHroesBUxPQHAxaLBdrDZ+/ZevGBB0/fsfW8wPbOLo92PvPk7ReVXxVPeLN3QbFUx7IsUTMThTamaYriJWHo44ryQDrLs1ZttKg22rR+jmh2+pxVGtSaXb7f9mh2f1G96XB+1eRHT1ctTSYmrutiTSxRORLCmM1mQ5ZlCtpprcXu0SWFvWM+CvqDIYZpMbHnZBuI05QoSfGjhFUQEUcRkUIoZAGJzHa9XiuyPGvFUoOXhUO2X3/isaDd6mCMDJbLpSr4E6lc8MPcGJeBzEvNU+p0XRelhphj37d8UO1SqvfZr3Q4qnbUfFzXUY6mou4v4RrPD9VPMMemIsgNsqypql2tVgRhiPZViPbLbUVYqvWIpYX/xb3CmCjMv8lcOfrvo3n8BhcuTEktRVqOAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Data contract form&quot;
        title=&quot;&quot;
        src=&quot;/static/e5465d77dcfeda53532f0e0c0fbef1cd/8c557/DataContractForm.png&quot;
        srcset=&quot;/static/e5465d77dcfeda53532f0e0c0fbef1cd/4edbd/DataContractForm.png 175w,
/static/e5465d77dcfeda53532f0e0c0fbef1cd/13ae7/DataContractForm.png 350w,
/static/e5465d77dcfeda53532f0e0c0fbef1cd/8c557/DataContractForm.png 700w,
/static/e5465d77dcfeda53532f0e0c0fbef1cd/a016c/DataContractForm.png 762w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h3 id=&quot;data-provider&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#data-provider&quot; aria-label=&quot;data provider permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Data provider&lt;/h3&gt;
&lt;p&gt;To generate a template code for a data provider class you need to specify &quot;y&quot; for &quot;&lt;strong&gt;Generate report DP(y)&lt;/strong&gt;&quot; parameter and specify a data provider table(better to use TempDB table here).&lt;/p&gt;
&lt;p&gt;The following class with 2 methods - &lt;strong&gt;getReportDataTmp()&lt;/strong&gt; and &lt;strong&gt;processReport()&lt;/strong&gt; will be generated&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token attribute&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;SRSReportParameterAttribute&lt;/span&gt;&lt;span class=&quot;token attribute-arguments&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;classStr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;AATestReportContract&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;SRSReportQueryAttribute&lt;/span&gt;&lt;span class=&quot;token attribute-arguments&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;queryStr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LedgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;//Change query&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AATestReportDP&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;extends&lt;/span&gt; SrsReportDataProviderPreProcessTempDB
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;TmpLedgerConsTrans&lt;/span&gt; tmpLedgerConsTrans&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token attribute&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;SRSReportDataSetAttribute&lt;/span&gt;&lt;span class=&quot;token attribute-arguments&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;tableStr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;TmpLedgerConsTrans&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;TmpLedgerConsTrans&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getReportDataTmp&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;select&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; tmpLedgerConsTrans&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; tmpLedgerConsTrans&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;processReport&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;AATestReportContract&lt;/span&gt;   reportContract&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;Query&lt;/span&gt;           query&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        reportContract  &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parmDataContract&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        query           &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parmQuery&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;//populate tempdb table here..&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;controller&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#controller&quot; aria-label=&quot;controller permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Controller&lt;/h3&gt;
&lt;p&gt;In order to generate a sample controller class, you need to specify &quot;y&quot; for &quot;&lt;strong&gt;Generate report controller(y)&lt;/strong&gt;&quot; parameter.&lt;/p&gt;
&lt;p&gt;In this case, the following class will be generated&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AATestReportController&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;extends&lt;/span&gt; SrsReportRunController
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;prePromptModifyContract&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;AATestReportContract&lt;/span&gt;      contract&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        contract &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parmReportContract&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parmRdpContract&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AATestReportContract&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;//handle external record&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;args &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt; args&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; args&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;dataset&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;tablenum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;CustGroup&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;strfmt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;@GLS110030&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;tablestr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;CustGroup&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;CustGroup&lt;/span&gt; custGroup &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; args&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;//contract.parmGroupId(custGroup.GroupId);&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;//Query query = this.getFirstQuery();&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt; main &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Args&lt;/span&gt; args&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;AATestReportController&lt;/span&gt;         reportController&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        reportController  &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;AATestReportController&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        reportController&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parmArgs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;args&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        reportController&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parmReportName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ssrsReportStr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;SalesInvoice&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;Report&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        reportController&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parmShowDialog&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        reportController&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;startOperation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;After generation, you need to modify a code according to your needs. Addin allows you to do less typing and focus more on report logic.&lt;/p&gt;
&lt;p&gt;If you are new to SSRS reports development, Docentric has a great post &lt;a href=&quot;https://ax.docentric.com/create-a-new-custom-ssrs-report-in-d365fo/&quot;&gt;Create a new custom SSRS report in D365FO&lt;/a&gt;. Also &lt;a href=&quot;https://www.microsoft.com/en-in/download/details.aspx?id=27725&quot;&gt;Microsoft Dynamics AX 2012 White Paper: Report Programming Model&lt;/a&gt; provides some development examples.&lt;/p&gt;
&lt;h2 id=&quot;summary&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#summary&quot; aria-label=&quot;summary permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Summary&lt;/h2&gt;
&lt;p&gt;You can download this &quot;&lt;strong&gt;DataContract class builder&lt;/strong&gt;&quot; from the following link &lt;a href=&quot;https://github.com/TrudAX/TRUDUtilsD365/releases&quot;&gt;https://github.com/TrudAX/TRUDUtilsD365/releases&lt;/a&gt;. If you find that something is missing or can be improved, don&apos;t hesitate to leave a comment.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[How to create a new design for a Sales Invoice report in D365FO]]></title><description><![CDATA[In this post, I'll try to describe how to create a new Sales Invoice report design using SSRS and X++]]></description><link>https://denistrunin.com/xpptools-reportsalesinvoice/</link><guid isPermaLink="false">https://denistrunin.com/xpptools-reportsalesinvoice/</guid><pubDate>Wed, 10 Jun 2020 20:12:03 GMT</pubDate><content:encoded>&lt;p&gt;Creating a new Sales Invoice report design using SSRS and X++ is quite a common task. In this post, I&apos;ll try to describe how you can do this in Dynamics 365 Finance and Operations.&lt;/p&gt;
&lt;h2 id=&quot;sales-invoice-report-development&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#sales-invoice-report-development&quot; aria-label=&quot;sales invoice report development permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Sales Invoice report development&lt;/h2&gt;
&lt;p&gt;I will use &quot;DEVTutorial&quot; prefix for new elements&lt;/p&gt;
&lt;h3 id=&quot;data-provided-class&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#data-provided-class&quot; aria-label=&quot;data provided class permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Data provided class&lt;/h3&gt;
&lt;p&gt;Let&apos;s start with a data provider. We should create a new class and extend it from the standard &lt;strong&gt;SalesInvoiceDP&lt;/strong&gt;. In this case, we can add additional fields that are relevant only for our report.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token attribute&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;SRSReportParameterAttribute&lt;/span&gt;&lt;span class=&quot;token attribute-arguments&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;classStr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;SalesInvoiceContract&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;DEVTutorialSalesInvoiceDP&lt;/span&gt;  &lt;span class=&quot;token return-type class-name&quot;&gt;extends&lt;/span&gt; SalesInvoiceDP
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;populateSalesInvoiceTmp&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;CustInvoiceJour&lt;/span&gt; _custInvoiceJour&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;CustInvoiceTrans&lt;/span&gt; _custInvoiceTrans&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;TaxSpec&lt;/span&gt; _taxSpec&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;CustPaymSchedLine&lt;/span&gt; _custPaymSchedLine&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;CustTrans&lt;/span&gt; _prepaymentCustTrans&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;TaxTrans&lt;/span&gt; _prepaymentTaxTrans&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;_custInvoiceJour&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _custInvoiceTrans&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _taxSpec&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _custPaymSchedLine&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _prepaymentCustTrans&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _prepaymentTaxTrans&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//populate additional fields in salesInvoiceTmp here&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//salesInvoiceTmp.MyField = &apos;&apos;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//this method is called for main lines and also for all linked tables&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//please note, that it will not be called if there are already some data exist in salesInvoiceTmp table for the selected Sales order, you need to delete existing records   }&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;populateSalesInvoiceHeaderFooterTmp&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;CustInvoiceJour&lt;/span&gt; _custInvoiceJour&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CompanyInfo&lt;/span&gt; _companyInfo&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;_custInvoiceJour&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _companyInfo&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;//populate additional fields in salesInvoiceTmp here&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;//salesInvoiceHeaderFooterTmp.MyField = &apos;&apos;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;report-design&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#report-design&quot; aria-label=&quot;report design permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Report design&lt;/h3&gt;
&lt;p&gt;Then add a new SSRS report to our project&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/0f5f0c8c368bd26d3984190e0095515b/65c7b/CreateNewReport.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 50.857142857142854%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABzklEQVR42l1SCXLbMBDT/5/XNtMmsePYOqyDpHhIoqgLBemJe2gGQ4rLBbC7zN4vJc7nHHnR4sL96XTD57VC3SgUZQ2lHcJ6YJo3OOcwTRP3O3z4g8mv8PPCNSD7uNX49XrGiaRtq2HdjLrt8fLzRJEa2gwwboBUlv8FYw1qYVHVEsVdoGp6lLVgrEJR1cjmZYPsOnTENA7ECCkVfnz/BqUktKaItXQ2Yl1XhGWB9xO6tkXT1DTRMpf3eg3He4lQCAEpJBM27PvO0kbcbjcMA90ZQ2KFEAK+vv04MLD82AKtDauw6fzgebZsB1oqFXmBbdtSwPsZeZ6nBMMERcfzPD/Yjki4w1LIMtbTmTbuKZYFEr69nVFVTWr4vh//EOq+T4j7p0NWEdsQ3ff6P8KHw4aK9nkYCQsOIJYcexgRnUZS730qLfYrkj5K/ovw3nF6ZcdJSSjjYYYFQjlcr9dUVuxfdBiT41A24qDD5I7nfW8wjP6rG8iuzYiqG3GXHpWYULYT2n5KU42JCwnMGOD8gnE5MPLdWb9x2hud7qnvUejp8OXU4P3S4VJorgJvHw3On3wKasAwbdBuxV0FCgYKElxLMUPa9RG3C+puIFzCb72d/TP/8j2GAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Create a new report&quot;
        title=&quot;&quot;
        src=&quot;/static/0f5f0c8c368bd26d3984190e0095515b/8c557/CreateNewReport.png&quot;
        srcset=&quot;/static/0f5f0c8c368bd26d3984190e0095515b/4edbd/CreateNewReport.png 175w,
/static/0f5f0c8c368bd26d3984190e0095515b/13ae7/CreateNewReport.png 350w,
/static/0f5f0c8c368bd26d3984190e0095515b/8c557/CreateNewReport.png 700w,
/static/0f5f0c8c368bd26d3984190e0095515b/65c7b/CreateNewReport.png 795w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;We need to add Datasets for this report. In the standard system we have 4 sales invoice datasets, let&apos;s add them all.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dataset name&lt;/th&gt;
&lt;th&gt;Query&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;SalesInvoiceDS&lt;/td&gt;
&lt;td&gt;SELECT * FROM DEVTutorialSalesInvoiceDP.SalesInvoiceTmp&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SalesInvoiceHeaderFooterDS&lt;/td&gt;
&lt;td&gt;SELECT * FROM DEVTutorialSalesInvoiceDP.SalesInvoiceHeaderFooterTmp&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SalesInvoiceLocalizationDS&lt;/td&gt;
&lt;td&gt;SELECT * FROM DEVTutorialSalesInvoiceDP.SalesInvoiceLocalizationTmp&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DocuBrandDetailsDS&lt;/td&gt;
&lt;td&gt;SELECT * FROM DEVTutorialSalesInvoiceDP.SysDocuBrandDetailsRegular&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;At the end you should have something like that:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/eece8136d9187ca0412e1bc647afcf32/e35ec/ReportDatasets.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 30.857142857142854%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABTElEQVR42nWPy0sCYRTF/Vdr22MXEW0iKoigZRhEEi6iKEIMgnYV4nt0LHPCRz7H0c9njkY6M78+jdpUB34cLtx7ONd1eOLj+jbE1U2Ac/89R14fbs8FB8cX7B94uPKdcXZ5ysbuHmub26xv7bCwssrcwhLzi8u/cD1rWQy9Qr/XZTL+wJpMsMZjpkomw6QUP+XCHfVqlEEvg9nXZv4frsxLAVVVUeIJ0ukMudwr/TcTy4ZIVOEhEORZ7uSKHcq1AZX6kKox+hdXMJJCTT6RzRZ5LVap1poI0aPdfiMcS1PM5em2BN1OB9McyN4OtjXBsa0/kQ3z8mVdLpt8y3GcmSuqRiiRQau00fJlEokk8biCXjcYjd7lzfCHwcxlw4psNJVlWbOgaZZtfwXGHgt4gzrucI87TSAMnVKpTN0wEK0WLYkQkqag0WjIuc0nDSipSbblfPwAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Add dataset&quot;
        title=&quot;&quot;
        src=&quot;/static/eece8136d9187ca0412e1bc647afcf32/8c557/ReportDatasets.png&quot;
        srcset=&quot;/static/eece8136d9187ca0412e1bc647afcf32/4edbd/ReportDatasets.png 175w,
/static/eece8136d9187ca0412e1bc647afcf32/13ae7/ReportDatasets.png 350w,
/static/eece8136d9187ca0412e1bc647afcf32/8c557/ReportDatasets.png 700w,
/static/eece8136d9187ca0412e1bc647afcf32/e35ec/ReportDatasets.png 861w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h3 id=&quot;report-design-1&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#report-design-1&quot; aria-label=&quot;report design 1 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Report Design&lt;/h3&gt;
&lt;p&gt;Then let&apos;s add a new Precision Design(Report)&lt;/p&gt;
&lt;p&gt;Modify its properties: Size to standard &lt;strong&gt;A4 210x297mm&lt;/strong&gt; and all Margins to &lt;strong&gt;0&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 336px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/8acc7b6d18e82a8947f13cb17fc86468/d99f2/ReportProperties.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 140%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAcCAYAAABh2p9gAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAEOUlEQVR42p1WXW/bZBT2P+GKCwR/g/tJ/IPBBZeIu90gMSEBm2j3gQaMFug6SiXUCyoKlcoQMARjaZs2cT4cf8RxbMdOYid2EsfO18N57aQkbbOhWXqU18n7Hj/POc85DvfGW9fx7vtf4Z33vsTb1+7hytXruPLmBy8M7sbtTTz+O43f/0yhIJShqDWUZP2Fwa1vbENTjnCaycJxO2h7HXSDCN3eFNN1Lxgk6yBZLwO3cvcO5PwOfv71MQ7+KmH/0RMc5YwYx3kzRrpQwzHdp2l9yOtIZatLwa1t/oAoaEFRKqhoJioVHUq5inJZgygpyOUEFAsSVPpeKMloOj76IWMTXQpu7eEeBmEIsVSEUCxBkSSCjFyWh2XZ6HQ6cBoN+PTZbrURRQM86+LWv93DZDiATEGKeYGYKijmClDVCqJBcngymcT4Pxd3b30HDWLC80Wo5QokkqmS3EbTRUhs+kGYoB8hJKmMYRQNMRgM43UYRgvgbn2+jbKs4ODgEapVE57Xg+t6aDZaJLEb3/t+ANt2YBh2/H2j7qJO967rx7/PI5bcabco8QWUhBJkkUkvUh6VmMXsajab0PUqPbQKldIiChIcxz1LyZnkj259A0OrxDmUCJqqQSurVGGRKpocGI/HGA6HGI3GC/mcrefB3bjzALWqhgKxEgUBoiiiRYFYAIbZYafRRJ72sKrPHrI0oGXoJJVklMQ4YJ9sNGPADrKr7bK0FNFue88LuAGTJCtUGEmUkONzsGr2f4emAb2WR7lTp3mdLA/44erXsEwjZieRqWs1i2zSv5CjiCzR6/WSzM9Z8kLAm3c30bBtClYm/6nQjRpc1hHEZDSeTAEE9BCb9rFqu64DTauSVxvEeNH83O0vttH3PZKtwlQV2KaOes2gig4XLNGo2/jnaQr5HE9dVIYky7GisL+ohtvY2oMRALvHOjZ+OsQvRRdP9CH+UHpTdPGbEiBfqVN+M0ilnqLtd5bbZuu7XVzbr+O1FQlXdyy8fr+Cl2+KeOUTOcarKzJe+ljB6r4AuZDFKQ0NVmlWFCb3khw+IPcbSJ0WkM4KaPohutEEnXAcw++PEJB6TTeQyWaRy+eR5XlimwWfy1/slPsbu/GiRl7UVHVauvG0lOypiW1Majs+XyBmIxoKUczuUoazgAYxYGOLTYz5/MyMbdIDi2St84yWBrRME1pFS3jNbZgFrDGvkvlnhl9q7LXNH6eSDEglCb7ngxE4H1Cnfuep9Z7L8NO17xH1A2hVHQVqu5ppTTeOFwIy87Mi+J4Hr92GQYpcNxkiCz5c/WyLGt+BQLOQzcHOtL3OM3SpQ46OjumlxdMLTKEXlogSGyTnjb32MJFcp07IpE/IY/7CNDkL6Dg4OT2loIfwnmXsWVFseq9kjk+omolkNkzHrI9HScC6ZeEonUY2k6E/A358eDQaxXvm8S+W/g0UZA9+OgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Report Properties&quot;
        title=&quot;&quot;
        src=&quot;/static/8acc7b6d18e82a8947f13cb17fc86468/d99f2/ReportProperties.png&quot;
        srcset=&quot;/static/8acc7b6d18e82a8947f13cb17fc86468/4edbd/ReportProperties.png 175w,
/static/8acc7b6d18e82a8947f13cb17fc86468/d99f2/ReportProperties.png 336w&quot;
        sizes=&quot;(max-width: 336px) 100vw, 336px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Add the following sections&lt;/p&gt;
&lt;h3 id=&quot;header-section&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#header-section&quot; aria-label=&quot;header section permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Header section&lt;/h3&gt;
&lt;p&gt;For the header, let&apos;s add a logo from Document branding&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;vb&quot;&gt;&lt;pre class=&quot;language-vb&quot;&gt;&lt;code class=&quot;language-vb&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;First&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Fields&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;Image1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Value&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;DocuBrandDetailsDS&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;and some client information&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;vb&quot;&gt;&lt;pre class=&quot;language-vb&quot;&gt;&lt;code class=&quot;language-vb&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;First&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Fields&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;SalesId&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Value&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;SalesInvoiceHeaderFooterDS&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;   &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt; vbcrlf &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;  
First&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Fields&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;InvoiceDate&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Value&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;SalesInvoiceHeaderFooterDS&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt; vbcrlf &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;
First&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Fields&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;InvoicingAddress&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Value&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;SalesInvoiceHeaderFooterDS&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;line-section&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#line-section&quot; aria-label=&quot;line section permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Line section&lt;/h3&gt;
&lt;p&gt;Add a new Tablix control with &lt;strong&gt;SalesInvoiceDS&lt;/strong&gt; dataset&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/782542f79ce7c70ce2f86114ba9653e4/fd28b/LineTablix.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 64.57142857142857%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACDUlEQVR42q1S227TQBD1b/LKR/AF5QlQHyrUNgKEuKkSAlIq8VCpj7whIVASSMjFsR05sRvfvb6s7cPMxg4CqTwg1jqe2Z3dM2dmVxsP3uPblz5+jC4wGZ5j9LUPa/EBl1cXOHryFr0XfRw9fo17x69w8uwdTp/38fDpGxyTz/PD3hnuHj7Cwf0THDw4hZblBdA0hNYQ6npn/2VoaSogpSQCZmjUx6NpfkdNvz/XdmhUrIOWigxlKfG/hpZlOaqqgh+ESmlVSbIliqJQfoeynZdl2e7ZrRVFrvbyGY6pHuaE8WSKIExQ1Q24DYuFjrygTbIiSOVzbL12ECcpWMh8rmM2ncM0LCVKCAEtTAQ8z4Oz2aDMM8pEATqcZoWyGbUjKyQEJWWf11PyRV4iETkiOh/EQvWPVWumE+BOf4bbZwvcemmg99GGiHx4vg+fwMl83yO7VX4URUiSZI84jokwVeWqkl0/xqeZg89WjIEjMV1HMJY6lgTLssguYVomdJob5LuuiyAIVLIOzrWHreephFqaS3hblxqcq1vi/i11nS4pQBKTClLAKuJWDSsMw3APJg9J4f6WDfsaBUlt2pfMjTWWhsrcEdwEJnRdB7brYU3YELTB6DtkVe8zCFZIpXG5nP1vhBw3TYPIqOxtAJegJfyw5a+HzQon4zGGwyF0Kn21Winym2DbNvildCX/BLwt14+sUxZlAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;LineTablix&quot;
        title=&quot;&quot;
        src=&quot;/static/782542f79ce7c70ce2f86114ba9653e4/8c557/LineTablix.png&quot;
        srcset=&quot;/static/782542f79ce7c70ce2f86114ba9653e4/4edbd/LineTablix.png 175w,
/static/782542f79ce7c70ce2f86114ba9653e4/13ae7/LineTablix.png 350w,
/static/782542f79ce7c70ce2f86114ba9653e4/8c557/LineTablix.png 700w,
/static/782542f79ce7c70ce2f86114ba9653e4/fd28b/LineTablix.png 811w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Adjust Row visibility to the following formula &lt;em&gt;&quot;=IIF(Fields!ItemId.Value = &quot;&quot;, true, false)&quot;&lt;/em&gt; as &lt;strong&gt;SalesInvoiceDS&lt;/strong&gt; may contain data from linked tables(like payment schedule)&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 583px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/a1229dbd19d16a789ce37ffad6277c7d/9fc4b/RowVisibility.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 29.714285714285715%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABKklEQVR42l2QW0+DMBiG+f//xUvjjV54s8RkomM6lHFwdEChHQXcCSi8tt3mok2evF/ffPlOVtu2kFJC9hJd1xn6vj958uT1XYvunHd5wzBckdfYonmBKIxAKQXnHIwxFIXyoghpmhkvoQwkK7BWmjFh2O0PppkeyOh5GOv+7gaPD7dwXQ9ZliFNElP8aTKBbdsghMDxFH4K+4NguoiVxojJGr7vIQgDLL1PhIGPpe/DSkiIklOUokLT1EhyjtWamqmKTQVW1jj2A1q1bTecaOWIersHE7WiMTk65uIb1uUm4zga1QlBECJXp9hudxBCqEYNjmq1w/Hwi/7/R69v6UIafVD9ci7gvruYvTpwZnM8T1/wNl8gXqk141JphdXXBklSqGY1yrL6ww+g3MU0w8sdiAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;RowVisibility&quot;
        title=&quot;&quot;
        src=&quot;/static/a1229dbd19d16a789ce37ffad6277c7d/9fc4b/RowVisibility.png&quot;
        srcset=&quot;/static/a1229dbd19d16a789ce37ffad6277c7d/4edbd/RowVisibility.png 175w,
/static/a1229dbd19d16a789ce37ffad6277c7d/13ae7/RowVisibility.png 350w,
/static/a1229dbd19d16a789ce37ffad6277c7d/9fc4b/RowVisibility.png 583w&quot;
        sizes=&quot;(max-width: 583px) 100vw, 583px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Let&apos;s also add a totals section. The resulting design should look like this&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/6cb2f7cd38378ad8a508ed23e02cf53a/7fee5/ReportResulting.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 52.57142857142857%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABbklEQVR42p1STU/CQBDt//8TiidFDgYFSdRE68ETHgxBPUHBfoXS1n7QdrvlObOkNTZogpO8zOx2Zt682WqepWNt6wgcHSvzHqGrI/Ke0O2PcHQ2wEnvGp3zITrse8NdTDhmdAc47d/i8uYRF6MH9K7uoKVZgbIESrmDoLgQwHaLf5kWRj4qWVIDiW21g5SSSKRKWC6XGI+fMZsbmE6nyud5gZXnQRC7rCrK/4ZW8ngtq1SSbOKiYBWl8qKsmxD5HhmaEKIpbOM342/tZnxmaJvNBmmSqAkYghaY0JknaBPwXZ7nyrPcJE4IMdWnKGgNfK/FUQTTtBpWQbLMD1MV8vlHUypwHbcht6iOc9nzOpTkejf1yIyiyPdK5rssy9QkaZriMwzVA3EcBAFYrfbXrtqmHpAIY5L5/voGh6ZVRPS6tmVjYSwOa8gPWMNfr+HYLioiyLKcGlow6Jc6eML6dwl8X+2e5RqzOSYvE9XwC4WWT3J3iIVqAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Report Resulting&quot;
        title=&quot;&quot;
        src=&quot;/static/6cb2f7cd38378ad8a508ed23e02cf53a/8c557/ReportResulting.png&quot;
        srcset=&quot;/static/6cb2f7cd38378ad8a508ed23e02cf53a/4edbd/ReportResulting.png 175w,
/static/6cb2f7cd38378ad8a508ed23e02cf53a/13ae7/ReportResulting.png 350w,
/static/6cb2f7cd38378ad8a508ed23e02cf53a/8c557/ReportResulting.png 700w,
/static/6cb2f7cd38378ad8a508ed23e02cf53a/7fee5/ReportResulting.png 781w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h3 id=&quot;connect-a-new-report-to-print-management&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#connect-a-new-report-to-print-management&quot; aria-label=&quot;connect a new report to print management permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Connect a new report to Print management&lt;/h3&gt;
&lt;p&gt;A sales invoice can be used in a Print management module. In order to connect our report to this module, we need to subscribe to two events(create 2 new classes):&lt;/p&gt;
&lt;p&gt;Update 25/11/2021. A more detailed description can be found in the following blog &lt;a href=&quot;https://ax.docentric.com/how-to-add-new-report-format-to-print-management/&quot;&gt;How to Add New Report Format to Print Management&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token attribute&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;ExtensionOf&lt;/span&gt;&lt;span class=&quot;token attribute-arguments&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;classstr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PrintMgmtReportFormatPopulator&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;final &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PrintMgmtReportFormatPopulatorDEVTutorial_Extension&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;   &lt;span class=&quot;token keyword&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;addDocuments&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addStandard&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token named-parameter punctuation&quot;&gt;PrintMgmtDocumentType&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;SalesOrderInvoice&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token return-type class-name&quot;&gt;next&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;addDocuments&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;final &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PrintMgmtDocTypeDEVTutorial_EventHandler&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;     &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token attribute&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;SubscribesTo&lt;/span&gt;&lt;span class=&quot;token attribute-arguments&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;classstr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PrintMgmtDocType&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;delegatestr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PrintMgmtDocType&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; getDefaultReportFormatDelegate&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getDefaultReportFormatDelegate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;PrintMgmtDocumentType&lt;/span&gt; _docType&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;EventHandlerResult&lt;/span&gt; _result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;   &lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;_docType&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; PrintMgmtDocumentType&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;SalesOrderInvoice&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                _result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ssrsReportStr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;DEVTutorialSalesInvoice&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Report&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;test-sales-invoice-report&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#test-sales-invoice-report&quot; aria-label=&quot;test sales invoice report permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Test Sales invoice report&lt;/h2&gt;
&lt;p&gt;That is all. It is time to test our report.&lt;/p&gt;
&lt;p&gt;Build and deploy the report. Then, before the test, you need to add it to the print management settings. In order to do this - run the following job&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;DEVTutorialPopulateReports&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;   &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Args&lt;/span&gt; _args&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        PrintMgmtReportFormatPopulator&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;construct&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;populate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

https&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;usnconeboxax1aos&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cloud&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;onebox&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;dynamics&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;com&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;?&lt;/span&gt;mi&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;SysClassRunner&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;cls&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;DEVTutorialPopulateReports&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Next step is to add a logo to our report. Go to the &lt;strong&gt;Document images&lt;/strong&gt; form and upload the image. Then go to the &lt;strong&gt;Branding details&lt;/strong&gt; form and select this image.&lt;/p&gt;
&lt;p&gt;To print the invoice go to the &lt;strong&gt;Accounts receivable - Invoice journal&lt;/strong&gt;, select &lt;strong&gt;Document - Original preview&lt;/strong&gt; and you should see our sample report:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/52e32f821e6e520926d5a196d314fad2/2e195/PrintedReport.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 76.57142857142857%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACcElEQVR42oVTTW/TQBDNLwMJ9cAFiRN3/gcnJH5DJQ5cEFz4AxzghNRWEFFVCU3iJP6KP9f2Zu21k4ZGesysYzdtDxxGs56dffPezHgQxgJpJlHXNTaNRq1L1JXCdqOxpW+ObZu78/9sUJYV1FpCyRwleVkUEKKAlAoiVyiVRCok8lxivS5Qlao3XZWPjACZUYlmt0dz85eCnFyC40q1d1rXpECjOVitK8NGV9VjQK01Pls13n/4iNNPXzEMdtg1LYMNPRZpgt/DIWazKUajK+NZRRAEpjAXuAfIPXt7CZy8eIWXr9/guwfc1tIw5IRSrZGJFEWRI88EyZaIogAX52eYTq4Rx9EDwO0N3p1+wbMnJ3j+9ATfzqa43W0ISBn5nMQS2fjMUvMshWvbSAgsjsI+p5dsjS7x6+IcP89+IPBcutQ0oLXxNfWJpXXGAywVAzemLaxgLdthMeigqStkWY6U1ud2v8dm00AkMeZzC8FqhShsGXRTzYQwANzbmO74PoljJFFE54ABNVICCKnJLJOtyDJ4rgN7sTReEVuOd57N9zwClmbSrIQBbXvZAnIlTuhkiTTFbDqFNZnA992DNHUP1KHHRZ6bM7/hXi7m8xYwDFYmoT7slUgSXI/H+DMeUWJ0KKT6nrF3HAbM+t75rosJTX3AH53kjmFOffIowfd9E+d1YWnMrmPIcd7HniGpdKk9reQ4NAB3khNTzZrNsFwsaO9C04ZjyR5tw7FkZmhZs5YhA4Q0oW45WQoXWPketcI2bLrVaCWXZrrMsJt+RDmOY9MePljczswO6rt/9/ieQVY0LHu56P+muWXBdWz8A5RiXdjOM2XiAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Printed report&quot;
        title=&quot;&quot;
        src=&quot;/static/52e32f821e6e520926d5a196d314fad2/8c557/PrintedReport.png&quot;
        srcset=&quot;/static/52e32f821e6e520926d5a196d314fad2/4edbd/PrintedReport.png 175w,
/static/52e32f821e6e520926d5a196d314fad2/13ae7/PrintedReport.png 350w,
/static/52e32f821e6e520926d5a196d314fad2/8c557/PrintedReport.png 700w,
/static/52e32f821e6e520926d5a196d314fad2/2e195/PrintedReport.png 782w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-future-of-ssrs-reporting&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#the-future-of-ssrs-reporting&quot; aria-label=&quot;the future of ssrs reporting permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;The future of SSRS reporting&lt;/h2&gt;
&lt;p&gt;There may be a question of what is the future of SSRS reporting. Considering the latest news, I think that its popularity may grow. Microsoft recently released &lt;strong&gt;Power BI Paginated Reports&lt;/strong&gt; that are completely based on SSRS &lt;strong&gt;&quot;rdl&quot;&lt;/strong&gt; files. Technically a new &lt;strong&gt;Power BI Paginated Reports Builder&lt;/strong&gt; is an old SSRS report builder with a new name(yes, another name change).&lt;/p&gt;
&lt;p&gt;Check, for example, this recent course &lt;a href=&quot;https://docs.microsoft.com/en-us/power-bi/learning-catalog/paginated-reports-online-course&quot;&gt;Power BI Paginated Reports in a Day course&lt;/a&gt;. Almost all its modules(except maybe 04) are relevant to D365FO development.&lt;/p&gt;
&lt;p&gt;And this Bear in the previous picture is not just a funny picture, it is an official mascot of Power BI &lt;a href=&quot;https://youtu.be/vu32LfckCt8?list=PL1N57mwBHtN1icIhpjQOaRL8r9G-wytpT&amp;#x26;t=7&quot;&gt;Paginated Reports&lt;/a&gt;. So with a new name and a new Bear, I hope the popularity of SSRS may grow.&lt;/p&gt;
&lt;h2 id=&quot;ssrs-reporting-issues&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#ssrs-reporting-issues&quot; aria-label=&quot;ssrs reporting issues permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;SSRS reporting issues&lt;/h2&gt;
&lt;p&gt;If you watch this  &quot;Power BI Paginated reports Day &lt;a href=&quot;https://docs.microsoft.com/en-us/power-bi/learning-catalog/paginated-reports-online-course&quot;&gt;course&quot;&lt;/a&gt; you may feel that SSRS is cool(presentation is really great). However, the last main update for Report Builder was 10 years ago and the current version has some issues. Just some of them:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&quot;rdl&quot;&lt;/strong&gt; file is a very complex XML format. So in most cases, you will not be able to compare changes in the report - by using text compare you will see a huge number of differences in XML structure even for a small design change.&lt;/li&gt;
&lt;li&gt;Page splitting is very basic. For example, if you have a data row that consists of multiple lines and you want to avoid page breaks inside this row, you may find that this is not supported and you need to develop your own page grouping solution.&lt;/li&gt;
&lt;li&gt;You can&apos;t define a section that prints something on the footer of the last report page(and it is a quite popular requirement for reports - often it contains some bank payment information). There is a workaround for this if your report has 1 or 2 pages - you can put this information on page footer and hide the element using &lt;strong&gt;Globals!PageNumber&lt;/strong&gt; and &lt;strong&gt;Globals!TotalPages&lt;/strong&gt; variables, but if a report has 3 or more pages this will leave an empty space on these pages.&lt;/li&gt;
&lt;li&gt;Report designer doesn&apos;t support formulas for defining Width property.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So there are a lot of things that can be improved, and I hope Microsoft will invest in it.&lt;/p&gt;
&lt;h2 id=&quot;summary&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#summary&quot; aria-label=&quot;summary permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Summary&lt;/h2&gt;
&lt;p&gt;Real-life invoice reports can be quite complex and require a lot of efforts to create them. However, as we see, creating a simple &lt;strong&gt;Sales Invoice design&lt;/strong&gt; is not a complex task. You can use the project above as a starting point(another option to consider is to install modern design &lt;a href=&quot;https://docs.microsoft.com/en-us/dynamics365/fin-ops-core/dev-itpro/analytics/install-modern-report-design-templates#apply-the-modern-designs&quot;&gt;templates&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;If you have some hints for SSRS report development, don&apos;t hesitate to post a comment. The project used in this post can be downloaded from my &lt;a href=&quot;https://github.com/TrudAX/XppTools/tree/master/DEVTutorial/DEVTutorialReports&quot;&gt;GitHub&lt;/a&gt;(you can download a model to a temporary folder and add elements from it to your project using &quot;Add - Existing item..&quot; command)&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Understanding D365FO Version control system and why it is different from AX2012]]></title><description><![CDATA[In this post, I describe some scenarios for Team Foundation Version Control usage in Dynamics 365 Finance and Operations and how it is different from AX2012.]]></description><link>https://denistrunin.com/d365fo-tfs/</link><guid isPermaLink="false">https://denistrunin.com/d365fo-tfs/</guid><pubDate>Wed, 27 May 2020 22:12:03 GMT</pubDate><content:encoded>&lt;p&gt;If you are developing in Dynamics 365 Finance and Operations, you need to use Team Foundation Version Control(&lt;strong&gt;TFVC&lt;/strong&gt;) system. It is not very complex, but its concept is different from what we have in AX2012.&lt;/p&gt;
&lt;p&gt;In this post, I describe some scenarios that may produce unexpected results if you don&apos;t fully understand &lt;strong&gt;TFVC&lt;/strong&gt; and use it in an &quot;old AX2012 way&quot;.&lt;/p&gt;
&lt;p&gt;On a typical AX2012 project, we usually have a common development application, where we are developing modifications, and when they are ready, we use import/export XPO file to transfer them on TEST application. Let&apos;s discuss how this may work in D365FO.&lt;/p&gt;
&lt;h2 id=&quot;initial-setup&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#initial-setup&quot; aria-label=&quot;initial setup permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Initial setup&lt;/h2&gt;
&lt;p&gt;Here is our project setup, I created two branches one for our internal development and testing(Trunk - &lt;strong&gt;Main&lt;/strong&gt;) and one for user testing - &lt;strong&gt;TEST&lt;/strong&gt;. &lt;strong&gt;TEST&lt;/strong&gt; is mapped to some temporary folder to allow merging.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 618px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/730245b9c6bc5d6e6ec892bf2c0f6d3e/6e6fb/InitialTFSSetup.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 74.28571428571428%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACeUlEQVR42p1UTW/TQBD1D65EOfBVVKkSVSukogI5wgUJgXrhwhUOcKlUStqqlCZtncSJHcff9vpjvf7IY3bTVlQIibLS0+yM1y8z+56j7X19iePDHRx8e4/93Tcw9I/4/OUD1jvvsPb8Le5tvsbDJx0srzzF0v1NLD16hrur21h+vKXiyvoLPFjbwupGBxvbr6Addnfx89zCSd+EMTRUPOmN0TsfoX8xxmjiwjRncP0IXhAjSjlYVsIPEoRRClGW4Hmmolxa9/AEGUtQFAVqUaDIE2RZijzPkaUMnutiZtvwfQ8szeExATfh8JJSwafcSQTyskZdV9D2u0fQdR1BEMKhl32KURSrvOBcwTQtDAZDuF6AiRtj4iwwskP86A9x3B9hMDJhz2bQRpMpojCAO7MUiVzz+VyhaRqUciRe0r5VNXp6jcWZSkF2V1U1NGNiK5KUxfCcKaZTF0GYqFrbtuBEKESFf13XhLwUsPQjfN8/gEFdXy3ZpRDi9oR5XsAeX9DoNjIS5L8JdWPRTSPHS2w4pGiaZjcIy9sQssRCxRlZxSWPlXDJayEjXzVAWc/BqxYFJXL/L9Du7Jyi82mAnLk0NkcYhsqDRcHRSrVv6PobLp0wvzpzGbW9QYyhzyFI8jKzyOQBPPJbSqY2LQtxHIMxpmIURUr5um6UjeReXskCVKeoiUbyyodUrEu1r6qGVL+0ivzl9sqDuK5JO0khORcql36VZzSPz9E1fFjjsVJXvsZ5gLNhH6dGACsWsNPmD+izGL2xhzOTvp6gwMWUJnUYEeYtjiZkarKLvLu6pR6rAI7Vg2G6f738MElJwAgO/WkkaYEwlnmCXx6UbkSnNGQKAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot; Initial TFS Setup&quot;
        title=&quot;&quot;
        src=&quot;/static/730245b9c6bc5d6e6ec892bf2c0f6d3e/6e6fb/InitialTFSSetup.png&quot;
        srcset=&quot;/static/730245b9c6bc5d6e6ec892bf2c0f6d3e/4edbd/InitialTFSSetup.png 175w,
/static/730245b9c6bc5d6e6ec892bf2c0f6d3e/13ae7/InitialTFSSetup.png 350w,
/static/730245b9c6bc5d6e6ec892bf2c0f6d3e/6e6fb/InitialTFSSetup.png 618w&quot;
        sizes=&quot;(max-width: 618px) 100vw, 618px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;case-1---why-my-code-doesnt-compile&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#case-1---why-my-code-doesnt-compile&quot; aria-label=&quot;case 1   why my code doesnt compile permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Case 1 - Why my code doesn&apos;t compile&lt;/h2&gt;
&lt;p&gt;let&apos;s do our first modification. Add a new EDT &lt;strong&gt;EDT_FieldA&lt;/strong&gt; and a new field based on this type to &lt;strong&gt;CustGroup&lt;/strong&gt; table&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 561px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/154ec159b8407440e1fdebdefc7da5f9/410f3/ModA.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 42.285714285714285%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABuUlEQVR42mWQ7WvTYBTF+0/7F/hBVPDLFCeIH8ZE0NF96FYGm2+oU4akadaYNjVp0yZP0vcma1aaNvn5JJtl4oEDD/c599x7T2l3r8K7yhfK1XMOjr7yuvyR/cOcH9g7OGN3/5hnr8o8ef6GxzsvqStlGuohWq1M1zrBsU+wzAq2ecS4/5ZSQzfo2m0cp4vr9hDCYzgIcPsOPVkTnovwfVl3qZ5+Q2n00E0PzehLeqh6H7XhyJove0xKIhgxm01oNlsEQcB0OiNNMzabVHJDsl6zWq3IcaH8QtebcojHaDjA9wSBHJZzsbhCtlGaTCPW6wTDMLjULqnXNTwpHE8m/EU+IMdPtYnT8+h0bNSaiqLU0Bu67NPou26hKY2nYfEYjkbYtk0wGLBKEu4izW4MFa3FPIqJr+b8bpuYbYsoioq/XJKzMEzTlI40y7cUQsgIZluTfw1NwmhBtl7Ic7v0rLakKS9cbbXbDT25su8HzMOwyO4uNrcnV89N7h3HPPh0zYvTNo/O5jx8H7LzPeHpBdz/fGuYZWlhaFkWlm0xkIEvl8v/MvxRa2GImOBaRhSnBDHFWyzAjW74B1I4SVJUCpAJAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot; Mod A&quot;
        title=&quot;&quot;
        src=&quot;/static/154ec159b8407440e1fdebdefc7da5f9/410f3/ModA.png&quot;
        srcset=&quot;/static/154ec159b8407440e1fdebdefc7da5f9/4edbd/ModA.png 175w,
/static/154ec159b8407440e1fdebdefc7da5f9/13ae7/ModA.png 350w,
/static/154ec159b8407440e1fdebdefc7da5f9/410f3/ModA.png 561w&quot;
        sizes=&quot;(max-width: 561px) 100vw, 561px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Commit our changes as &lt;strong&gt;ProjectA&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 359px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/0d98b31eb30a83b97962a7eadf92139f/f5eb6/CommitA.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 104%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAVCAYAAABG1c6oAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAC1UlEQVR42o1Ua5OiMBDk//+x+3R1D91dFEUERUgIEF7had8k6OqWu+emamoGAp2Z6c5YtrPFn4WNl7c1bMfDYmnj9+KV4h3yPMPpdEIURejaDnpN04Tz+fzB9Or7AbksYFWVAucpGBMQqUTbjyjVgKab0Haj8ZUaofoJ43gmwK9Ng1tCSKxXGzIXYcjQqA6+aBGkHRLZ4pRRLDqwYsAwzdn8b1mMMfjBEb4fIDxFGMZbSdPFTExg4zfMKqREEBzgeR6Ox9CcMhLoSL26At6X9MysfhghuKByI2qqRNf1BlBvGuA704Q8M0skCXzKjsURZXjAcrnExrFRFuWFVTrZZDg9HPBpyUzk+PF3h1+rAK4fYuEE+GkHePMFIjkiJjJi2RtSCOM5KVo/kaiQli1k2YClBbGrEKclYlEgZBlCLsHpfVnVqOsaVT37vu8fAcdxgMxzNE2NRn9cVmhVQ740z2UhKS5MC0raK8hLErCkfqu2NSAfSOGcw9u5pMM1XG+PlW1ju3Xhui4BX38gu/q7mNr6IG6rqFu87jMsvRR2ILDyIrzsOF79DG7cmN7143NB30om1JLKU1QmKeiiPZhbMegMvo91B5gnKPkOqqa+NQot9abrWnOIjpWid/Ss+6ya5rLfoSaSGvOsUFUVfdfCMpOCUpEZQyEO4HQV9XXMssyY1ilj3JAghECaakvnPaEHyhwn9F2e5TOgXm03oEpPKMiCw9HIAtfxdMa7f1ryPe16JQnH1tnQ7dnDWTvYbCje7xEej7QnZtY/mYnvsrll2CPnPmQSmh/jKDalSJlTts1DJpfzH5J+B5wuX3DOsPd2cLdb0uMOAWW3dbdwHIdG3AFxzKjP3BDwZcl64lQ5Q9vkZnrnmYAWvCYnDEPyMQ2PGFwTpD3t6exzumGaIE1Ylmly8lsPC5khDTfg0RExu2ahLrJoZ1OzhDotJXqvY03eVUZaNv8AWONYNB02T18AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot; Commit A&quot;
        title=&quot;&quot;
        src=&quot;/static/0d98b31eb30a83b97962a7eadf92139f/f5eb6/CommitA.png&quot;
        srcset=&quot;/static/0d98b31eb30a83b97962a7eadf92139f/4edbd/CommitA.png 175w,
/static/0d98b31eb30a83b97962a7eadf92139f/13ae7/CommitA.png 350w,
/static/0d98b31eb30a83b97962a7eadf92139f/f5eb6/CommitA.png 359w&quot;
        sizes=&quot;(max-width: 359px) 100vw, 359px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Then let&apos;s do our second modification - A new field to the same &lt;strong&gt;CustGroup&lt;/strong&gt; table based on a new EDT &lt;strong&gt;EDT_FieldB&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 555px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/23cb1b30fb22a442ccff31165a60e260/cd039/ModB.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 48%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACNElEQVR42nWSSW8TQRBG/ds4coIzUiSUY6QI5QCCC0FCKAIHLkgs/wAJkbAekpDN2E5iO6tnbI9ns2dsZjxeEyeOl5lHewkCIUr61NXV6ldVXR2auf+SmQdCYp2ee87UnTBTs0+5PRfmxvQ812/d49rNWZ69eMLXT4t8eB/m49Iika03RLffEo2M9UP4ka3XhOLJNIdpleRRjnhSInGYZXdfIp5KE02cENk55N3SCktfPmPoKfb3N5DlOEp+j0wmipTeJi1FccxlSlaCkKGrWMUClYqDJ1SrejjlEmWhn0LDvZzL8W1tF6NYI2+4aAUP1fTQzKqI1bGdNp7n4npnhMqOQyy2I7JlkbM5ut0+g0FAv+9zKXw/CHCrTSKxA0zdQNNUdLHKkoyuaaJaGbdSYWiDgU9IM2yisQSbWzusrG0jZQwkWUfTyximi2V7HByp7KUkepdtDFVByWZQMhKWqWObKvXqGBiI5KF+v49tWSKzhqIo2LZNs9mkJ+JX1mi0WE+q5KsBx6rF3rFC9LiAWetQvgCjCXp9rFCv18N1HQzDoCjAnU4H3/d/Zxza+WmLhWWVu6sQXq/yaqPE49U2C9/bPFwf8GgT5icaVWgVi5imKSpp0Gqd0p9UdwWs1VscSerIv2h6KPIJala8oZLFKRU4azWYXBgDS6LNIdCyrRGw2+3+C0yPgb4fjDoYHg3PB8IfDmO8n7RcKtliAIaYnk61VqPdPv8LWPHq4q/m/4gF/M9+AeaAzJH0I56zAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Mod B&quot;
        title=&quot;&quot;
        src=&quot;/static/23cb1b30fb22a442ccff31165a60e260/cd039/ModB.png&quot;
        srcset=&quot;/static/23cb1b30fb22a442ccff31165a60e260/4edbd/ModB.png 175w,
/static/23cb1b30fb22a442ccff31165a60e260/13ae7/ModB.png 350w,
/static/23cb1b30fb22a442ccff31165a60e260/cd039/ModB.png 555w&quot;
        sizes=&quot;(max-width: 555px) 100vw, 555px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;and then commit it to our &lt;strong&gt;Main&lt;/strong&gt; branch as &lt;strong&gt;ProjectB&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;These two modifications are logically not linked, so after the testing, we can decide to move only &lt;strong&gt;ProjectB&lt;/strong&gt; to the user test environment. It is a typical situation in AX2012, where you just export the project to XPO from DEV and load it into TEST(during the import you compare XPO with the existing code on TEST and transfer only relevant changes)&lt;/p&gt;
&lt;p&gt;Some people may think that in D365FO the system can transfer only the relevant changes automatically and compare is not needed.&lt;/p&gt;
&lt;p&gt;A typical mistake is to use &lt;strong&gt;Selected changesets&lt;/strong&gt; merge to do this. Let see how it works:&lt;/p&gt;
&lt;p&gt;You run a Merge command and choose &lt;strong&gt;Selected changesets&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/5c489b1079c3b1d4273425feae501e39/c8e86/SelectedChangeSet.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 78.28571428571428%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAYAAAAWGF8bAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACV0lEQVR42pVTyY7aQBTk//8kl4yySMkhp0xumURJmAkYGBZv3V5wLzbewK553YaJRkCiIBWv7abrVb8qRizk0Eohzwtk2y2SJEUcx0jTDPtDZ3HoCFS7vrfrdn+g939gns3e97GD0a/xA4SQ0FqhyHNIKeH7AXgiIFSBOBVIthJboWzNpEaUbKGKEoceaDuDHs2+R161GDHOwUMXjMVWxYE6alLrEulquUSuNRTdoCgK29Q0NO9M892uQLnb2b2OlJvPqKoatG2D5WyCzdpFXddo2j0kkZZliaqqoIhIE4EmIkMoqYE+NhJCIMtoPPu9JbWENR2K/Edwxom8tYQRzdDdbOB5HsIwhE/V93y4rouA1Hvu8JwkCSkcRmUwKqsaPTGL2LM/bJrGDjlgEZypg9VqZRuJTFhFSklbzWEhha3D+wGjsqzt3fvjV28GTApDmulivsCGVK5Xa0uaxAkhRhzFNgnqdHU9VIOXhKaS/XXTIs0k5rMZJpOJVTqlOnMcaxQLGZnISOFLdecKTaXrN+Q2W6wwfn2D8dv3+HnzBosPHxF+vQOPIjs3o5DzCBGBm6SwockFhZ29sh8EmN3/wOPkfsB8ToaYOfvDYTLKwKyNaWEQIiCcEXY0wwNF4GGT4NWtg3ffPHyapGCZpswVQ3wI+SVQHs8JaYYmOksu8Xka49ZJ8MWJwVIKdG4M0M8GXMJFU6q6oc0c7U4SlIWiiGQUYvEPXCXcypz+v4IgLaSQz+H9G64SZtKkX1w9eAr3qZ7W/01orsWOLk/dCHeOh99kYBRxG5snhz7Ajd84pFsAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;SelectedChangeSet&quot;
        title=&quot;&quot;
        src=&quot;/static/5c489b1079c3b1d4273425feae501e39/8c557/SelectedChangeSet.png&quot;
        srcset=&quot;/static/5c489b1079c3b1d4273425feae501e39/4edbd/SelectedChangeSet.png 175w,
/static/5c489b1079c3b1d4273425feae501e39/13ae7/SelectedChangeSet.png 350w,
/static/5c489b1079c3b1d4273425feae501e39/8c557/SelectedChangeSet.png 700w,
/static/5c489b1079c3b1d4273425feae501e39/c8e86/SelectedChangeSet.png 758w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;then you select only &lt;strong&gt;ProjectB&lt;/strong&gt; assuming that only changes from &lt;strong&gt;ProjectB&lt;/strong&gt; will be included.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 622px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/948b1804995ffaf1dce9429af98ab2f7/604ec/SelectChangeSet.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 49.71428571428571%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABn0lEQVR42oWRW2/aQBCF9/9L/QeV+hClQGnVp15e+pQm4mIwkIsEsQqlJuDLer27viDH+HR2QepLSUb6dGbGR+vRDOOpRq41kpgjjmIkiUDCE3DOIaVEGIS23zQNzsXhcEBd16iqCmzlP2HxuEBRFJYsyyx5nls1PZPrU24efgm2izh4HGNf7hGTRlGEMAxp0oRymo7HNGGEgHqcei9NaoIJlUFrhVSkpBpKKlsbtSiCak0qqTY/EkIcSY6Y9Zi1SJmCzb0lBsMRnJGLyfQO7mQG151a+n3HquOMMSTG46n1GB2Rv98f4v5hjuVqjUfvF/zNFizYbSG2K4jdGjL0oaIN5T5E4KPKUuC5RFPlBO1vnxGaegVQFyct6SqGve2xHw8h3nyd4+31Fq2pwsVghw+jEJ9nCdrXHr7dxfh+z/FlFqLV2+Dd1RoXY4HWROK9wTWkR6hmV57AJRk+3ip0ZxodJ8DlzRqd3h90bzx0fs6JBT71lmj3fqM9eEL3VpNX/Rem8tJe55XjneJ1E0uzEgfyVXWDZ0rqM/z7Bpuf4y/SZuylLmfdngAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;SelectChangeSet&quot;
        title=&quot;&quot;
        src=&quot;/static/948b1804995ffaf1dce9429af98ab2f7/604ec/SelectChangeSet.png&quot;
        srcset=&quot;/static/948b1804995ffaf1dce9429af98ab2f7/4edbd/SelectChangeSet.png 175w,
/static/948b1804995ffaf1dce9429af98ab2f7/13ae7/SelectChangeSet.png 350w,
/static/948b1804995ffaf1dce9429af98ab2f7/604ec/SelectChangeSet.png 622w&quot;
        sizes=&quot;(max-width: 622px) 100vw, 622px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;But the result will be not as expected - you will also transfer a new &lt;strong&gt;FieldA&lt;/strong&gt; and it refers to EDT that doesn&apos;t exist in TEST branch. So you will get a compile error when you try to Build your TEST branch(and that is not the worst scenario)&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 643px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/d06b59ff0760d3520a542d0b18c06c1e/b5bda/MergeResults.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 82.28571428571429%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAYAAAAWGF8bAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACt0lEQVR42o2UyY7bRhCG9f5vk6NhBIER5BQgB09GzkikRJEUm2Rz3ykuX6p77LFh+DAEflRv9dfOwzw/aNqWcRzpuo5lWXg8Hm/Yto3v386+76+rr/Lt5uv+sIwpRZ5QVRW1QGvNMAyWvGkaWjEWx7GVRZFT1zVlWVppdPq+t2TGsMFheQzW8jBOTNPMtq6sBuLpuq32kdmbu7btJZreng3DKBEslszARGo9bLveXnT9IJ4W5Flurf78mfCruhHPGmZZmzdGx6Tq1budSZw6KK2I0xwliGJNlGbEWUGa14KKJCutzMsGLVKXci73Zd2T6pyqaXlImucVpmXnoLOEONGoOCEVskRn+H5AePMIfJ8wCHEcl+AeoZSS/Z0wSuz6elO4niITjmWebWoOSXDkcvybwHkmcf7hfn0Rb0oSFYisKGQdibF7JkVrB+qyINOheFgT5TNuUBGrK2UihZWiHZ4+P+F9+ZPrf7/hv7jo85E8Limzjk4eNSqSfUseepT6L6nsJIpyL+HXYrCpTXc0cl7byh9cz6f0L2RKE3hwd2p8r5KzhPr0BX1SBM+IoYkuyuhiaKOdOoDKhyYye6hDpDOkymfHIY8i9nXjcoWTM3M8tlyvPbegk0JMmKJLF73rO5xdlywM2JYVTwjPJyThINFYonXdbZ++YsMMxDfwTf5I6Ahh4nlGU3oKIhNO1FPEI33QMng5o5Avhnx6h4en8xkdSEKkOaXnhXcjcmecfxNenjPOzwWnp47bqSFPKrp2l4mRvDWCTnpv+gVhJj1mfN8Esdq5iMOXG+SpTJDuuP/+B+rTR+4fP6A/O8iAWOJOiKfxF4TpTbTN3Eo+ymKnuHWoS0V2lpZwc5pU8lnK+A3vDDkL768h77stgvI3Qq+RIlVc3ApXwvU9mXNdyB9ol57jDcNPRv4HOAXIoS/wfngAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;MergeResults&quot;
        title=&quot;&quot;
        src=&quot;/static/d06b59ff0760d3520a542d0b18c06c1e/b5bda/MergeResults.png&quot;
        srcset=&quot;/static/d06b59ff0760d3520a542d0b18c06c1e/4edbd/MergeResults.png 175w,
/static/d06b59ff0760d3520a542d0b18c06c1e/13ae7/MergeResults.png 350w,
/static/d06b59ff0760d3520a542d0b18c06c1e/b5bda/MergeResults.png 643w&quot;
        sizes=&quot;(max-width: 643px) 100vw, 643px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;case-2---why-my-test-system-doesnt-work&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#case-2---why-my-test-system-doesnt-work&quot; aria-label=&quot;case 2   why my test system doesnt work permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Case 2 - Why my test system doesn&apos;t work&lt;/h2&gt;
&lt;p&gt;Let&apos;s consider another example - you are developing some complex modification(&lt;strong&gt;Project1&lt;/strong&gt;), and a part of this modification is a new validation on the Sales table&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 699px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/6a90c1bbe4cabe0b97dafd973fb4e5ab/3fe45/Project1.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 41.142857142857146%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABbklEQVR42oWRW2vbQBBG/f//Rh/7HAgOoS91ik1wsV0KaprIstJESSRrL7rsxdLpSnHa+qHtwLCw8J09MzuZfVqyS1OiH8/cPjzxLclInyXbxyei5J7v8RYpFc55+q6nlBUXH+Yk2x030S3xXUIU3bCNU4osZnK1WCFUjbKOOM8pRImQkqquQ1e0rWGovu/Hs9aad2dLpqsXppuC8y+Cy6+S803J5R1MZvMVdQirxrB72VO2ntY4ZABrXQUzdwJUQvH+Ys0mc0w/p5wtM65Tx/Kh42MyABdrdFXRdR11yJaVe7UzB/ZlSR6spVJ470egCONfhcxQZf5Idh9TiZxWl7hWDyOvR8A4ToAUyiB1TVEE2wC0xoyW3aE7AjWz+SvwECQO4d6Fx976BGhDsAmWqmpQ+z1NaKskvm1owwq8aRHit+HbGv6sE6DxPY31WGs5Jn513x0N/wecLYZPabDeUNThd20T9uX4Wwmh/wn8Cae8X/mingrLAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Project1&quot;
        title=&quot;&quot;
        src=&quot;/static/6a90c1bbe4cabe0b97dafd973fb4e5ab/3fe45/Project1.png&quot;
        srcset=&quot;/static/6a90c1bbe4cabe0b97dafd973fb4e5ab/4edbd/Project1.png 175w,
/static/6a90c1bbe4cabe0b97dafd973fb4e5ab/13ae7/Project1.png 350w,
/static/6a90c1bbe4cabe0b97dafd973fb4e5ab/3fe45/Project1.png 699w&quot;
        sizes=&quot;(max-width: 699px) 100vw, 699px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Another developer has developed in the same branch a simple modification just to provide some default values for the SalesTable(&lt;strong&gt;Project2&lt;/strong&gt;)&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 389px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/38b8a5b7d09e5833b48448516742ed70/00a4e/Project2.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 76.57142857142857%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAClklEQVR42pVTx3LbMBTk/39VcsjJHjmxZZEUbRWKpAiwd7Bhs6Q9iRwnh2BmB+UBD7uvGIH9BPN5h+12h8fvj7AsG6Zp4elph+PJQ9cPaLr+Da1C3SmuOTfduv8TRigTtLxsBREsrp0owzaQMN0rTK+C7dfYc729eNiHAlvf596DEBLjNGMYpw8w4ihA00h46YisA7IWSBogljF8Pg4DgfPxiIvn4RqGCPwAHtdZnmMZWusPoEMfRXZC141ohwaiDCErgbhOyGDimcK8Xgbm+ffDadIYx/kTDBnFGIZh/a1sCrjCgysvZJuvjsZ5pKP5BtPq8F/DiGLGsG0x0mnWzPBzjaLViCk7KIG86XE5n3A6Euczw+AhCK6/SHxyGMcCSeQiEhHqtkahShRdgVLVlDyiHwdoBl+T3cQQLCyX9RqDv8CQwsHQWav3buoQqRSijRCrDKNm5oj/GYaUrxhqE3NSQScJdJZBpzmR8SzlfAPa5+XO+3xrX8/rmjHMUlQnB+nmAZ69xcPdVzzef8F28w2hZcF9eoDYmYgsE9K2Iff7FYnjINlzby42C5INkW82i8McxeGAMYqQ9IBbaZSDhlRMSDtASAmf9SeEQFDVEEohVB2yYUQcsX6v4ZqkkIoafmDELND05QU9K79j5iYmgH6g2HJ1WaAoSjSUothuBe+WVYWyLKHoeJn1e5KWQmqowJBppsvjSQ9ksoxWzXBiwAsTvNg77J7f4Nh7XFwXF0o8bJ/Zy81aamvGF3DUlqWNlAyq0xk9JSuWyMTUd7S3lKSGfmXakE1DmYttXlTw3nxb3Ev3LAwZ1yWGUek4+Ui6hX/AaX8P17mD//oDKvTRXT02NjMYx9BSQPPjFVT0C4wvaK83G/UTN7x4Rf6Hp0gAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Project2&quot;
        title=&quot;&quot;
        src=&quot;/static/38b8a5b7d09e5833b48448516742ed70/00a4e/Project2.png&quot;
        srcset=&quot;/static/38b8a5b7d09e5833b48448516742ed70/4edbd/Project2.png 175w,
/static/38b8a5b7d09e5833b48448516742ed70/13ae7/Project2.png 350w,
/static/38b8a5b7d09e5833b48448516742ed70/00a4e/Project2.png 389w&quot;
        sizes=&quot;(max-width: 389px) 100vw, 389px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Project2&lt;/strong&gt; is simple to test and after testing you decided to move to it user testing - TEST branch. Again this is a typical valid scenario in AX2009 or AX2012, we often don&apos;t care about other people modifications, we just transfer XPO and compare the code during the import.&lt;/p&gt;
&lt;p&gt;You run &quot;selected changesets&quot; transfer and choose only &lt;strong&gt;Project2&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 479px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/14832a920b5c052541909bcbf961797d/a9b70/MergeSelected2.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 49.71428571428571%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB7klEQVR42n2S227TQBCG/ZjcISEVid6BEIIX4QV6UaQWBOKiAnEBLRcIkiZNYmdt7zqxE2ft2Dn40LQ52D+ziwSNQFj6NDP/rse/Z9dYzOdYzBdIkxTTKEbgj+D7AeJIIpIRJuEEyTRBkiSQE4nZbI7/PUae59TAh5RSC9vdDkVRoqpqotLUdY0d6YqK8u1mQ2z1nr8aCs9Do9FEHMfIlktwzhEEQzDbxnA4JMdDcOFBCEG6D4/2KzjVZXmtm9xta9ztrpxoqvpPXu+vqbd1qOt/YoxHAVifgVl9eOTEdRzChc1seFzoNZU7pAtyryO5c+gPhHLucnBCaa7twhgFI1y1O2hfttBn7Fdzotft6dg3TTRpJF2qTcq7nS5atFetW6YFU+k90q+oR6sDIwxD+qqrT1Y5UPPyg4DmNCDHA5qpwHKZIS8KZHSABc0tL0uqS6qL3yyzXGNk8xkmdAhxOMJ6VaBa3+gYh2NUm1vclDkSGWJHOeotykWCNAywytX12ZC23sN4+TXGvaOB5v6JJCIcvJZ48m6MZ2cJHr+PcXjq4/nZFI/ejPHi1MTTE4YHRwwPXwkcHPM9jEG6wgWbwozW6Ea36E03+C5SfPjh4GOD40svxKdLgbfnbXzjKT43Gc7bHFZ0DXNSwJLlHj8B6Rvbf+gpeuMAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;MergeSelected2&quot;
        title=&quot;&quot;
        src=&quot;/static/14832a920b5c052541909bcbf961797d/a9b70/MergeSelected2.png&quot;
        srcset=&quot;/static/14832a920b5c052541909bcbf961797d/4edbd/MergeSelected2.png 175w,
/static/14832a920b5c052541909bcbf961797d/13ae7/MergeSelected2.png 350w,
/static/14832a920b5c052541909bcbf961797d/a9b70/MergeSelected2.png 479w&quot;
        sizes=&quot;(max-width: 479px) 100vw, 479px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;As the result, you will get a file that contains a part or &lt;strong&gt;Project1&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 465px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/782af5288b1debeacdddd18aaa66ca97/9ff85/Merge2.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 110.28571428571428%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAWCAYAAADAQbwGAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACwklEQVR42pVUy27bQAz0/39Gr0FP7Qf01EPtomictEljPewYiWxJ1vut5ZQUZcVOXSARQKykXQ6HXA5nXxfXmM/n+PF9gV/LGyzmt1gsllj+vMP99QO8XQDfF/MvmO4FwYvNNmsHrrtGFHromxpRBGw3wMMDYNtAHBMAgjG80mg4N6IXmzm2A8uyEIYh5CHq0bU9ssTAXhG2j0CWiluPtlOr2w59b9C2QNfh7Jk5jsNMbCRJPAJqJDMyWbvA3W9gvQ6xf3Kxub/G8/oPpxch8AHPIyX9GjBOEqBpUNl3aFY3MPYtKHhGmTZIow5FZng/B4oAqPksmRGCzhkKmG3ZqJh/xcV7+vgB3ucreJ+uEH/7ws6hWrnj3NmKA1BxDUyPS8/MdV24jos8z7XAcpC4MKbhla0p+bPhV95vS2VZMcNSAjFwU5yBK0O+mKIoNAFj9FAZjQ4M0NWaZpMxWKyAw7cEOQUkBZQ6ToBS4SOIMBJnASk51cLXGv4n3YnhGSAzJMP90LcK0qQjo3QEjhVU9iTg8D+a9hjQesXQKANZxUGAJa2u4rVS9pK6/Otr/S+g8s3ntYavU5Z0T9Mmwlufmc0qcaZLIWXYlUMaVGdsqQZ5M+BQQxdFng1pdi2rBO8idaGxpQ/jgIlVLClgx3I6hMRBiPuTUJbvBLTYDofD8MNIHzJHHjyweOJYK8DfDzvDQOiN6Jzvo7+cBU8bW7Ucnw8HcaxrwmbNoBbxXDzAe95i664Q7hI8bQGR/8VLsU4B5SK4p0iUwPJLghr7neEScH/yRZnoEZTttV+n4UAT3X/aRluGL4iBhx4EvfNSmKGA5vkImHmcC+eTeqpnYctKoWEwFBpMTAL3zfg99qwyPPahNHCvej0KXxQg75O0olHTgcpRwGTq5L6+n2pZx9eolOMwEKci1CDiIKs4cw0HyV1I+S/BmadY/Y60agAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Merge2&quot;
        title=&quot;&quot;
        src=&quot;/static/782af5288b1debeacdddd18aaa66ca97/9ff85/Merge2.png&quot;
        srcset=&quot;/static/782af5288b1debeacdddd18aaa66ca97/4edbd/Merge2.png 175w,
/static/782af5288b1debeacdddd18aaa66ca97/13ae7/Merge2.png 350w,
/static/782af5288b1debeacdddd18aaa66ca97/9ff85/Merge2.png 465w&quot;
        sizes=&quot;(max-width: 465px) 100vw, 465px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;This will probably create an unexpected new validation on TEST branch, and your users may even not be able to create Sales orders due to this validation.&lt;/p&gt;
&lt;h2 id=&quot;case-3---why-my-code-is-missing-after-the-merge&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#case-3---why-my-code-is-missing-after-the-merge&quot; aria-label=&quot;case 3   why my code is missing after the merge permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Case 3 - Why my code is missing after the merge&lt;/h2&gt;
&lt;p&gt;Let&apos;s continue with the example above. Consider that it is your lucky day and you noticed that you added unwanted code from &lt;strong&gt;Project1&lt;/strong&gt; to the TEST version before it&apos;s being deployed to users.&lt;/p&gt;
&lt;p&gt;You open the class in TEST branch and delete the code related to &lt;strong&gt;Project1&lt;/strong&gt; from it. It is a typical AX2012 operation, you don&apos;t need this code now.&lt;/p&gt;
&lt;p&gt;Then after some time, you finally decide to transfer &lt;strong&gt;Project1&lt;/strong&gt; to TEST from Main. You can even run full branch merge for this.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 454px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/1e15765e5d8623c6406dd0b372802ec8/b3c1d/MergeSelected3.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 50.28571428571429%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACAElEQVR42nWSW2/TQBCF/ScRPKBIFTyBhITEC3+HSwsVUuGFp9I+FNHUubopSdNkba+9duLgkNS3XcdNDmNXjSgSK33amXPG6/GstfA6wSwIMJ/PMfV9CMcFJ3zPg3AFhBDwiSCYwXFdsNGYdA836zU2m03F30tbJgrFKsdiscRNUVTiv0W3+X3tf0tjjo/euYHDw2+IowgT6tLmDkyTESYcx7mFNGaZsG2Lcl55jDGEYbh9aYmW5GvILNt2lec5FJFlaYXKFZRSSKs4J19BSoksTSGVxGpV3O9wHmVIkwRxHFdkdHiS0C5Jp4fuKPXSv8vLQ9MkpdoEEX1Z6ZWxNg2XMDodNPQG6j/qODcMtBpNdEjTz3QYXQNnp3WcktfUSW+3aG9QvU6UeQfddhftZpviNrTg9zXNxcaIbo8xE5xm5QqP5uTCMu3qxjnn5FkUO9V8Xbrt8ZhVtaXvVDW3s9Z+LSIIawyP25i6HNboin4TjgnFgluYCiq0GGQSoVBZRS5TFDnNr8rlljLXJvMY3/sCX+uXOO4JXEwVLgKFBgtx8tPDVbiCISIcdSwMAonBTEIfODhuDXHS4xhMYvT9kgh9L4J2ScHOvovanoOHuz4e7Xp48N7Dk32Bl198vPjs49nBBE8/WHj+0cTOnoVXn4Z4fTBG7e0Qj98MUXs32vIH/OXbHS5qAWcAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;MergeSelected3&quot;
        title=&quot;&quot;
        src=&quot;/static/1e15765e5d8623c6406dd0b372802ec8/b3c1d/MergeSelected3.png&quot;
        srcset=&quot;/static/1e15765e5d8623c6406dd0b372802ec8/4edbd/MergeSelected3.png 175w,
/static/1e15765e5d8623c6406dd0b372802ec8/13ae7/MergeSelected3.png 350w,
/static/1e15765e5d8623c6406dd0b372802ec8/b3c1d/MergeSelected3.png 454w&quot;
        sizes=&quot;(max-width: 454px) 100vw, 454px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;After a successful merge, your code related to &lt;strong&gt;Project1&lt;/strong&gt; will not appear in TEST. You lost it!&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 593px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/cd527143eda444149e84f2d958a5e824/0b5b1/MergeResults3.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 72%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACSElEQVR42oWT2Y7TQBRE/f8/whfwgpDghUfQwMx4EmdxnHhtL+19iWMfbpzRSAwRtFSyb7e7qu5iw/GO6DRBRRGRIAwjlFIEfkAcJ3iuRyyx7/uoMCQMbkiTFK1zvNOJqizo2pbLZcJQmZaLISc3IM8ysiQmTvOFMBSx64VYxWy3Np7KUal8E6d4QnoVDJTGtFus3QHl2xirlx9Y3z9hPXzGefzK7uELm1/f8GyLJItJ81SQiIhC6QRdRBSlJs99sjxCVyV+UtzOAxfjp7liJ+zHzQes9Ylif6CyTJKjODnWVBsfbbqEmx61DslPH8nCgczv0FFHrhqKsKHSHV0/YKwlFfd0pMhbPA92LwPByhYBB9sMOJgR+0fF0ZJ6rs84JpQ+NKEghi6DWt6HhmUZL5s9B9umrivGESI1YzsTQTjRdBfGoWDuIuZLu1yY+fcyzPVOGuLSZv4iNVURo1acE5chEWntQLKF3BU75Y10fmV+jyvh82qLK4RDlcIovscapuuzkDyEYKgEstdLfG743xLCDY7jiHhKU8/IGMosiqn01cmdNb8etG3H+Tz+Sfi0EB6ErF42aiFVUkeZ9TuE813idzXc3ghl0m/HE+dBHEoHlbjtul7mrhTBjkqy73ve6ngPxrO1w9tvqcKcUkpUlBOVuIzjmadH2G8bQudEKN8Fzoj8HEsWVXUfxuPKwpWxudQNk0hMYm8az0zTJJB4/jvdt8bedSgpuwchlNTocxmTA1SBVFy60oqdXkve+hZfu33Fsl/cncrfkrkuvmAb66EAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;MergeResults3&quot;
        title=&quot;&quot;
        src=&quot;/static/cd527143eda444149e84f2d958a5e824/0b5b1/MergeResults3.png&quot;
        srcset=&quot;/static/cd527143eda444149e84f2d958a5e824/4edbd/MergeResults3.png 175w,
/static/cd527143eda444149e84f2d958a5e824/13ae7/MergeResults3.png 350w,
/static/cd527143eda444149e84f2d958a5e824/0b5b1/MergeResults3.png 593w&quot;
        sizes=&quot;(max-width: 593px) 100vw, 593px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;microsoft-recommendations&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#microsoft-recommendations&quot; aria-label=&quot;microsoft recommendations permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Microsoft recommendations&lt;/h2&gt;
&lt;p&gt;All examples above may happen due to incorrect usage of branching strategy.&lt;/p&gt;
&lt;p&gt;The basic advice from Microsoft is the following:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Start with the main only branching strategy, &lt;a href=&quot;https://docs.microsoft.com/en-us/azure/devops/repos/tfvc/branching-strategies-with-tfvc?view=azure-devops&quot;&gt;branch strategically&lt;/a&gt; and adopt other strategies to evolve into more complex strategies as needed.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;To achieve this, you need to work in sprints(for example 1 release per week).&lt;/p&gt;
&lt;p&gt;It is a high chance that sometimes you need an emergency fix (that can&apos;t wait for a week). In this case, you restore a new temporary branch from the last build, implement a fix in this temporary branch and merge changes back to Main before the next release(so it will be a &lt;strong&gt;Release isolation strategy&lt;/strong&gt;).&lt;/p&gt;
&lt;p&gt;Full list of strategies is available here &lt;a href=&quot;https://docs.microsoft.com/en-us/azure/devops/repos/tfvc/branching-strategies-with-tfvc?view=azure-devops&quot;&gt;https://docs.microsoft.com/en-us/azure/devops/repos/tfvc/branching-strategies-with-tfvc?view=azure-devops&lt;/a&gt;, but please note that none of the recommended strategies allows &quot;Merge selected changesets&quot;, you should always work with a forward-only merge. So merging just changeset2 on this diagram may corrupt your branch&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/92a2454f8192bbee9d513e5303f13023/fe9f1/ChangeSetMS.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 21.142857142857142%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAYAAACOXx+WAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAA80lEQVR42lWMzU6DQBSFeT0egAfgjdqVP+nGS20ixQapbIzWFUVDU2wdBxvdwMoYNyZoSjszx4FxoZN8uWfOd2esfq+Hq+sbBOEUB6chvHGEoWYQxDjxfBx7AQZnEQ6169ME4/ASpP3RKERwEWN0PsUkinE7m8G2bVhpmgoAHY2CqPcmo2nE5/xOvNXyn98Kk9Vv9xfXdYWVJAnaI6Xs5tdO4VvP+vEJ1cMztjrvpIJSnca7LvZm1bxT7d0U+kNYvu9TVVVUFBtarjits4xYtqSPl9fh4n5BRZ4T165lnjNKc04rtiHGDWtWEOcFlWVJjuPQD1IjD2f21jkFAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;ChangeSetMS&quot;
        title=&quot;&quot;
        src=&quot;/static/92a2454f8192bbee9d513e5303f13023/8c557/ChangeSetMS.png&quot;
        srcset=&quot;/static/92a2454f8192bbee9d513e5303f13023/4edbd/ChangeSetMS.png 175w,
/static/92a2454f8192bbee9d513e5303f13023/13ae7/ChangeSetMS.png 350w,
/static/92a2454f8192bbee9d513e5303f13023/8c557/ChangeSetMS.png 700w,
/static/92a2454f8192bbee9d513e5303f13023/fe9f1/ChangeSetMS.png 883w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The main issue that &lt;strong&gt;TFVC&lt;/strong&gt; doesn&apos;t prevent from executing the wrong commands and probably in 95% cases when you run &quot;Merge selected changesets&quot; it will run without any issues as modifications usually don&apos;t contain common elements. And this may create a wrong feeling that it will always work.&lt;/p&gt;
&lt;h2 id=&quot;summary&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#summary&quot; aria-label=&quot;summary permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Summary&lt;/h2&gt;
&lt;p&gt;One of the key features of Team Foundation Version Control(&lt;strong&gt;TFVC&lt;/strong&gt;) is that changeset is a whole object, not just changes.&lt;/p&gt;
&lt;p&gt;If you use the old AX approach(&quot;Merge selected changesets&quot; in random order) with D365FO Team Foundation Version Control(&lt;strong&gt;TFVC&lt;/strong&gt;) system, you may face problems. You may get compile errors, transfer unwanted code and lost changes in code.&lt;/p&gt;
&lt;p&gt;So choose your branching strategy before the development, agree on it with a Project manager and follow it. Also If you know any tools that can prevent the described cases feel free to post a comment.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Resolving performance issues caused by parameters sniffing in AX2012 and D365FO]]></title><description><![CDATA[The blog post compares ways how to solve SQL performance problems caused by parameters sniffing for AX2009/AX2012 and cloud version Dynamics 365 for Finance and Operations]]></description><link>https://denistrunin.com/performance-sniffing/</link><guid isPermaLink="false">https://denistrunin.com/performance-sniffing/</guid><pubDate>Thu, 07 May 2020 22:12:03 GMT</pubDate><content:encoded>&lt;p&gt;Let&apos;s discuss how AX performance problems caused by &quot;parameters sniffing&quot; may be resolved when you have on-premise system and access to SQL Server and for Dynamics 365 Finance and Operations.&lt;/p&gt;
&lt;h2 id=&quot;ax2009ax2012-on-premise&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#ax2009ax2012-on-premise&quot; aria-label=&quot;ax2009ax2012 on premise permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;AX2009/AX2012 on-premise&lt;/h2&gt;
&lt;p&gt;One of our clients reported a problem that his users complained about a slow AX performance. There was not just one operation, the general complain was something like: &quot;System is very slow today - Posting is slow and invoicing is slow&quot;. When I logged in to the SQL box, the first metric I saw was a high CPU utilization that was above normal for this client.&lt;/p&gt;
&lt;p&gt;After executing a &lt;a href=&quot;https://github.com/TrudAX/TRUDScripts/blob/master/Performance/AX%20Technical%20Audit.md#get-top-sql&quot;&gt;top SQL query&lt;/a&gt;, I saw the following result. The first query took more than ten times logical reads than the second one.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/36872c11ca0b9c9000e04e78f7304f55/62da8/TOPSql.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 60.57142857142858%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB5klEQVR42p1S2ZKbMBDk/39oPyCbtySu7MYxmNMIBMIIc9ncdEbysdnK1j5kqro0ulo9mjaev3zFt+cdNj92+L55xesvC5uXLdIkwtRJXNojRho5j/HbcmHZHrY7Gz+3Fl4+gMG5g5hFSDiHlEciSlBIiXVd8T9hhAcTvuvBsizsTQuu48BxXZwvFyxEeqdVD7wHsCzrPzB4GEAmZ62sLhp0zYq26XCpK/TFCSsRo+sw9RPWYcQ40LRf0Pf9xwpZ6OIoS4g6xfEscKoblEWHQV24ytBYl2v+pmy5S7/iUTLzEGU5Am7jkFJeCMQ5R3bKMM/z5x92I1qn6Y0wyXwkbQZexRoZdbWdWiyYPye6kfVRhDP9+X3dyEidinmZoVqgu6vOrvir0+u7xuggVe12i8Y0sdwqUXuGSd5iIYNIBaqqQlkqlBpVVZOVJPI8hxAZ2alATnNh2wiensBplHRG7SvIXMKwHQ9+4CPwA9h0wLYd7Pe2zpV9hBBo2zOattVCfXo8PjAUtD6Qsr7rdccVhmGA4RBhGIYERh504RGJ59Ejvg/GmFY6jqOGCtPn8NMKddOQhQaqfNJEal/lhrV3wCKGIAhI2V4b/HAIwWPqNJV5OpVkw+7huzThaJoaF/LnXdUw9A/CP09clAw75+K/AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;TopSQL&quot;
        title=&quot;&quot;
        src=&quot;/static/36872c11ca0b9c9000e04e78f7304f55/8c557/TOPSql.png&quot;
        srcset=&quot;/static/36872c11ca0b9c9000e04e78f7304f55/4edbd/TOPSql.png 175w,
/static/36872c11ca0b9c9000e04e78f7304f55/13ae7/TOPSql.png 350w,
/static/36872c11ca0b9c9000e04e78f7304f55/8c557/TOPSql.png 700w,
/static/36872c11ca0b9c9000e04e78f7304f55/e996b/TOPSql.png 1050w,
/static/36872c11ca0b9c9000e04e78f7304f55/62da8/TOPSql.png 1262w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The query was quite simple - get the last cost price for the item&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;sql&quot;&gt;&lt;pre class=&quot;language-sql&quot;&gt;&lt;code class=&quot;language-sql&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;@P1&lt;/span&gt; nvarchar&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;@P2&lt;/span&gt; nvarchar&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;21&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;@P3&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;@P4&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;datetime&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;@P5&lt;/span&gt; nvarchar&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;@P6&lt;/span&gt; nvarchar&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;11&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;SELECT&lt;/span&gt; A&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ITEMID&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;A&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;VERSIONID&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;A&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;PRICETYPE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;A&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;INVENTDIMID&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;A&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;MARKUP&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;A&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;PRICEUNIT&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;A&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;PRICE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;A&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;PRICECALCID&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;A&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;UNITID&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;A&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;PRICEALLOCATEMARKUP&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;A&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;PRICEQTY&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;A&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;STDCOSTTRANSDATE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;A&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;STDCOSTVOUCHER&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;A&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;COSTINGTYPE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;A&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ACTIVATIONDATE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;A&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;MCSPMFBATCHSIZE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;A&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;CREATEDDATETIME&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;A&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;RECVERSION&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;A&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;RECID &lt;span class=&quot;token keyword&quot;&gt;FROM&lt;/span&gt; INVENTITEMPRICE A &lt;span class=&quot;token keyword&quot;&gt;WHERE&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;A&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;DATAAREAID&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;@P1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;AND&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;A&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ITEMID&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;@P2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;AND&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;A&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;PRICETYPE&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;@P3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;AND&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;A&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ACTIVATIONDATE&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;@P4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;AND&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;EXISTS&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;x&apos;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;FROM&lt;/span&gt; INVENTDIM B &lt;span class=&quot;token keyword&quot;&gt;WHERE&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;B&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;DATAAREAID&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;@P5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;AND&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;B&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;INVENTDIMID&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;A&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;INVENTDIMID&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;AND&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;B&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;INVENTSITEID&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;@P6&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;ORDER&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;BY&lt;/span&gt; A&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;DATAAREAID&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;A&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ACTIVATIONDATE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;A&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;CREATEDDATETIME &lt;span class=&quot;token keyword&quot;&gt;DESC&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But when I clicked on &quot;query_plan&quot; column in the output, I saw the reason why it took so much time – the wrong plan that started with &lt;strong&gt;InventDim&lt;/strong&gt; table.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/5c050e172d5f90d6da013675dfff0cb2/d5b59/WrongPlan.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 25.142857142857146%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAYAAABFA8wzAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAA40lEQVR42n2PzU7DMBCE+/53eASegCfgwIErqOLnUFE5aew4P42bOLGdfGxaiQsRK41s745nZ3b7/RvW5BQnRZ4dsFZzPH5jS0NdWbQ+0TQV2hiZlehSoAuMzFt3ppAzy3OqqqQV3k4pRUqR0XvBwDzP8tHi1/c4CbEmhIjrB8Yp4KXnhoHLZaD/+sR+vNN2Z+I0stbOVu31siwL2/W3P6oML8kenxR3z4H7l5mHV8TMKljfBL3vxaETFxPGNsQYt+Vlceg6lhDohGK9oF8Et9W/gkEISURSSjjnrtH/rTXRRqofvhOBjdO0jcMAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Wrong plan&quot;
        title=&quot;&quot;
        src=&quot;/static/5c050e172d5f90d6da013675dfff0cb2/8c557/WrongPlan.png&quot;
        srcset=&quot;/static/5c050e172d5f90d6da013675dfff0cb2/4edbd/WrongPlan.png 175w,
/static/5c050e172d5f90d6da013675dfff0cb2/13ae7/WrongPlan.png 350w,
/static/5c050e172d5f90d6da013675dfff0cb2/8c557/WrongPlan.png 700w,
/static/5c050e172d5f90d6da013675dfff0cb2/e996b/WrongPlan.png 1050w,
/static/5c050e172d5f90d6da013675dfff0cb2/d5b59/WrongPlan.png 1370w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Probably recently they created a new location, and this new location was the first parameter for this query and SQL Server based on the current statistics decided to start the plan with &lt;strong&gt;InventDim&lt;/strong&gt;(that was probably OK for this new location with no data), the plan was cached and caused a performance problem for all other locations.&lt;/p&gt;
&lt;p&gt;The correct plan should be the following - start the search by &lt;strong&gt;ItemId&lt;/strong&gt; and then check &lt;strong&gt;InventDim&lt;/strong&gt;(it can be obtained by running &lt;strong&gt;Display Estimated Execution plan&lt;/strong&gt; for the query above)&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/8b75ce22640e2ae86029b4d30ac99698/02cd5/GoodPlan.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 45.142857142857146%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABt0lEQVR42m2S247TQAyG8/Q8wEqAgBteAe65AgmV82FFQrvbNJNzMpNM0rTd0iYf7hSkrrSWrPw+/bbH8W7mM6xp6dqawfYMnWbdVYRhiR8smC9Cfl4vBCf4/i3Bb+XUD3x++THBPCROElScuK+3isShrBgFaVaRZVq0oK4biiKnqmq01pSlFa2pKy0xg9FrjLGCtYv3XU9n13g3y4gkqVgul0IghKl1RHGsUJGSgoqyKomiQvJSlIokFot/kLxC/BGh1J4aF8WA9/bdjCAIiLOcPEspJekUNMa4zidcylTaNLS2w8okurGYtqVpWqy1dF1H6+wG78uPa1Qay5opyyhmpRLyPGO5SghXSnBOqzO2Xcmu15gq424w3PU1tj03revzAI7wmzxu1pacRJ3eqRkEjYRxLo0qmA68CkaefJh4Ojvw6M2O559Grt6PLMwkuRPjODFNZ/XCMGY8HsWA3XbDn/3ekVtZoV+vHflrIXz8EV5+h2efJ158hasZ3DYu1dX+Fy8v9T/nhfdCXOfxyGFnudtYtKx32LRMx/2D+fcI75Fe4MNxlCNYcvkLUjleIUfa7h4m/As0faRj66hqfwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Correct plan&quot;
        title=&quot;&quot;
        src=&quot;/static/8b75ce22640e2ae86029b4d30ac99698/8c557/GoodPlan.png&quot;
        srcset=&quot;/static/8b75ce22640e2ae86029b4d30ac99698/4edbd/GoodPlan.png 175w,
/static/8b75ce22640e2ae86029b4d30ac99698/13ae7/GoodPlan.png 350w,
/static/8b75ce22640e2ae86029b4d30ac99698/8c557/GoodPlan.png 700w,
/static/8b75ce22640e2ae86029b4d30ac99698/02cd5/GoodPlan.png 821w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;To avoid such situations in the future, I created a custom plan with a &quot;force order&quot; hint&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;sql&quot;&gt;&lt;pre class=&quot;language-sql&quot;&gt;&lt;code class=&quot;language-sql&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;EXEC&lt;/span&gt; sp_create_plan_guide &lt;span class=&quot;token variable&quot;&gt;@name&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; N&lt;span class=&quot;token string&quot;&gt;&apos;[AX_InventItemPriceDimSite]&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;@stmt&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; N&lt;span class=&quot;token string&quot;&gt;&apos;SELECT A.ITEMID,A.VERSIONID,A.PRICETYPE,A.INVENTDIMID,A.MARKUP,A.PRICEUNIT,A.PRICE,A.PRICECALCID,A.UNITID,A.PRICEALLOCATEMARKUP,A.PRICEQTY,A.STDCOSTTRANSDATE,A.STDCOSTVOUCHER,A.COSTINGTYPE,A.ACTIVATIONDATE,A.MCSPMFBATCHSIZE,A.CREATEDDATETIME,A.RECVERSION,A.RECID FROM INVENTITEMPRICE A WHERE ((A.DATAAREAID=@P1) AND (((A.ITEMID=@P2) AND (A.PRICETYPE=@P3)) AND (A.ACTIVATIONDATE&gt;@P4))) AND EXISTS (SELECT &apos;&apos;x&apos;&apos; FROM INVENTDIM B WHERE ((B.DATAAREAID=@P5) AND ((B.INVENTDIMID=A.INVENTDIMID) AND (B.INVENTSITEID=@P6)))) ORDER BY A.DATAAREAID,A.ACTIVATIONDATE,A.CREATEDDATETIME DESC&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token variable&quot;&gt;@type&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; N&lt;span class=&quot;token string&quot;&gt;&apos;SQL&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token variable&quot;&gt;@module_or_batch&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token variable&quot;&gt;@params&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; N&lt;span class=&quot;token string&quot;&gt;&apos;@P1 nvarchar(5),@P2 nvarchar(21),@P3 int,@P4 datetime,@P5 nvarchar(5),@P6 nvarchar(11)&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token variable&quot;&gt;@hints&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; N&lt;span class=&quot;token string&quot;&gt;&apos;OPTION(force order, loop join)&apos;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;After that, the system performance restored to normal, and the CPU load was considerably reduced.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 225px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/440f86e5dc9565956de12069c22eb3f3/3684f/CPUResults.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 61.142857142857146%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAA7EAAAOxAGVKw4bAAACyUlEQVR42n2TS0hUURjHz73n3rmOOmMzoznNOEOmUQsX7SJatGqRgTPYokWLWrloE0WLaBO9rAh6bIKECntNRNGLhIqEsqKEQiUzsRdB0Vg2OTba6Iy/PmdEXEQH/pzn/Z3/953vqlwuRyYzzrcvSb7/GuVHKkVq5Bdjv38zPDzCz1SaZHKY4e8/mMxO8q+Wy+WZyueZnMqh8jJ49OwhiTvX6byV4NrV8xw738bdB7e519lB+7VLJG4muCJ79x7d52X/S7r7ugt60fuCnoFePn/6wMDQEPlpUOl0mqX19Si3ornaR1ckQtMiH8prYXttSr0OJf4SHJ+DdmtMj4n2SO+YqBLFonCI9++G+JpMCnC6CKxbtgRVrlABm5UBNzf8AU5V+gkHHFk3sAMWjt/CEpBVKb3MLblQVShqakN0dT3m52i6EH4RuKQOZSocjwuzVGPbJtuqFtAZDLIlUIFVamGW27gcC5dnBmyhHV1wGBKHbwcH+PMnOwsUcl2DAMMKV9yFE5kJVW4XF/V+h7PiNhFcSEOoTNKgcVfJmSobu8JGLVBExOHTp0/E4VgRODqSpnZHLWqfQp+U3ERNzKCJa5fkKiIuLJONQS8d1dUc8vnY6vWgJI92iS7kPVQT5s2bfsYnJmYdjgnwhABbBXhIY+wz0LsFfEqgayVELU58mqik4+PCMBPRKGtqygUqZyWH4cVhenpekZbSmwPWH5VXPqiwW230YY1u1QW3eoM8QrlAgzZllQ6rJOzNlT7W+r3i3MZwG0SlKrq7n5Oae5QZh0fE4V6FeUBKYb8qhK8Oi7aL9ojWyd5y2dtpYFSZGA0G5mqZRxTBFUHeDQ6RnZoqAjPjGVouttB4ppH4uTixs7GizoguiC7GaDrdROx4E82XYjS3xYi3y/rlOI1t69ncvonevtfFX2amDvlfm55Vft54vmYh2Wx27pO/LO0yg8yAiRoAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;CPU utilization&quot;
        title=&quot;&quot;
        src=&quot;/static/440f86e5dc9565956de12069c22eb3f3/3684f/CPUResults.png&quot;
        srcset=&quot;/static/440f86e5dc9565956de12069c22eb3f3/4edbd/CPUResults.png 175w,
/static/440f86e5dc9565956de12069c22eb3f3/3684f/CPUResults.png 225w&quot;
        sizes=&quot;(max-width: 225px) 100vw, 225px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;So the troubleshooting was quite easy to perform, the problem was fixed, and this issue will not happen again. The complexity of these steps is that you need someone who understands Dynamics AX DB structure and has access to the SQL Server.&lt;/p&gt;
&lt;p&gt;If you have just a SQL administrator who doesn&apos;t know AX Database structure, you can create a simple instruction to deal with such problems:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Run a top SQL &lt;a href=&quot;https://github.com/TrudAX/TRUDScripts/blob/master/Performance/AX%20Technical%20Audit.md#get-top-sql&quot;&gt;query&lt;/a&gt; and copy results to Excel(you can copy all columns except the last one - &quot;query_plan&quot;)&lt;/li&gt;
&lt;li&gt;Click on the last column - &quot;query_plan&quot; for the first 3-5 rows&lt;/li&gt;
&lt;li&gt;Save them to separate files with  &lt;strong&gt;.sqlplan&lt;/strong&gt; extension&lt;/li&gt;
&lt;li&gt;Try to clear the SQL cache with &lt;strong&gt;DBCC FREEPROCCACHE&lt;/strong&gt; command&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Then this information may be passed to AX developer in order to fix the problem.&lt;/p&gt;
&lt;p&gt;The wrong way to resolve such problems is to perform one of these actions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Restart the system&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Run reindexing&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Run statistics update&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These actions will clear the current cache, and there is a high chance that the problem will disappear, but it will not be resolved.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A note about Plan Guides:&lt;/strong&gt; ideally you should keep number of custom Plan Guides to minimum(as they may become invalid if you, for example, modify the table structure). After you fixed the issue with the plan guide, try to think how this can be avoided by modifying the code(typical solutions - create/update indexes, use &lt;strong&gt;forceliterals&lt;/strong&gt; hint in X++, modify the query..)&lt;/p&gt;
&lt;h4 id=&quot;some-troubleshooting-tipsupdate-18022021&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#some-troubleshooting-tipsupdate-18022021&quot; aria-label=&quot;some troubleshooting tipsupdate 18022021 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Some troubleshooting tips(update 18/02/2021)&lt;/h4&gt;
&lt;p&gt;1.You can view existing plans with their hints in &lt;strong&gt;Plan Guides&lt;/strong&gt; section&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 534px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/d98de5031423a6cbc11c7f9c0c67bceb/a07a7/PlanGuidesInDB.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 99.42857142857142%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAIAAAAC64paAAAACXBIWXMAAA7DAAAOwwHHb6hkAAACxElEQVR42pVTaW/TQBD1DwdBBSoUxCfEBw4hVXxEghbSktIzbZomTZOmjd3Eietk7bUdx469PrJ24mPZJL1ApIjR09tZad/M+I3MZLZPfuxWVvfKX7Oljb3qVrG+Vzg7OOL2T9r75dZfkTvmD6uXnzM5JiUkwJ4JKwLP8XwbAGDbKAzDNE2TORHHMSHkqFxj6JGkxFB4uV0SLoHvedbAGkcRmR+0LuXyKctML2Sgi0rnzDBsWpf8K34XE9JXWxJfbDTarSavQCW6v/OUD47KzOweRYkB63K3JUmKpmoOcmbl57VN4ujn9sGVeBwlvU5ZaNQajZYKFdM075+cmra5k7/uHCe6VJPEhiRBhFAUxf8lTg14LjTPbOTNZkvnzX1XnEwfhVGqiCWhWW9fAhwEM1fS6SKSJI3TCehGKeJkklBHszffTB8GjsY22V63Y0AZIxs7duCike/G0fgPxyado/HmxhazC3prAK0D9A04r0u1T5X2x1LrbZ79ULh4n6u92Sovl5oZQV9tqhlxsA6cGda66FX2mHmQv3haBUuc9oKDLxvqEgefc3DpQnnGygtF7nGhTvGocP5w//RJRVhk4WJdnoAmNZFZyVfb54d9pekj0fdE7HWw3x0Nu0nQJZE8DqSRL6YxJKlGEoXQ5BYK86VQ3skV17YOedmEAwxNrNoj2Hc1TbdsR9asCx4Ypu34AfKw4+EZz8AIth9h33Nd+rvcmDIKR3rfECXV7Gtj3wx8G7tW4FkTdidM4TsW03HDmYW3IAQHoWmYy0fmQtZ6l7eynL/K4u/scI0brtQx5Qw7zAvDKzFd5t11YBw4rsfr4U7TPbwcsgCJVgIQkZ20Y6WKS1SPmJgwHS+8Xt5tBEFgIddFCDtmPA56itRXJV2VVUmkeYi9cYix794nppbofdMYWKrW03q61uvLUOkCmTKQIQDyL17oTi6H61n0AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Plan guides&quot;
        title=&quot;&quot;
        src=&quot;/static/d98de5031423a6cbc11c7f9c0c67bceb/a07a7/PlanGuidesInDB.png&quot;
        srcset=&quot;/static/d98de5031423a6cbc11c7f9c0c67bceb/4edbd/PlanGuidesInDB.png 175w,
/static/d98de5031423a6cbc11c7f9c0c67bceb/13ae7/PlanGuidesInDB.png 350w,
/static/d98de5031423a6cbc11c7f9c0c67bceb/a07a7/PlanGuidesInDB.png 534w&quot;
        sizes=&quot;(max-width: 534px) 100vw, 534px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;2.In order to check what plan hint is applied for the query, press &lt;strong&gt;Show execution Plan XML..&lt;/strong&gt; in the plan view, and check the last value for &quot;&lt;strong&gt;StmtCursor&lt;/strong&gt;&quot; tag.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/1d617021994621d8d31a2f7d155b6086/f4b77/IsPlanApplied.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 16%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAADCAYAAACTWi8uAAAACXBIWXMAAB2HAAAdhwGP5fFlAAAAg0lEQVR42l2OyQ7DMAhE/f+/2FsvOVRZMHbaeOEVK1FU9fA0wAyI8Joe6PrkkyaoizNDu/S3bhf//p07CaqZ2ozecKPfNBerBqW5ZxzFx9Uzwxgzz7j47kmppwbZBNmMdzxABW+wKOTdj6Yd1pkj7iz+lMaOJWU0RRKqRhokQ8TIufMFENPqGprTLcYAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Is plan applied&quot;
        title=&quot;&quot;
        src=&quot;/static/1d617021994621d8d31a2f7d155b6086/8c557/IsPlanApplied.png&quot;
        srcset=&quot;/static/1d617021994621d8d31a2f7d155b6086/4edbd/IsPlanApplied.png 175w,
/static/1d617021994621d8d31a2f7d155b6086/13ae7/IsPlanApplied.png 350w,
/static/1d617021994621d8d31a2f7d155b6086/8c557/IsPlanApplied.png 700w,
/static/1d617021994621d8d31a2f7d155b6086/f4b77/IsPlanApplied.png 770w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;3.You can use a handy tool &lt;a href=&quot;https://github.com/denissukhotin/MSSQLPlanToSpExecuteSql&quot;&gt;MSSQLPlanToSpExecuteSql&lt;/a&gt; by Denis Sukhotin to convert the plan XLM to a normal SQL with the actual values instead of @P1. Then you can execute this query from SSMS with different parameter values and try to understand why the wrong plan was used&lt;/p&gt;
&lt;h2 id=&quot;dynamics-365-finance-and-operations---cloud-version&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#dynamics-365-finance-and-operations---cloud-version&quot; aria-label=&quot;dynamics 365 finance and operations   cloud version permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Dynamics 365 Finance and Operations - cloud version&lt;/h2&gt;
&lt;p&gt;In the above situation, we had access to the SQL box, let&apos;s discuss how this can work when we don&apos;t have direct access to the SQL Server - in the new cloud D365FO.&lt;/p&gt;
&lt;p&gt;Microsoft proposes to use LCS for this. On the Environment monitoring page you have a &quot;SQL Insights&quot; tab where you can execute the predefined &lt;strong&gt;&quot;List most expensive queries&quot;&lt;/strong&gt; command(full documentation is &lt;a href=&quot;https://docs.microsoft.com/en-us/dynamics365/fin-ops-core/dev-itpro/lifecycle-services/performancetroubleshooting&quot;&gt;here&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/c189b8520394172b1e1c40bde2828095/dcccd/ExpensiveQueries.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 69.14285714285714%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB0UlEQVR42qWTyW4TQRCG5zEREiiQBCEWA+KAuITY4jUCkW0w8SEsDhLPARySmATP1uNZPD2bZxLb8FNVEyEu+GAfflV1T/fX9Xf1GO13A+z3PqHb/4ze4Re8evMer99+QPtggL3uoXzr9I/QoXHn4Ajt/uBv3qX5/d5HWbPXrfcZGw92cPfpSxHnrO0nLdxu7GLrcQubj5rYIm02mth42MTN+y8o7kp+q9HCjXs7uLb9DNfvPBcZUTCGY43gubbIdSy4tgnHPIdyTIyVI+M00ZgvfqMqK1TVBUqKs8sZ5vMFFrNL/JrXMjzlwlMKynVJNszRT/Dc2TlBXQ86niAMAmRpgjzLKKaS1/o3r2XYjoJl2fD9sWyOJxNEYQjH5mptjD0+yJG5eBIh0TGB0//KCHwflmkKsCpL5HmOlCph68PTU7JrEYSr9EV86FKgZY5wcnwsNqMwQKw1ErJSyILaRpFnmBasXPKlwLMfQ3z/9hUMVmSRLTNw2aalQK6M76ig06tyiozs6iS5qnAFYJGnKKcFPYWK4hQJwXSSrg7krvFFF9QMAeo1gSE1IqDuMeyCqlzbMr8zT9mICMpgfdXllZvCf8PJcAST3mLge3KH6wD/ABTh+PNIUjuZAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Expensive Queries&quot;
        title=&quot;&quot;
        src=&quot;/static/c189b8520394172b1e1c40bde2828095/8c557/ExpensiveQueries.png&quot;
        srcset=&quot;/static/c189b8520394172b1e1c40bde2828095/4edbd/ExpensiveQueries.png 175w,
/static/c189b8520394172b1e1c40bde2828095/13ae7/ExpensiveQueries.png 350w,
/static/c189b8520394172b1e1c40bde2828095/8c557/ExpensiveQueries.png 700w,
/static/c189b8520394172b1e1c40bde2828095/e996b/ExpensiveQueries.png 1050w,
/static/c189b8520394172b1e1c40bde2828095/dcccd/ExpensiveQueries.png 1127w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;And to check the actual plan you need to get a result of this command and paste it to &lt;strong&gt;&quot;Get the SQL query plan for a given plan ID&quot;&lt;/strong&gt; and this will give you a &lt;strong&gt;.sqlplan&lt;/strong&gt; file that you can open in a local SQL Management studio.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/873a13657807e528cfcddd09a60fcaec/c1c45/ExpensiveQueries_getPlan.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 80.57142857142858%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAYAAAAWGF8bAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAC9klEQVR42m1TTW/TQBD1b4ADEh8SUIoEAiFRyoUTlZAAqS0c+IlwQAialn4AhbYIIUpVqTTfjpPYTrJrx3ZsJ3ZS1MNjZpMUBXoY7ezM6s3Me7NaZm0Ly+vbeP1uA2ufvmF98zvef/iKN5mPWFr9DM6/Xdk8ua9s7CCzvqXiE0axpdUv0C7efoLLd+dx88ELTN9/jkt3nuL8rce4QPFrs88wdW9RxadmF3F1ZgFXZubJFnDuxiOcmX6Is9Nzf+36HLR63YReqaDCZlRhGIa6G8qvQteHft20IIREa2RCCDrFyJejnIDmiCb0UgFmzYBR0WHVa9DLJRUz9DJKxTyKhRxaDRu/j/oYpAkG/WR4nmJa4HtwpEDY6aDVbCIKO+ouRQudwKOqLnTDRrvtoxtHKh9HofJPM81x2zBtSYABRItBfAJuqFNQ903yGTwgcK/twrYsVTDt9ZD0uhPW68bQ2o4kjiqo0cj8cJzoxTGiuAvO25YJy6zDIWDPdSBlC64j6D2fEg4ZF/U9D5qqalsw6/Vhh9RpHEUKtBPF9IgmIF5Nk/NN1SW/4QkC31eTDX1PUaHxo0I+R2qWVTJSgKECDMJY+QziEXDbdRXIv6NOjMyArGrDNiGpwzF/CQN2QiUCk93rdkcW/yNEPCGU1qBxs4eHqFWNIXdkKVWLki488kMCaQcBiRLQBCFc6lJKqcxhcxyI0V1KZ8ihS0Femz7tEbfeoYo+dW3sbKO2twdzf1+Jc1DMolQp0zQ2cUpCkeKWZdPS10kHG03aVY3lP+r3cTQY0MKmah1C6kzs/sCvVy9xuJyBs7uLSqmInwf7EO6ws2yWwEv0Acq6AuXOYxpfLTaPHY7EOLG0B5P4rZDCx8fH9DV1FAoF4qmrBMpmc0NA+qaNRoNixHuaQuPfkc8XkMvlUaYuqrSTkv4kg/L/ZDrSJIFPhSXtaUzEM038hjvlPBeIacUSmk7z/BC2CNBodRTprNR4BaI4Vv44No7zmSa9/1aGVf4DqHhwHgy6mYoAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Expensive Queries getPlan&quot;
        title=&quot;&quot;
        src=&quot;/static/873a13657807e528cfcddd09a60fcaec/8c557/ExpensiveQueries_getPlan.png&quot;
        srcset=&quot;/static/873a13657807e528cfcddd09a60fcaec/4edbd/ExpensiveQueries_getPlan.png 175w,
/static/873a13657807e528cfcddd09a60fcaec/13ae7/ExpensiveQueries_getPlan.png 350w,
/static/873a13657807e528cfcddd09a60fcaec/8c557/ExpensiveQueries_getPlan.png 700w,
/static/873a13657807e528cfcddd09a60fcaec/c1c45/ExpensiveQueries_getPlan.png 824w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Then there is another command to fix the plan.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 571px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/231449fa499c35d1c12b260def6f552d/17d73/PlanGuideAction.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 63.42857142857142%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACDElEQVR42p1T2Y7aQBD0///KbqLVPq2UKMnmYMGcYcHGt/GBjY2Nxx5Q3irdg4AQKVKSh9Ec7q7uqmpr08kY45GOkd7HoN/HaKjjdT7DYMD3HobDIXQ6zyiu9/ULXnrfMNQHeP70AWEQ4HiQaEWDrhVqaXm2QZrE6nFf7xCGAZpmj7raIVqHyDYp4mitgstiizxLEUUh6rrCQXY3YApwm2dI04TAKuyrEps0VudqVyKJI/D3jIqKfY0oKWB7Gxh2jE1e4tC1F0DeeWmB78L3PXUxLR+2Qx1SMnfluY4CZPCVYcB1bLieB5/WOgwproJtW3DofWUaxDSBJlUVoVZZCRS75kpDnCqL5trFmdrvVM93bTn/DnPxijEJPSNzcqJ8pCId6cgBggvVFEwJ3MWc4mfTCZaUMxmPSKLkRkutpEOx36OixIyMKKibWpJzx6Pq8ALYNuQqSWKtFE2PaJrGEtttDmZ5McV6+wbm/T2MuzvYDw+In54QPD4i13XIo1R0GVBSMJvF7tfVed9d5LgATj4/Y/z8ES/v38GfzyHY8ShCQ2ZwZSGugHyXsj3t6tyh68QtoE9z55BrAc2cS247HrlObxZRkr9oKNvbxD8tzSBxWWBjedqnJLjr2mrYeXxaCir+BdAhkS3LJMAFzVaghpy14V/qvzpk10wa2gXpx7/hD3JXKl2am7H5W8CfnvXCmqJyi04AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;PlanGuideAction&quot;
        title=&quot;&quot;
        src=&quot;/static/231449fa499c35d1c12b260def6f552d/17d73/PlanGuideAction.png&quot;
        srcset=&quot;/static/231449fa499c35d1c12b260def6f552d/4edbd/PlanGuideAction.png 175w,
/static/231449fa499c35d1c12b260def6f552d/13ae7/PlanGuideAction.png 350w,
/static/231449fa499c35d1c12b260def6f552d/17d73/PlanGuideAction.png 571w&quot;
        sizes=&quot;(max-width: 571px) 100vw, 571px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;So &lt;strong&gt;in theory,&lt;/strong&gt; we should have almost the same tools as we have with on-premise system. But the current problem is that every action in LCS is very slow. I tested these functions on several production environments and typical response time was about &lt;strong&gt;5-10 minutes&lt;/strong&gt;(you just see &quot;Please wait&quot; message). This time is huge, and the whole system is quite unusable due to this. Moreover, you can&apos;t run this in different windows, only one request in time is allowed.&lt;/p&gt;
&lt;p&gt;From the practical experience queries that work with SQL plan cache are almost instant even for huge databases, so the current problem is somewhere in communication between LCS and Azure SQL.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#conclusion&quot; aria-label=&quot;conclusion permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;If you use the on-premise system(AX2009, AX2012) and have access to SQL Server, make sure that your administrators know how to diagnose and solve parameters sniffing issues. It may happen even for an old system, for example, a case from this blog happened to a seven year old system.&lt;/p&gt;
&lt;p&gt;If you are in the cloud - vote for the &lt;a href=&quot;https://experience.dynamics.com/ideas/idea/?ideaid=2a4ab902-5690-ea11-99e5-0003ff68aebe&quot;&gt;idea&lt;/a&gt; to fix LCS Insights response time&lt;/p&gt;
&lt;p&gt;Any comments are welcome&lt;/p&gt;</content:encoded></item><item><title><![CDATA[D365FO Table browser extension]]></title><description><![CDATA[This post describes an extension for the standard D365FO table browser that allows root navigation and editing for non-development environments.]]></description><link>https://denistrunin.com/xpptools-devtablebrowser/</link><guid isPermaLink="false">https://denistrunin.com/xpptools-devtablebrowser/</guid><pubDate>Wed, 18 Mar 2020 20:12:03 GMT</pubDate><content:encoded>&lt;p&gt;The idea of this post is based on Alex Meyer&apos;s post &lt;a href=&quot;https://alexdmeyer.com/2020/02/27/how-to-continue-to-use-the-table-browser-functionality-within-d365fo/&quot;&gt;How to Continue to Use the Table Browser Functionality Within D365FO&lt;/a&gt;. I created a new X++ utility - Table browser extension. It contains the following changes:&lt;/p&gt;
&lt;h3 id=&quot;-allow-root-navigation&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#-allow-root-navigation&quot; aria-label=&quot; allow root navigation permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;-Allow root navigation&lt;/h3&gt;
&lt;p&gt;As Alex suggested in his post, I created a new menu item that allows running the table browser for a specific table:&lt;/p&gt;
&lt;p&gt;**&lt;a href=&quot;https://usnconeboxax1aos.cloud.onebox.dynamics.com**/?mi=DEVSysTableBrowser&amp;#x26;cmp=DAT&amp;#x26;tableName=UserInfo&quot;&gt;https://usnconeboxax1aos.cloud.onebox.dynamics.com**/?mi=DEVSysTableBrowser&amp;#x26;cmp=DAT&amp;#x26;tableName=UserInfo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/bc90ad3c44163fbc3c03f5111aa65552/3a737/TableBrowserRun.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 43.99999999999999%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB0klEQVR42mWSb2/TMBDG8xXHBC/ZxNYJFWnakrZrEYhBuwmKEJo0JvhoezMo2h9YkzhxEjt2nDzcOWgS4sVPdz7b57vzE1jrgK4DnEPXko8OStfQtUFt7D8Y26CuLapKoVKKzmko9RfdE0wXZ5jOzzB++R6z10uEr5bYi+bYOyTCRW+JQTjH8+gEw8kpjk4uMDv95jlafEX09gvG8wtP8GQwwbP9Y5/kxfQDdg7eYXM7wqOtETa2Qmw87dncHhFjPN6ZYDj7hMM35wiPzzGcfsZutMRg9BG7RFDX3EYDo6mNQqIsCtS6RGM0bK3grPF7rR8H/EjQNUBre8vAPRBIKaGqEkm8RkzkuUCWZTSnCjLPkQlBNkOeiQcykfqYzP6PB4oualWhLEvIosc2VLG10Pw5RJ5LSFnQXoGUHijpTpIKCJEhJctx4YtQCAo6yC3dixKXqxSXP2JcJxY3SYPr2OCG4PXqd0Vri6vbwsd/3musflXe/35X4uquwm3aIOCZcYWKksaJwHodw7oWDWEbB0tSYZ+lxJYrZfmw3Lh6VhzHuHLXdvQppB1NM9SUUFAwTRO66EiWDg21zrDP+2yNMZTMUpy0WWv6rI7GRQnTmPwWfwAY33yHPjds/QAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Run the table browser&quot;
        title=&quot;&quot;
        src=&quot;/static/bc90ad3c44163fbc3c03f5111aa65552/8c557/TableBrowserRun.png&quot;
        srcset=&quot;/static/bc90ad3c44163fbc3c03f5111aa65552/4edbd/TableBrowserRun.png 175w,
/static/bc90ad3c44163fbc3c03f5111aa65552/13ae7/TableBrowserRun.png 350w,
/static/bc90ad3c44163fbc3c03f5111aa65552/8c557/TableBrowserRun.png 700w,
/static/bc90ad3c44163fbc3c03f5111aa65552/3a737/TableBrowserRun.png 897w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h3 id=&quot;-allow-editing&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#-allow-editing&quot; aria-label=&quot; allow editing permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;-Allow editing&lt;/h3&gt;
&lt;p&gt;The standard table browser doesn&apos;t allow editing in non-development environments. This is controlled via the following standard code:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 489px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/85e3f77a19c3f8d257d5d49735a6d0fa/03e1f/TableBrowserNew.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 35.42857142857142%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAAA7EAAAOxAGVKw4bAAABaElEQVR42o2QzW7TQBSF/bDsQIgVqNsWXoAlrVQVqS0bWPAS3RYap3GdyJETx67tsVsn09jj8XyMnbQSrLjSke6fzj3nOgv3hMn1MXfXX5iPT0mCC5A/OTn9zKt3h7w9+MSbDx//C6/fH+HEwYxwEeFP57hewDLOqZ40ctvSqIau02iLruv22NXPPd21Q26MQSmFk4mStlXIWiOkYauhaqCUmo3c0ke//BxmqPe5JewL0+2hO5xciIGwH6qmYRHOCecB8WpJEidE0dL2QrKiIiklkcgJs4xVWXKfZvhBQGbzpu1VGxxRFGith4t1XTPxJtyMRiRJwuPDA75/hzty8WczslxY5AhLkK5WTH98xz37inf5Df/inPTqCqewhEq1gy25kfz+dcPYvbUYs4xipp6HN74lt3sv9s3Obl2taSzqx4one3y7Xu8UDs/VrSVuyKwdYZWk9ymiKFGbDdoqNy9k5q+f/ht/AEI8/4BKsNctAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;The new method&quot;
        title=&quot;&quot;
        src=&quot;/static/85e3f77a19c3f8d257d5d49735a6d0fa/03e1f/TableBrowserNew.png&quot;
        srcset=&quot;/static/85e3f77a19c3f8d257d5d49735a6d0fa/4edbd/TableBrowserNew.png 175w,
/static/85e3f77a19c3f8d257d5d49735a6d0fa/13ae7/TableBrowserNew.png 350w,
/static/85e3f77a19c3f8d257d5d49735a6d0fa/03e1f/TableBrowserNew.png 489w&quot;
        sizes=&quot;(max-width: 489px) 100vw, 489px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;I created an extension that overrides this behaviour. If a user belongs to the new role &quot;&lt;strong&gt;DEV Editable table browser&lt;/strong&gt;&quot;, the table browser editing function is not blocked.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 520px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/748ac5dda2a417c50546d71afa8ed2fe/69902/TableBrowserEdit.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 60%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAA7EAAAOxAGVKw4bAAABzklEQVR42qWSy27TQBiF/dBdQQEJAZtu2hdgASpSX4EHYMOiQm2AOHFJmzSx41vs8Ux8G3/8kxIJQaVS8UtHtuyZM+cy3vTLW76fv+NqdEpwecr04j2zbx+4GZ9h1Uc+fzrjyctjXrw54Zng6avjv3D4+oSD50ccHB7hxYs549mCc/+K0Y8bRsGci2mIfxNxmyvmm5LYVCRGU1SKYRi4b4ypUUWFp1RFXLZkW0tU1sR6S6gNq0oTliXzomBZKpZKschyuq5nsAP2D7hzHLxCNjRNg9m2hFGKaTpa2dS2LXXf01tLK/+bupGNlofGK+X0vu9IlajUlqKGjTKkeS4qKwoj7/GaKIpp5BA3zvZ9uCNUjlBsDBbdWMliyyZLSJMYrTWPHU+JCpeL7Qex3lJoUStZJoVkGYaibE2yjllHEXHRklRwPbvGn/j4vs90MiEIpkyDgExcCaHeZbMvbyukSorJpd0sy6jrmlLXVPKtaS1Njyg3uDIrwe5Z3cEJ8iohdHb32bhJ4pivo0tRMCYR66lBbkLjVjxseUf4qz233LXqml+tloSrkDRNUcJVmu7fMvydsO+6XUH/MzvC/f1ySjZVSy6qIilhsbh9dNM/AUHEkiAvw1QHAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Allow edit&quot;
        title=&quot;&quot;
        src=&quot;/static/748ac5dda2a417c50546d71afa8ed2fe/69902/TableBrowserEdit.png&quot;
        srcset=&quot;/static/748ac5dda2a417c50546d71afa8ed2fe/4edbd/TableBrowserEdit.png 175w,
/static/748ac5dda2a417c50546d71afa8ed2fe/13ae7/TableBrowserEdit.png 350w,
/static/748ac5dda2a417c50546d71afa8ed2fe/69902/TableBrowserEdit.png 520w&quot;
        sizes=&quot;(max-width: 520px) 100vw, 520px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;As I know the only way to edit data directly in tables for non-development Dynamics 365 Finance and Operation environment is either become the master of &lt;a href=&quot;https://erconsult.eu/blog/electronic-reporting-in-data-migration/&quot;&gt;Electronic reporting&lt;/a&gt; or create a support request. These options may take some time, so it is good to have an &quot;emergency&quot; tool like this.&lt;/p&gt;
&lt;h2 id=&quot;summary&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#summary&quot; aria-label=&quot;summary permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Summary&lt;/h2&gt;
&lt;p&gt;You can download the Editable table browser tool using the following link - &lt;a href=&quot;https://github.com/TrudAX/XppTools#installation&quot;&gt;https://github.com/TrudAX/XppTools#installation&lt;/a&gt;. I hope you may find this tool useful, also feel free to comment if you see something is missing&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Visual Studio extensions to simplify your D365FO debug experience]]></title><description><![CDATA[In this post, I want to describe some great Visual Studio extensions to simplify your D365FO debug experience.]]></description><link>https://denistrunin.com/d365fo-debughints/</link><guid isPermaLink="false">https://denistrunin.com/d365fo-debughints/</guid><pubDate>Thu, 27 Feb 2020 20:12:03 GMT</pubDate><content:encoded>&lt;p&gt;Visual Studio Marketplace contains lots of tools, and some of them can be used with D365 Finance and Operations. In this post, I want to describe some useful Visual Studio extensions to simplify your D365FO debug experience.&lt;/p&gt;
&lt;h3 id=&quot;debug-attach-manager&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#debug-attach-manager&quot; aria-label=&quot;debug attach manager permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Debug Attach Manager&lt;/h3&gt;
&lt;p&gt;The first one is a free, open-source tool &lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=ViktarKarpach.DebugAttachManager&quot;&gt;Debug Attach Manager&lt;/a&gt; by Viktar Karpach.
To debug the running D365FO application you need to go to Debug &gt; &lt;a href=&quot;https://microsoftdynamix.blogspot.com/2019/01/d365fo-debugging.html&quot;&gt;Attach to process&lt;/a&gt; &gt; then select &lt;strong&gt;iisexpress.exe&lt;/strong&gt; process and press Attach.&lt;/p&gt;
&lt;p&gt;But with &lt;strong&gt;Debug Attach Manager&lt;/strong&gt; it is much simpler - it adds a new button that allows to do this in one click.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 413px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/5e903a0ec3539b269a4f87895ab62f3e/6c1e7/DebugAttachManager.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 32%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAAB2HAAAdhwGP5fFlAAABm0lEQVR42m2O3UtTcRjHz5/UXxBB194XGQUJ4o3EFhFBylLWYO6lQCh7k1qKGV4kRGRTz9mbHvd2trNN3c7mpobnnBLK1ZSIT491FXTx4cPD7/s8v6+y9DrH0kKOpG4SX80LWT4sb5Baq5Jar7Gs5VFTpT9e0QriAivJInE1z2qiKFkdvWBRs1xqDRtFS1XQ8y3UtEmutIOaqVIwO3Jsi0TGxKh0+KgZstSUTIV4okSpuidHyxTLbdIb22hrm2SNlpTaRml0DtlqOvKDzaZ1gFFuiG3WDYt3mSaasSfvNvX2F+otaWE56HUHtdjE6NhYuwcc906w3a/sf5KG45GX3A3F8D+YYywyw2jwBf5ojJHAFEMjT/GOP8cXevWX8KlnuBWM4fFPkw1EmY88JvDsLROTcwQnZ1HOnOvn4qCP2/em8Yw+wuub4sbYE4bvPGTAG+aaJ8zV66F/GBD6vfeZvzTI4vk+Ll+4yRVPVLIRlLN9Q8y+eY/7+ZCd9q6wT0vsyHz0/Zhv3R5d8f9wej9xyyZuMk335BdH3R/8BmA/fcryWd86AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;DebugAttachManager&quot;
        title=&quot;&quot;
        src=&quot;/static/5e903a0ec3539b269a4f87895ab62f3e/6c1e7/DebugAttachManager.png&quot;
        srcset=&quot;/static/5e903a0ec3539b269a4f87895ab62f3e/4edbd/DebugAttachManager.png 175w,
/static/5e903a0ec3539b269a4f87895ab62f3e/13ae7/DebugAttachManager.png 350w,
/static/5e903a0ec3539b269a4f87895ab62f3e/6c1e7/DebugAttachManager.png 413w&quot;
        sizes=&quot;(max-width: 413px) 100vw, 413px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Update: the similar functionality exists in &lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=ErlandR.ReAttach&quot;&gt;ReAttach&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;visual-commander&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#visual-commander&quot; aria-label=&quot;visual commander permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Visual Commander&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=SergeyVlasov.VisualCommander&quot;&gt;Visual Commander&lt;/a&gt; is designed to provide lightweight scripting to Visual Studio IDE. It is more like macro VBA scripts in Excel, but for Visual Studio. You can use C# to write new commands and a free version allows you to create 10 commands.&lt;/p&gt;
&lt;p&gt;For example, you can create a command that adds a breakpoint to &lt;strong&gt;Infolog.add()&lt;/strong&gt; method&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;EnvDTE&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Debugger&lt;/span&gt; debugger &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;EnvDTE&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Debugger&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;DTE&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Debugger&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  
debugger&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Breakpoints&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;@&quot;K:\AosService\PackagesLocalDirectory\bin\XppSource\ApplicationPlatform\AxClass_Info.xpp&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;298&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//use C:\AOSService\PackagesLocalDirectory\Bin\XppSource\ApplicationPlatform\AxClass_Info.xpp for Local VMs&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/3bf904ed7630ed523c6a5bb07f628fea/fcda8/CreateCommandVC.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 51.42857142857144%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAB2HAAAdhwGP5fFlAAABy0lEQVR42n1Ra2/TMBTN//8J7AvjA6sQgiIYTEgtsIm/wKBL6NKuzcuJYztPO83ZtUM1KiEsHd2Xfc+519780xIv315hNv+A9GFJWEBk1+DJNdj+K4roGyS7QVt+x/JmiYt3n/Hm4wLzqy94fbnA81fvcXY+w9mLGZ6dX8BrKgWLSkrECUMc5+BlhRHA4TBiHEc0TYeMCZQlR5ZEdF+gbSrYU3KGwP+J+3WAPE/hRdQkSgsI1RBqGGrSmwM6PZygNwPa3sLWTmHzTWfQku/FKYMf+LgPN/D9AFXd4H/HKifRp8ATvJQVJDWHUgqcc3RdR6OVYJRLkphGZSjFNO5+v0fX91Nj2+kfx1N1S7s6QIiSdleirmvwgqMoCjCWIU1TR8Q5rYX2LKSAJFtVFb0RjlypylmpJLzeTEx1XTmVx0tWtZQKBVnO/xCRtURTjhMhqXc2d+/6XlPD4Ul6Thd+rVbYbre4u1shDENsNiHtOCAyiR2NHEURAop/r9d42O2wpfqP21vn26YnDa2KLMtcIY5jx2yV2rEjiq2qJEmcSkueU93u1b5hhJjIPPvd9mhtaJcDzDBgIGjdwxgDozX5msaZYusfrf4rPuYeAfRh9LDzLLJDAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;CreateCommandVC&quot;
        title=&quot;&quot;
        src=&quot;/static/3bf904ed7630ed523c6a5bb07f628fea/fcda8/CreateCommandVC.png&quot;
        srcset=&quot;/static/3bf904ed7630ed523c6a5bb07f628fea/4edbd/CreateCommandVC.png 175w,
/static/3bf904ed7630ed523c6a5bb07f628fea/13ae7/CreateCommandVC.png 350w,
/static/3bf904ed7630ed523c6a5bb07f628fea/fcda8/CreateCommandVC.png 590w&quot;
        sizes=&quot;(max-width: 590px) 100vw, 590px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;or create a command that opens your favourite object&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;string&lt;/span&gt;&lt;/span&gt; absolutePath &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;@&quot;K:\AosService\PackagesLocalDirectory\ApplicationPlatform\ApplicationPlatform\AxClass\Info.xml&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
DTE&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ItemOperations&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;OpenFile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;absolutePath&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;These commands will be available in &lt;strong&gt;VCmd&lt;/strong&gt; menu&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/25e8a2ee91e4321f08d0b516c89bc8d0/VCMDCommands.png&quot; alt=&quot;VCMDCommands&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;summary&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#summary&quot; aria-label=&quot;summary permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Summary&lt;/h2&gt;
&lt;p&gt;I hope you may find these tools useful, also feel free to comment if you see something is missing&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Note: there is a strange bug when downloading extensions using IE from VS Marketplace site. It autosaves downloaded file as &lt;strong&gt;&quot;.zip&quot;&lt;/strong&gt;, but to install the extension, you need to rename this file to &lt;strong&gt;&quot;.vsix&quot;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded></item><item><title><![CDATA[Examples of AX2012/ AX2009 performance problems]]></title><description><![CDATA[This post describes some real-life examples of AX2012/AX2009 performance problems and solutions for them.]]></description><link>https://denistrunin.com/performance-examplesAx2012/</link><guid isPermaLink="false">https://denistrunin.com/performance-examplesAx2012/</guid><pubDate>Wed, 08 Jan 2020 20:12:03 GMT</pubDate><content:encoded>&lt;h2 id=&quot;introduction&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#introduction&quot; aria-label=&quot;introduction permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Introduction&lt;/h2&gt;
&lt;p&gt;In this post, I try to describe some performance-related issues that I faced on client projects(mostly versions AX2009 and  AX2012R3) and how they were resolved.&lt;/p&gt;
&lt;p&gt;It is more like a collection of examples for my previous post &lt;a href=&quot;https://denistrunin.com/performance-audit/&quot;&gt;Dynamics AX performance audit&lt;/a&gt;. It also illustrates the initial concept described in this post: a performance analysis should be performed from the highest level and to continue by going deeper in details.&lt;/p&gt;
&lt;h2 id=&quot;server-related-issues&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#server-related-issues&quot; aria-label=&quot;server related issues permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Server related issues&lt;/h2&gt;
&lt;p&gt;There was a set of problems where users complained about the &quot;slow system&quot; in general&lt;/p&gt;
&lt;h3 id=&quot;shared-hardware-usage-for-ax-sql-server&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#shared-hardware-usage-for-ax-sql-server&quot; aria-label=&quot;shared hardware usage for ax sql server permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Shared hardware usage for AX SQL server&lt;/h3&gt;
&lt;p&gt;This issue was quite an unusual one. The whole AX implementation was installed on VM cluster where every CPU core shared between several VMs. The number of VMs allocated to the same CPU core is called &lt;em&gt;CPU allocation ratio&lt;/em&gt;, and it was 1 to 5. You probably can save your money on hardware and electricity costs using such configuration, but as a result, overall system performance was very slow, especially during the day. &lt;a href=&quot;https://www.microsoft.com/en-au/download/details.aspx?id=11094&quot;&gt;Microsoft Dynamics AX 2012 System Requirements&lt;/a&gt; document clearly says that dedicated hardware should be used.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How to detect:&lt;/strong&gt; I don&apos;t think is possible on Windows level, the best option is to ask IT support. Leading cloud providers always provide you with dedicated hardware&lt;/p&gt;
&lt;h3 id=&quot;database-mirroring-setup&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#database-mirroring-setup&quot; aria-label=&quot;database mirroring setup permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Database mirroring setup&lt;/h3&gt;
&lt;p&gt;One client set up a database mirroring using “High safety without automatic failover” mode. In this mode, a process waits for transactions to commit on both servers. This setting caused massive IO delays(like one record inserts for several seconds), not &lt;a href=&quot;https://docs.microsoft.com/en-us/dynamicsax-2012/appuser-itpro/sql-server-topology-recommendations-for-availability-and-performance&quot;&gt;supported&lt;/a&gt; by Microsoft and solution was to switch on &quot;High-performance&quot; mode for mirroring settings.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How to detect:&lt;/strong&gt; Such issue is quite easy to identify using &lt;a href=&quot;https://github.com/TrudAX/TRUDScripts/blob/master/Performance/AX%20Technical%20Audit.md#wait-statistics&quot;&gt;Wait statistics&lt;/a&gt; script. If you see that more than 80% waits are disk related, it is a time to check what the reason for this is.&lt;/p&gt;
&lt;h3 id=&quot;slow-performance-due-to-low-sql-server-memory&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#slow-performance-due-to-low-sql-server-memory&quot; aria-label=&quot;slow performance due to low sql server memory permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Slow performance due to low SQL Server memory&lt;/h3&gt;
&lt;p&gt;Dynamics AX is an OLTP system; it should not read any data from the disk during routine daily operations and SQL Server should have enough memory to hold the active data. If you don&apos;t have it - the available memory should be increased&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How to detect:&lt;/strong&gt; Check TOP SQL queries during the day – if you have a lot of physical disk reads, it is time to increase SQL Server memory(queries, of course, should have proper indexes)&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/4bd28cfda2bae9773f694439366338cc/cb9f4/PhysicalReads.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 34.85714285714286%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAAB2HAAAdhwGP5fFlAAABVElEQVR42jVRCXKDMAzk/09pH9EvNKTEYE4D4Qw3SZpkhq0kGs1oLMs6dteW1hppmiEMIxiToWkv6PsRwzCJj3LSnXLdpUdV1WiaC1r2tkNTVxQbyseoqwjWsizQnkYQBFTYIM9yFEUpcVVV4nXdoOsHcG1ZVljXK4FIcVIu+q6ECT9RmA/0zdc+MM8yeK5HCA2Kc0ELfLh0dxwHSil5q+sa9/sdr9cLbPk5h6c9iZPE0JJVYmuaJqQmhUvbmHqeU6GrBbXWvrhHcULL5nnGer1KIyP0iRUbs7jdbti2DRYX8aOSgemOkIYEfkCUFH4IZRiG6Loe8zSLFO+BAeXZGP3z+XwPXASV7/vISD8WPY4SRPRJTPd0UiIF02UUA2kplKknEIQbfU6Lx+OxU+YCRnC0j/LTIrajSAIF27bxfTiQnq7QnUmecRylMY73hWy88Pd/4B8Hjwb8RsQVjQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Physical reads&quot;
        title=&quot;&quot;
        src=&quot;/static/4bd28cfda2bae9773f694439366338cc/8c557/PhysicalReads.png&quot;
        srcset=&quot;/static/4bd28cfda2bae9773f694439366338cc/4edbd/PhysicalReads.png 175w,
/static/4bd28cfda2bae9773f694439366338cc/13ae7/PhysicalReads.png 350w,
/static/4bd28cfda2bae9773f694439366338cc/8c557/PhysicalReads.png 700w,
/static/4bd28cfda2bae9773f694439366338cc/e996b/PhysicalReads.png 1050w,
/static/4bd28cfda2bae9773f694439366338cc/2cefc/PhysicalReads.png 1400w,
/static/4bd28cfda2bae9773f694439366338cc/cb9f4/PhysicalReads.png 1903w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;sql-server-issues&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#sql-server-issues&quot; aria-label=&quot;sql server issues permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;SQL Server issues&lt;/h2&gt;
&lt;h3 id=&quot;missing-indexes&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#missing-indexes&quot; aria-label=&quot;missing indexes permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Missing indexes&lt;/h3&gt;
&lt;p&gt;That is a common problem. Usually, you use a missing index &lt;a href=&quot;https://github.com/TrudAX/TRUDScripts/blob/master/Performance/AX%20Technical%20Audit.md#missing-indexes&quot;&gt;query&lt;/a&gt; to find such indexes, but I also added a new column to TOP SQL &lt;a href=&quot;https://github.com/TrudAX/TRUDScripts/blob/master/Performance/AX%20Technical%20Audit.md#get-top-sql&quot;&gt;query&lt;/a&gt; - &quot;Has 99%&quot; that allows to quickly see your TOP SQL queries that have 99% missing index impact recommendation&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 670px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/3ac352b6984ce9ee290d0dbf385c67b8/d67fd/TopSQL99.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 14.285714285714285%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAADCAYAAACTWi8uAAAACXBIWXMAAB2HAAAdhwGP5fFlAAAArklEQVR42lWO2wqDMBBE/f8v8g98slARq+ZiaOKVWqO2xGrpNAn0oQsDy7BzZoOmadC27Z+c13UdxnHEMAyQUmJZFsRxjDzPoecZxhg8tw2cM/T29sJrEHVDwDlHVVUeUBSF352nlPKg2YYdbN93UEp9gZu31csW1NEJrQFIvyFRBoFrJIR4GGMMWZahLEsfFkJAa41pmnAcB9I09d//gPcwhEgo5PrB+fpARFd8ASJn3UNWPvSNAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;TopSQL99&quot;
        title=&quot;&quot;
        src=&quot;/static/3ac352b6984ce9ee290d0dbf385c67b8/d67fd/TopSQL99.png&quot;
        srcset=&quot;/static/3ac352b6984ce9ee290d0dbf385c67b8/4edbd/TopSQL99.png 175w,
/static/3ac352b6984ce9ee290d0dbf385c67b8/13ae7/TopSQL99.png 350w,
/static/3ac352b6984ce9ee290d0dbf385c67b8/d67fd/TopSQL99.png 670w&quot;
        sizes=&quot;(max-width: 670px) 100vw, 670px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h3 id=&quot;parameters-sniffing&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#parameters-sniffing&quot; aria-label=&quot;parameters sniffing permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Parameters sniffing&lt;/h3&gt;
&lt;p&gt;Parameter sniffing can be a huge problem, especially if you have separate teams responsible for SQL Server and AX. We had a case where a client complained about periodic slow ledger journal posting that stopped the work of a whole accounting department.&lt;/p&gt;
&lt;p&gt;In that case, the reason was just one custom query affected by parameters sniffing(not the optimal plan was initially selected and cached). Before the performance audit client spent about a month with tons of e-mails between AX team, SQL team and Microsoft support trying to implement typical recommendations like statistics refresh, re-indexes with a different fill-factor and so on...&lt;/p&gt;
&lt;p&gt;The issue has been quickly resolved by creating a new plan guide with &lt;a href=&quot;https://github.com/TrudAX/TRUDScripts/blob/master/Performance/AX%20Technical%20Audit.md#create-a-plan-guide&quot;&gt;OPTIMIZE FOR UNKNOWN&lt;/a&gt; hint.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How to detect:&lt;/strong&gt; To start with you need to analyse &quot;Get Top SQL&quot; output and check queries from the top. Often, the first step is to compare the actual plan with the Unknown parameters plan. To do this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Copy a query to a new SQL window and replace “(“ with “declare” and remove the last “)”&lt;/li&gt;
&lt;li&gt;Press “Display estimated execution plan” button&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Compare it with the plan from the &quot;Get Top SQL&quot; output; if they are different, you need to analyse why.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/9ba1cdbd56b114ecaad3f40f19a9680a/84f4d/ComparePlanWithUnknown.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 108%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAWCAYAAADAQbwGAAAACXBIWXMAAB2HAAAdhwGP5fFlAAADHElEQVR42oVV25KbOhD0Z5+/SOW38rzeU2tsDJibhLnfwdCnRzaJvcnmTJUKMUitnpkesfODEFEUQSuFMOQ8jnG5eIj5DIIAiv6L78PnXGuFgHNZJ98vvvk+d10H3/e/7cTeTx7quoY4y7LEm+UhzXK0bYumadD3HSwngBPEGDgXX8bvRVHgw/ZJQM2gcf8d0LZtfszFhyxNcfg4IM9zLMtifNM0wbIsw/B2u3FjDxUrE8XpdOQ4zcu6iP8OuK6r2SiLZf75XWzzy5hnQ8gceC0aHvhwAH8G3OzzARuI+GV4nou3/V5y9wr4DGDYfAIU66cZ3Ti/fB/H0eSTKfka0DB6YqO1hqICTs4FB9thZSMUZYFP9jdAPpdfIUrldXJFer0iCXyUSYKJPiYScz9IxWTcAftHUchk3ZLd9z32doym7cjwZtbagUbdtGbzjaOjnKqqxumiTMhVXd0Bm+b7C0Mx0aOIvGmbh4wy7PdvZJkYViIr13XhnM/wXM/MKfJXhmlelBUFTbBVQhSW8hRht+39aXxc01HMQ1WhpW4barVnPulfMAyo0vRHpNQ/u8Ph4JxONj4O1nKmyI8U8Yd1hG2f4V9802JSnDDWpg23dzNXGgnZh1G0ZjyApIbdPE1OpK6wzt46jgPZtfj36CJhuPI+TaMpzLvl/GR+JYgfxqy8a+bilxpQQvWO1XWkL5NEL9Jm4zghYvM3zKcURkx6XJjJpoHhFUWJlPmMyTLnXu5bH1IbpFOcTXqbuJ+ltDzJSNSw6TXWCQKG/Dh0W/Q74Es/mwtifdHn+jhIrja56h6t/DXgs4kO8zxDQmEf3QB5lqFnjp9tlUMfYRDgz4BblLJYcqSlU1SMjBqty8pokhU0T9LFLHMhyQK8AEr/SlUtV7Nna7NIXVM4fmQ2dgSzvJCd05hQKxZORH++hLiySG1V3V4Atwu1ENFSzGIJNRdFIVYCNgxZkam030RWFQ+QbtIsUEnB13n+O+CXJrmSy2CrNt/lCsuYkpOvkRP8Ngz/D/jzShNACtjkTi4KRpBGMSLPg+LvQLHqtda3/wCsPHb3EznTxAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;ActualPlanWithUnknown&quot;
        title=&quot;&quot;
        src=&quot;/static/9ba1cdbd56b114ecaad3f40f19a9680a/8c557/ComparePlanWithUnknown.png&quot;
        srcset=&quot;/static/9ba1cdbd56b114ecaad3f40f19a9680a/4edbd/ComparePlanWithUnknown.png 175w,
/static/9ba1cdbd56b114ecaad3f40f19a9680a/13ae7/ComparePlanWithUnknown.png 350w,
/static/9ba1cdbd56b114ecaad3f40f19a9680a/8c557/ComparePlanWithUnknown.png 700w,
/static/9ba1cdbd56b114ecaad3f40f19a9680a/e996b/ComparePlanWithUnknown.png 1050w,
/static/9ba1cdbd56b114ecaad3f40f19a9680a/84f4d/ComparePlanWithUnknown.png 1208w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;You need to know what logical reason for this query is, how data is distributed in your tables, how unique(or how selective) each condition in the select query is, why SQL Server generates two different plans and which plan is the correct one.&lt;/p&gt;
&lt;p&gt;To view actual parameters for the plan in the cache you need to press &quot;Show Execution Plan XML..&quot; on the plan itself and scroll to the bottom. You can use a handy tool &lt;a href=&quot;https://github.com/denissukhotin/MSSQLPlanToSpExecuteSql&quot;&gt;MSSQLPlanToSpExecuteSql&lt;/a&gt; by Denis Sukhotin to convert this XLM to a normal SQL with the actual values instead of @P1. Then you can execute this query from SSMS with different parameter values.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/1ad153bacfa1d083fd47eb7a746309f3/5ba90/PlanXML.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 35.42857142857142%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAAB2HAAAdhwGP5fFlAAABdUlEQVR42i1Ri1KCUBDl//+pFAsDBLlAinChMDUBzRdOPBw77d1i5sxe4O557Gqr5Rs2m09UVYmyrNC2Lbq+Q9f9oW0aNG2HS33F136Piu4cDgf0dKfvejTq/z9UrxYEIYQfIMvekL/n2G63TFyWfwL15YIk38B9lbDtCcwXk6vv+8jznIxU3KPOikNL4gRJIlm1vl5Z5Xa7kYOeHf7c71htd7C9Vzw8DjAcDDEaPUEf6nCcKaIoQpqmKIqCOTRJZN7UQ0zEUbRgLJcfpFpwvdY1NtUBtpjh6dmAYYxhULUsG7PZDJLIjscj43Q6QXMmDoTw4YsALik6ExdT16N3H/N5xLNZF3tYRDimuJZpM2zTgj7Q8ULforkyoSJn0FzHZRLPEwj8kNwKmpENKVN8Ny3Uw4ReSJGHGBB0fcTRVc+cIkspsVqvcVSRszSjAQcIw5BrvIjZXUjLUsoXWooidIIFjLHJcdVihBA8njiOsdvtGOfzGb/UbfYS2ChvPwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;PlanXML&quot;
        title=&quot;&quot;
        src=&quot;/static/1ad153bacfa1d083fd47eb7a746309f3/8c557/PlanXML.png&quot;
        srcset=&quot;/static/1ad153bacfa1d083fd47eb7a746309f3/4edbd/PlanXML.png 175w,
/static/1ad153bacfa1d083fd47eb7a746309f3/13ae7/PlanXML.png 350w,
/static/1ad153bacfa1d083fd47eb7a746309f3/8c557/PlanXML.png 700w,
/static/1ad153bacfa1d083fd47eb7a746309f3/e996b/PlanXML.png 1050w,
/static/1ad153bacfa1d083fd47eb7a746309f3/2cefc/PlanXML.png 1400w,
/static/1ad153bacfa1d083fd47eb7a746309f3/5ba90/PlanXML.png 1604w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Some queries can be fixed only by changing the X++ code. For example consider the following code, that gets total quantity for the specified &lt;strong&gt;Item&lt;/strong&gt; on a &lt;strong&gt;License plate&lt;/strong&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;select&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;AvailPhysical&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; inventSum
    &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;inventSum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ItemId &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; @P1
&lt;span class=&quot;token keyword&quot;&gt;join&lt;/span&gt; inventDim
    &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;inventDim&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;inventDimId &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; inventSum&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;InventDimId &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;
          inventDim&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;LicensePlateId &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; @P2&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&quot;License plate&quot; is a very selective field, so for the normal parameters &lt;strong&gt;InventDim(LicensePlateIdIdx)&lt;/strong&gt; index will be used. But what happens if we try to execute this statement with &lt;strong&gt;@P2=&quot;&quot;&lt;/strong&gt;. If we had this plan in the cache, the system would scan all &lt;strong&gt;InventDim&lt;/strong&gt; records with empty &lt;strong&gt;LicensePlateId&lt;/strong&gt;(and this will be a huge number of records) or if it were the first run, it would start processing this select with &lt;strong&gt;ItemId&lt;/strong&gt; field, that is not so selective. Both options are incorrect and will lead to problems. But from the logical point of view &lt;strong&gt;LicensePlateId=&quot;&quot;&lt;/strong&gt; doesn&apos;t make any sense, so instead of trying to fix this statement, we need to fix its parameters. In this case, a developer just forgot to add a check for an empty value, and the solution was to add this check and not to run this statement if &lt;strong&gt;@P2&lt;/strong&gt; is empty.&lt;/p&gt;
&lt;p&gt;The main advice here is never use statistics update or re-indexing to solve such issues, in the origin blog post I have some links what the approach should be(like additional indexes, hints in AX, convert to &lt;strong&gt;forceliterals&lt;/strong&gt;, create custom plan..)&lt;/p&gt;
&lt;h3 id=&quot;aos-and-terminal-servers-issues&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#aos-and-terminal-servers-issues&quot; aria-label=&quot;aos and terminal servers issues permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;AOS and Terminal servers issues&lt;/h3&gt;
&lt;h3 id=&quot;waiting-time-for-batch-tasks&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#waiting-time-for-batch-tasks&quot; aria-label=&quot;waiting time for batch tasks permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Waiting time for batch tasks&lt;/h3&gt;
&lt;p&gt;A client complained about slow integration. During the analysis, I found that for the integration they used a batch job that should be executed every minute, and sometimes it wasn&apos;t.&lt;/p&gt;
&lt;p&gt;There is one old recommendation on the Internet that when you set up an AX batch server, you should allocate only several threads per CPU core. In this case batch server was set up with 32 threads and such low setting caused batch execution delays(as there were no free threads available). To identify such problems, I created a SQL &lt;a href=&quot;https://github.com/TrudAX/TRUDScripts/blob/master/Performance/Jobs/DelayedBatchTasks.txt&quot;&gt;query&lt;/a&gt; that compares batch job &quot;Planned execution start time&quot; with the &quot;Actual start time&quot;. If you see some differences between these numbers, you have the same problem.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 562px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/10521b1feb7f7f1d22889f116c4d24f2/6e88f/BatchDelays.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 10.857142857142858%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAACCAYAAABYBvyLAAAACXBIWXMAAB2HAAAdhwGP5fFlAAAAk0lEQVR42h2KywqCUABE+/9vaBMiQllQC1c+isx8EVl5sy4SmYgRQQTl8mQuDjOcmZ7pp1iBIM5KxO2FvDec629HkF7b7cA8zrBDgbfLCUWBEx2xgxRvf0HIipUywumrJKZLT3EkfwbWCc0t0MOa4brCEA2z7RPdLxmHFdoy7/p082AStR+vQF3kXRqtN5M3vvzwA0Sbh9D5P680AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Batch delays&quot;
        title=&quot;&quot;
        src=&quot;/static/10521b1feb7f7f1d22889f116c4d24f2/6e88f/BatchDelays.png&quot;
        srcset=&quot;/static/10521b1feb7f7f1d22889f116c4d24f2/4edbd/BatchDelays.png 175w,
/static/10521b1feb7f7f1d22889f116c4d24f2/13ae7/BatchDelays.png 350w,
/static/10521b1feb7f7f1d22889f116c4d24f2/6e88f/BatchDelays.png 562w&quot;
        sizes=&quot;(max-width: 562px) 100vw, 562px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;My advice here is to increase this &quot;Maximum batch threads&quot; parameter for AOS until you have CPU and Memory resources(modern server can handle hundreds of threads). It is interesting that in the new D365FO version Microsoft has added &lt;strong&gt;Batch priority-based scheduling&lt;/strong&gt;(PU31), but this feature probably just hides the problem.&lt;/p&gt;
&lt;h4 id=&quot;huge-delays-during-sales-orders-posing-and-printing&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#huge-delays-during-sales-orders-posing-and-printing&quot; aria-label=&quot;huge delays during sales orders posing and printing permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Huge delays during sales orders posing and printing&lt;/h4&gt;
&lt;p&gt;That was a quite interesting and complex case. A client complained about periodic delays(1-2 minutes) during sales orders posting. The issue couldn&apos;t be replicated(initially it looked like typical parameters sniffing or blocking issue). The problem was that they also had a lot of other performance issues(a lot of missing indexes, old SQL version, High CPU load on SQL server and so on...). The client used AX2009 and they outsourced three different companies to support Infrastructure, SQL and AX side.&lt;/p&gt;
&lt;p&gt;When we fixed all performance issues, the system load became low, but they still sometimes complained about the original issue and we still couldn&apos;t replicate it(in all our tests small orders posted within several seconds). Setting up a SQL blocking alert and analysing TOP SQL also didn&apos;t show any problem. We ended up with a monitoring modification that logged different stages of sales invoice posing. The first finding was that posting time didn&apos;t depend on the number of sales order lines, next iterations showed that delay was caused by the &quot;print&quot; method. Finally, we found the reason for this delay - users used Windows2016 Citrix clients(AX2009 does not support that) and in our tests we used Windows2008R2 RDP to run AX client. Printer driver reconfiguration solved this issue.&lt;/p&gt;
&lt;h3 id=&quot;slow-standard-operations&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#slow-standard-operations&quot; aria-label=&quot;slow standard operations permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Slow standard operations&lt;/h3&gt;
&lt;p&gt;A lot of clients experienced issues with operations already fixed by Microsoft.&lt;/p&gt;
&lt;p&gt;Top 2 problems that almost all clients had:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Batch tables deadlocks&lt;/strong&gt; - was fixed in CU13 &lt;em&gt;KB3209851Continuous deadlocks in batch tables&lt;/em&gt; - Microsoft switched locks processing to application locks&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Locks and deadlocks on InventSumDeltaDim&lt;/strong&gt; - was fixed in &lt;em&gt;KB4019571 Deadlocking on InventSumDeltaDim causes Sales order release batch to fail&lt;/em&gt;. The solution is quite simple - delete RecId index and replace it with TTSItemCheckDimIdx&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The best way to start any performance investigation if users are complaining to individual operations is to search for the solution on the LCS &quot;Issue search&quot;(you can search by description or by AOT element name). For example for AX2012R3, there are 120 resolved performance-related fixes to different parts of the system(you can view the full list searching by &quot;slow&quot;)&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/5562ab227b6d5b2f63147b60d6b9b179/2c5fd/SlowLCS.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 74.28571428571428%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB+ElEQVR42pVTi26cMBDk//8sX9BUp9413IO3bcDGxjwmY5O7puWUKkirBWPPzuysk7KqIE5H5McjVNchPOu6/hXfeRI7jpAvL3C3G9YNbbfpWQGtNdI03QMao3HOcxRkmqZv+PH6isPhgMvlgvP5jIrry7IylkcETO89jDF7QG0t3q4Zfl9zXLIiAt2yDE3ToBECfd9/T/I4zxj8DDctmFh9LxeYuT7NC/Ma2X7V12S0A0ohd71a1gWa/9phhNAWdW/RMAvjuO4xToEEg2Ssn7h/K5I4o3C4XHFuJFnMj0rsFirVoGoUilowS/TW8TAVjVMECYAhh+/AfnOZLE405SrbeOAzYN1J1LJDJRQq/u8Gh955aIYhyFPJeqBkpVjFc7OLoIE9hUP1LaTqCKogmC1B/jeVyUCXf9LlK1mMpB96c296qwfUrWYRH5kZN8FPy9eAYZZORYmy66HMwMP2wUIPFrLXEC3/MZsP0Lvby7qPRBPwmBfI2w4Z+1TzYHQcM26yRlqwj5QrWbC3YwQNPQzvW2z97D6+E8erd2tEdLkju8+mNDQl9E6qFooFnQ+S5ziTIZ5KXjgqirch48GOEu/zxDFm/wRq0aLk2JQsaNz4Z2Q4Ps8MSsKdzOnir6KOoP4xiytl0mHVc5A396Ncu0keGEHmv+PzDksvkb1lNuSMAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;LCS Search&quot;
        title=&quot;&quot;
        src=&quot;/static/5562ab227b6d5b2f63147b60d6b9b179/8c557/SlowLCS.png&quot;
        srcset=&quot;/static/5562ab227b6d5b2f63147b60d6b9b179/4edbd/SlowLCS.png 175w,
/static/5562ab227b6d5b2f63147b60d6b9b179/13ae7/SlowLCS.png 350w,
/static/5562ab227b6d5b2f63147b60d6b9b179/8c557/SlowLCS.png 700w,
/static/5562ab227b6d5b2f63147b60d6b9b179/2c5fd/SlowLCS.png 1006w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Also, it is helpful to have the latest standard version on AX2012 and use it as a reference(if you have such application you can also extract hotfixes from it as xpo)&lt;/p&gt;
&lt;p&gt;With the latest version definition there is a trick - if you google &quot;latest AX version&quot; you will probably find this page - &lt;a href=&quot;https://cloudblogs.microsoft.com/dynamics365/no-audience/2012/03/29/overview-of-microsoft-dynamics-ax-build-numbers/&quot;&gt;Overview of Microsoft Dynamics AX build numbers&lt;/a&gt;. The problem with this site that it is not updated anymore. Current AX2012R3 latest version(both for the Binary and application) is called &quot;August 2019 release&quot;. It can be downloaded from &lt;em&gt;LCS - AX2012 project - Updates -  UPDATE INSTALLER FOR MICROSOFT DYNAMICS AX 2012 R3&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&quot;application-issues&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#application-issues&quot; aria-label=&quot;application issues permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Application issues&lt;/h3&gt;
&lt;p&gt;I saw these settings that affected performance:&lt;/p&gt;
&lt;h4 id=&quot;unused-financial-dimension-sets&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#unused-financial-dimension-sets&quot; aria-label=&quot;unused financial dimension sets permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Unused Financial dimension sets&lt;/h4&gt;
&lt;p&gt;Some customers initially created a lot of “Financial dimension sets” but used only several of them. For example, the setup below means that when the system creates a one ledger transaction – 16 different dimension set transactions will be created(they are used in Trial balance report)&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/c56dd1db51c329c62f6b77e69d4bd044/b97f6/UnusedFinancialSets.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 50.857142857142854%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAB2HAAAdhwGP5fFlAAAB8UlEQVR42nWSaW7bMBBGfdFeqSfoBQIUTVJ0yc+iFyhSO4klL5IsUbtkW1u0v45kuGhRdIAPQ1Izjx9FLt68+8Hb7xs+aooPLwH325Sblc+d5PdaxM3S5vZFcbv2uNcCPpknPluTznP+4uR8dQru1i4PD99YbAyPPE3pygy6BoaOo+9TJAm0MmekLGuSY0letsRhROjYBLZN6rmURcWrlJX1wKkdWSg/kIaSYRyl9RKBNLmeR5IeqZuG/LVlYxxYb/c8a7rAj5zOGX4QEiZH4lNO1fSUzcBiZx5wHUU/DFzDVS4H64CS9aNAu2HENHY8rVa4rktelNi2ha7rxFFMVVUMQ0/d9iwsx6Uqqxk0jhePU5EvDiNxOgis7QccAfieT9/3ZFlGGAZ/9UwxAx0pysT+H+skcSINIXEc0zQtTTfIOJo3mgB5UZDKsa/AC3QUoBzZPNg4lkX9Wv8GBrKJpxTKdkgFWtXN5R/PGhjE8eR0dnHVDBSHzzuLveWggpggOZHVHYbtzpewNWxUmHCSW95aiqVmsNJNkcWTaKmZPG0OIhmvDQwVsdDcmL0Xox18dpLttMCZJM9kzqeKIJNnk3eE5+YfRef2Ms5akkIcPhqKn1uLx43svLfRVSjQ/KJkUsY2zNCjks1/NH1bmh5Ly+cXp2busSIebYEAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;UnusedFinancialSets&quot;
        title=&quot;&quot;
        src=&quot;/static/c56dd1db51c329c62f6b77e69d4bd044/8c557/UnusedFinancialSets.png&quot;
        srcset=&quot;/static/c56dd1db51c329c62f6b77e69d4bd044/4edbd/UnusedFinancialSets.png 175w,
/static/c56dd1db51c329c62f6b77e69d4bd044/13ae7/UnusedFinancialSets.png 350w,
/static/c56dd1db51c329c62f6b77e69d4bd044/8c557/UnusedFinancialSets.png 700w,
/static/c56dd1db51c329c62f6b77e69d4bd044/b97f6/UnusedFinancialSets.png 958w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;To get what was used, I created the following query(it displays the number of unprocessed records per dimension set):&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;sql&quot;&gt;&lt;pre class=&quot;language-sql&quot;&gt;&lt;code class=&quot;language-sql&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;select&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; NumberOfRecords&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; DimensionHierarchy&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;NAME &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; DIMENSIONFOCUSUNPROCESSEDTRANSACTIONS &lt;span class=&quot;token keyword&quot;&gt;join&lt;/span&gt; DimensionHierarchy &lt;span class=&quot;token keyword&quot;&gt;on&lt;/span&gt; DIMENSIONFOCUSUNPROCESSEDTRANSACTIONS&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;FOCUSDIMENSIONHIERARCHY &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; DimensionHierarchy&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;RECID
&lt;span class=&quot;token keyword&quot;&gt;group&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;by&lt;/span&gt; DIMENSIONFOCUSUNPROCESSEDTRANSACTIONS&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;FOCUSDIMENSIONHIERARCHY&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; DimensionHierarchy&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;NAME&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The solution was to delete unused sets&lt;/p&gt;
&lt;h4 id=&quot;pending-workflow-tasks&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#pending-workflow-tasks&quot; aria-label=&quot;pending workflow tasks permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Pending workflow tasks&lt;/h4&gt;
&lt;p&gt;If you use workflow, you need to check that the number of tasks in a Pending status will not grow. You can check for such tasks in the &lt;strong&gt;Workflow history&lt;/strong&gt; form and if there are some old and unused Pending tasks - delete them.&lt;/p&gt;
&lt;h2 id=&quot;summary&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#summary&quot; aria-label=&quot;summary permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Summary&lt;/h2&gt;
&lt;p&gt;In this post, I tried to provide some examples of what can be found during the performance review. The original post that describes the review process is &lt;a href=&quot;https://denistrunin.com/performance-audit/&quot;&gt;here&lt;/a&gt;, all scripts related to it are available on my &lt;a href=&quot;https://github.com/TrudAX/TRUDScripts/blob/master/Performance/AX%20Technical%20Audit.md&quot;&gt;GitHub&lt;/a&gt;. If you see that something is missing or want to share some performance-related stories, feel free to post a comment.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[D365FO class extensions naming tool]]></title><description><![CDATA[The post describes a solution for naming extension classes in D365FO based on naming guidelines rules]]></description><link>https://denistrunin.com/d365utils-classextensionname/</link><guid isPermaLink="false">https://denistrunin.com/d365utils-classextensionname/</guid><pubDate>Thu, 12 Dec 2019 22:12:03 GMT</pubDate><content:encoded>&lt;p&gt;In D365FO Microsoft introduced a new concept of extension classes, which is different from standard elements. For example, for a form, you have the form design and related X++ code as one object. But for a form extension you create a form design as one AOT object and the code related to individual form extension components as separate AOT objects(extension classes). And this creates a new problem for developers - how to name these classes.&lt;/p&gt;
&lt;p&gt;Microsoft published some basic guidelines for naming conventions - &lt;a href=&quot;https://docs.microsoft.com/en-us/dynamics365/fin-ops-core/dev-itpro/extensibility/naming-guidelines-extensions#naming-extension-classes&quot;&gt;Naming guidelines for extensions-Naming extension classes&lt;/a&gt;, but it seems these rules are not even used inside Microsoft teams.&lt;/p&gt;
&lt;p&gt;The page provides some basic rules - technically extension classes are not new objects, so Suffix should be used instead of Prefix, and you need to create a distinction between objects with the same names(like form &lt;strong&gt;CustTable&lt;/strong&gt; and table &lt;strong&gt;CustTable&lt;/strong&gt;)&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/45638fde199115e430cbd1b7dda0d025/d3d45/MSGuide.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 76.57142857142857%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAAB2HAAAdhwGP5fFlAAACMUlEQVR42mVUiZKqQAz0/z/PUne9uAaQS24tBTWvOzC83VqqYmYYJunuJK6CIBDP88T3/cXiOJYwDMV1Xbnf7/L5fOT1esn7/Vbj+jVi/5rX8xm/W3VdK13XSVPXk28aadtWauyrupKiKOR6vaqVZSllVarnvijmdzDe04AmMDPCQNG5WBtjhMgvl0QSWJalkqYp9hf4TJIk0bM8L8DmAp/LMA7CZ9U0rWZTRFWlmbiuq1oej4cMw/DLns/hzzvaOI5TQC7KmZIaKEZRpNlJl3TosyyTXC0HwgkxLQFqnhW4qwHJm5BpKQ5Ii8XYHw5ygAWQgmcVApNqFEbKorRsqplZPWtIuNSL+gXQ83Q6yX6/l91uJ9vtVr6+v8RxXL30s0A1CjYVp1CJWGkNyB9+bDWkZ+au7/DxRLeaUdjqLhWH2UTskIky+ueCvjOhEQOkrLBBDxI1Ua7Xa/kG4v1sPI+iWH0MH0JvysTAi4aLwCp2piIziWqGC9ZYAPVsG5wzUITkDNb3t/+UmSnglAS+6kU9bS/GcbRUmlLwstKfi2Jp1zANyLbhZQ9BjsejuI4jPprbdT3sT9Pen6Tg5bZtVEOrnU1Qc1JImTOYpdk8Bakios+Xj+ul8dmHKaaGgXsUwRaRFf7V2MYEcnbOOoIcPRe0HewdoDujjfie681mo4Xh+RVzfL/dlDYnyj4rRtdAaGYPdj5PgflvM/Xm1KO+52sBWFUy6PoeyEaM4lMR2oD/AJNxaJDSjM9JAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Microsoft naming guide&quot;
        title=&quot;&quot;
        src=&quot;/static/45638fde199115e430cbd1b7dda0d025/8c557/MSGuide.png&quot;
        srcset=&quot;/static/45638fde199115e430cbd1b7dda0d025/4edbd/MSGuide.png 175w,
/static/45638fde199115e430cbd1b7dda0d025/13ae7/MSGuide.png 350w,
/static/45638fde199115e430cbd1b7dda0d025/8c557/MSGuide.png 700w,
/static/45638fde199115e430cbd1b7dda0d025/e996b/MSGuide.png 1050w,
/static/45638fde199115e430cbd1b7dda0d025/2cefc/MSGuide.png 1400w,
/static/45638fde199115e430cbd1b7dda0d025/d3d45/MSGuide.png 1614w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Some objects from the standard code follow these rules, but many of them don&apos;t. Let&apos;s check standard objects in 10.0.5 application:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token attribute&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;ExtensionOf&lt;/span&gt;&lt;span class=&quot;token attribute-arguments&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;tableStr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;InventTable&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; final &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AppTroubleshooting_InventTable_Extension&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;According to the guide above it should be InventTable&lt;strong&gt;AppTroubleshooting&lt;/strong&gt;_Extension&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token attribute&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;ExtensionOf&lt;/span&gt;&lt;span class=&quot;token attribute-arguments&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;formstr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;BudgetReservationCreate_PSN&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; final &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;BudgetReservationCreatePSN_Extension&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ExtensionOf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;formStr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;RetailStatementsPart&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; final &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;RetailStatementsPart_Extension&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;These two are against the rule - &quot;Don&apos;t name the extension just &lt;strong&gt;_Extension&lt;/strong&gt;.&quot;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token attribute&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;ExtensionOf&lt;/span&gt;&lt;span class=&quot;token attribute-arguments&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;formStr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;SalesEditLines&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;internal&lt;/span&gt; final &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;RevRecSalesEditLines_Extension&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ExtensionOf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;formStr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LedgerJournalTable&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;internal&lt;/span&gt; final &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;RevRecLedgerJournalTableForm_Extension&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here &quot;&lt;strong&gt;RevRec&lt;/strong&gt;&quot; is used as a prefix instead of a suffix, but what is more interesting that for the first element they used an additional &quot;&lt;strong&gt;Form&lt;/strong&gt;&quot; suffix but didn&apos;t add it to the second one.&lt;/p&gt;
&lt;p&gt;So organising a naming convention even within Microsoft teams is a quite hard task.&lt;/p&gt;
&lt;h2 id=&quot;why-this-is-important&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#why-this-is-important&quot; aria-label=&quot;why this is important permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Why this is important&lt;/h2&gt;
&lt;p&gt;Currently, there is no combined view in Visual Studio to view the final code(that includes all applied extensions and event handlers), so proper naming convention helps you to quickly find objects and avoid code duplication(where the same logical function is implemented in two different classes).&lt;/p&gt;
&lt;p&gt;It doesn&apos;t matter what rules you will follow, more critical is that within one project naming convention should be the same.&lt;/p&gt;
&lt;h2 id=&quot;solution-to-this-problem---automatic-extension-class-creation&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#solution-to-this-problem---automatic-extension-class-creation&quot; aria-label=&quot;solution to this problem   automatic extension class creation permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Solution to this problem - automatic extension class creation&lt;/h2&gt;
&lt;p&gt;First, you need to define the naming conventions for your project. Currently, 8 elements can have extension classes; you need to define naming rules for all these elements(I have seen several dev guides where only 2 or 3 types were specified).&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Class&lt;/li&gt;
&lt;li&gt;Table&lt;/li&gt;
&lt;li&gt;DataEntityView&lt;/li&gt;
&lt;li&gt;View&lt;/li&gt;
&lt;li&gt;Form&lt;/li&gt;
&lt;li&gt;FormDataField&lt;/li&gt;
&lt;li&gt;FormDataSource&lt;/li&gt;
&lt;li&gt;FormControl&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In addition to these rules, you also need to define where to put your event handlers. Technically event handlers are static methods and can be created in any class, but you should not put these static methods to extension classes(details can be found in this article - &lt;a href=&quot;https://daxmusings.codecrib.com/2018/06/accidental-code-extensions.html&quot;&gt;https://daxmusings.codecrib.com/2018/06/accidental-code-extensions.html&lt;/a&gt;). I think the best approach to use the same names as for extensions, but with the different suffix &lt;strong&gt;_EventHandler&lt;/strong&gt;, and for forms put all handlers into one class.&lt;/p&gt;
&lt;p&gt;So totally you need to define 16 rules.&lt;/p&gt;
&lt;p&gt;I created a setup form where you can define these naming rules and added a function to quickly specify an initial template (currently there are only two: with &quot;_&quot; and without).&lt;/p&gt;
&lt;p&gt;You can adjust the default settings and save it to file&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/4ab5a08912361fc89b3087d8d31395d3/0c3d0/SetupForm.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 55.42857142857143%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAB2HAAAdhwGP5fFlAAACHElEQVR42n2Sa08aQRSG+f9/oE0/tCataVTQWsQLRfGyCCLLIhdhlzsrRSENy3VvyNOZNW3SxDrJmzNnsvPs+55M6Gn4xOBnn8fHRx4e+ozHY/yVj+85+L6DF1T3rzxPyhfycF0X13FwbJv5bMZ8PidkzRZMJxaTyQTLsoK9Y/vMZqtAi/mK6VT0gTyWC1ucv1yWwKUtgK6P7XqiuoTUssFmJMbW/gm7h0kisQTRRI7t6B1fwlnCB5roDaEacaVLtW6i13XqjQbWZErraUr2vktON/k19wjl75tsHSSJnd9ydlMJdHipcpxSOc0WSQidq+I8W+JcE6CWSU+v8dBuY5omjUaTZrOJbhi0Wm1CemeAJqCt/oiGOeSuXKPT6TAcjrDFbOylzVLIEbNyRSzbGjPpdpkPBsGZ/OZPlQrdVLokbg1O0vfsxDMiepyUolCtVtF1nXw+T7FYpN/vI9d6veatFboptzlTDX5kKoTj1+wdJ1GurtA0TURoUalUKBQKIlqD0ejF9XKxYP38/DrwutgkmW8QvVB5v/mNnWgcRTiUztpiTtKldCgdp9PpoJd7+WxeBaYKdb4nVTZ2jviwuS8iH5NKKYEzQwxagmu1GplM5r+Qf4CKZhA+uebT9iHvPu/yde+Iq8tLVFUNIpfL5SCydCndrVart4EXuSofBWwjfBTUSOxUwHKUSiV6vV7wJCRUzlD+RD7mt4C/AZvaHzrTC/0IAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Setup form&quot;
        title=&quot;&quot;
        src=&quot;/static/4ab5a08912361fc89b3087d8d31395d3/8c557/SetupForm.png&quot;
        srcset=&quot;/static/4ab5a08912361fc89b3087d8d31395d3/4edbd/SetupForm.png 175w,
/static/4ab5a08912361fc89b3087d8d31395d3/13ae7/SetupForm.png 350w,
/static/4ab5a08912361fc89b3087d8d31395d3/8c557/SetupForm.png 700w,
/static/4ab5a08912361fc89b3087d8d31395d3/e996b/SetupForm.png 1050w,
/static/4ab5a08912361fc89b3087d8d31395d3/2cefc/SetupForm.png 1400w,
/static/4ab5a08912361fc89b3087d8d31395d3/0c3d0/SetupForm.png 1414w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Next step is to exclude manual work when you create extension classes. I extended my &quot;Create extension class&quot; add-in to automatically generate a class name based on these rules(this form can be called for any object that allows extension classes)&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/e50cb3f8536ed15dc13d98401c97e43b/e72de/CreateClassDialog.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 39.42857142857142%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAB2HAAAdhwGP5fFlAAABg0lEQVR42n2RW3OCMBCF/f+/p4+dcZzeFCstalvLHQIBK4IgbVHQ091YnT714ZuTbDYnu5veKo3wsVohyzLFdrvF8XhA17bouu5C+6v7lugOF5p9i+9dq+41TYNeWVUIggBhGCJJEryaLoZPb5jbAsa7r3haeAjjJaqygGFHGGhT3OkvuJ3MMRg94+bZwnpT0fkGPTYzTROWZcH3fWj6DFfXt+jf6xjPbGhTGyNCf3ExN308zFz0JwsMGP0d/cc3UhOrLEfJhmmaKjPHcRBFQl26mbxSBQsMDQtDNiTjoWHjgSoZTS1oM/uk09ODmmHSuNYnw6IosFwuIaUEm4sogRdK1WIQp/CFhBtEKuaQWm6g1Ke8M14YI89zbDZkyIuyLBHH0e8cJQqKfX99oaZByziGS9WLMEAiY0IiX2fY7xpFu9/h87NWZuylZsjtsgohqO0IjuuqmAhPe457nkePpajrGhV9JBfxF/5l7rLHztw2wwfqYzQN4/FYwXs2OOdw/n/8AJLBS3ndFQFnAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Create class dialog&quot;
        title=&quot;&quot;
        src=&quot;/static/e50cb3f8536ed15dc13d98401c97e43b/8c557/CreateClassDialog.png&quot;
        srcset=&quot;/static/e50cb3f8536ed15dc13d98401c97e43b/4edbd/CreateClassDialog.png 175w,
/static/e50cb3f8536ed15dc13d98401c97e43b/13ae7/CreateClassDialog.png 350w,
/static/e50cb3f8536ed15dc13d98401c97e43b/8c557/CreateClassDialog.png 700w,
/static/e50cb3f8536ed15dc13d98401c97e43b/e996b/CreateClassDialog.png 1050w,
/static/e50cb3f8536ed15dc13d98401c97e43b/e72de/CreateClassDialog.png 1198w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;As a result, the following class will be generated&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token attribute&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;ExtensionOf&lt;/span&gt;&lt;span class=&quot;token attribute-arguments&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;formstr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;CustTable&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
final &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CustTableForm_TST_Extension&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;summary&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#summary&quot; aria-label=&quot;summary permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Summary&lt;/h2&gt;
&lt;p&gt;You can download this Create class extension from the following link &lt;a href=&quot;https://github.com/TrudAX/TRUDUtilsD365/releases&quot;&gt;https://github.com/TrudAX/TRUDUtilsD365/releases&lt;/a&gt;. If you find that something is missing or can be improved don&apos;t hesitate to leave a comment. If you have your own rules you can also send them to me(or create a Pull request) and I will add them as an option for the default settings.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Comparing D365FO development VMs performance]]></title><description><![CDATA[Comparing the performance of 3 typical VM configurations for D365FO development]]></description><link>https://denistrunin.com/devvm-perfv10/</link><guid isPermaLink="false">https://denistrunin.com/devvm-perfv10/</guid><pubDate>Wed, 11 Sep 2019 20:12:03 GMT</pubDate><content:encoded>&lt;p&gt;D365FO version requires more resources to perform development. In this post, I try to compare 3 popular development configurations and describe the pros and cons for each.&lt;/p&gt;
&lt;p&gt;I have chosen the following VMs: Local Hyper-V Image, Azure VM based on SSD disks, Azure VM based on HDD disks.&lt;/p&gt;
&lt;p&gt;There are detail specifications of these VMs:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Local&lt;/th&gt;
&lt;th&gt;SSD&lt;/th&gt;
&lt;th&gt;HDD&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;VM Type&lt;/td&gt;
&lt;td&gt;Local Hyper-V Image&lt;/td&gt;
&lt;td&gt;Standard D8s v3&lt;/td&gt;
&lt;td&gt;Standard D12 v2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CPU&lt;/td&gt;
&lt;td&gt;Core i7-8700 3.2GHz, 6 cores, 24 GiB memory&lt;/td&gt;
&lt;td&gt;E5-2673 v4 2.30GHz, 8 vcpus, 32 GiB memory&lt;/td&gt;
&lt;td&gt;E5-2673 v4 2.30GHz, 4 vcpus, 28 GiB memory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage&lt;/td&gt;
&lt;td&gt;Samsung 970(more than 100k IOPS)&lt;/td&gt;
&lt;td&gt;5 premium disks&lt;/td&gt;
&lt;td&gt;16 HDD disks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Run cost&lt;/td&gt;
&lt;td&gt;Box for run 3 VMs - around 1.5k$&lt;/td&gt;
&lt;td&gt;0.75$ per hour&lt;/td&gt;
&lt;td&gt;0.52$ per hour&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage cost&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;~4$ per day&lt;/td&gt;
&lt;td&gt;~0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Both 3 VMs have used the same D365FO version - 10.0 PU24. After installation I disabled the following services:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Microsoft Dynamics 365 Unified Operations: Batch Management Service&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Microsoft Dynamics 365 Unified Operations: Data Import Export Framework Service&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Management Reporter 2012 Process Service&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;overall-system-performance-tests&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#overall-system-performance-tests&quot; aria-label=&quot;overall system performance tests permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Overall system performance tests&lt;/h2&gt;
&lt;p&gt;First, let&apos;s compare overall system performance by running a full compile and full DB sync. They are not frequent operations for Dev machines, but they are very resource-intensive and it allows us to find out VMs overall capacity.&lt;/p&gt;
&lt;p&gt;For the compile task I got the following results:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/8a3d561ad1f10d8468457b0d556ea874/9a1cf/FullCompileTime.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 48.57142857142858%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAB2HAAAdhwGP5fFlAAABT0lEQVR42p2Ty0rDQBSG8xDu3KgP4TN1J1gVpRe7VNwpdmONVUHRWqQBQbDYjYLu1II3XDTaKGglNElzMcn8ziRRk6Yi9cDHmes/58yc4VRVg2EYMBmmCV3Xvb7jOPiPcYQQML4taEbG/rDwWu6t1UJubgFj0ykk07MYT2X7YiKTQyI5hd2K4AsqNOW1nRKW+CLyxQ0s90l+fROLBR4nZ+e+oKyb2JYMrIg6+Ecdq93Q8YLo+16wuaZmeXfFEuc61gcOmjJKjXeUxSh7FOFJRvVZxZGk/MqrZvwIvmgKRk8PMXi8j+FaBUMBIzUBA9UyEnWaim17i73L7/FYkUdp01KZf7jGzO0lMndXSAdk7+uYvLnAltQAXAIXzBEPEhTDF25YkLguGLFT7Xgd2jRSRld4MC0rWoc2FXSoD2M5dHMQkdbRoKgq2ooSF6QW/gSfM8LJK3u7V7EAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Full compile time&quot;
        title=&quot;&quot;
        src=&quot;/static/8a3d561ad1f10d8468457b0d556ea874/8c557/FullCompileTime.png&quot;
        srcset=&quot;/static/8a3d561ad1f10d8468457b0d556ea874/4edbd/FullCompileTime.png 175w,
/static/8a3d561ad1f10d8468457b0d556ea874/13ae7/FullCompileTime.png 350w,
/static/8a3d561ad1f10d8468457b0d556ea874/8c557/FullCompileTime.png 700w,
/static/8a3d561ad1f10d8468457b0d556ea874/9a1cf/FullCompileTime.png 924w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Compile is a CPU intensive task.&lt;/p&gt;
&lt;p&gt;What is interesting here - SSD VM time is very close to HDD despite of the fact that SSD has 8 cores and HDD has 4 cores. The main reason for this - is that Dv3 series has CPUs with Hyperthreading enabled but Dv2 has CPUs with Hyperthreading disabled. Hyperthreading gives only a small boost, that is why it is very important when you plan you virtual infrastructure to keep in mind - when we say for example &apos;8 core VM&apos; - whether these are real cores or virtual ones.&lt;/p&gt;
&lt;p&gt;Local VM has CPU with a higher clock speed and CPU itself has 6 physical cores - that explains more than 2 times difference in performance compared to the Azure-based machines.&lt;/p&gt;
&lt;p&gt;Next test is a database synchronize:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/0d65a667b24a5fecf73c30627452b60a/6bff2/FullSyncTime.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 42.857142857142854%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAB2HAAAdhwGP5fFlAAABY0lEQVR42pWSTU/CQBCG+9v0InrQX+BFD2IwKly8mvgXPOjF+EG8GDWeNEZsDAfk4+BBRUKh0A/BxAQolbLt9nV3LaQ0JsZJnsx22pm+MzuSbdtwXQJCCPMu/muUUgwGA1iWBc/zIFl9Gw3dgGa+o2mY4qxquvBhorHmGB1mqy0Kc5PkbBZLiTWsJlOIbyYZqT9Z2Uhief2HxXgCW9s7QiHvUHprf+Ig/4yT4iuOA44KL+MzJ10q4zQgXSzj6qmCiqKgWlehqCrrzIDv+wKp2hniTCO40H/nknHY+MJevY/9moVdpYdzw4bjOGJmYRMFr1s6pnJ3mMvLmA2IPd4Lz2PTuQxu2wZYP/BYAg3gyXxuI2Xjgjes4ExBxkLpAfMReCxWlJH5MAHiwo/c8KjQhELKZUdeILix6HpMJFOftTwZo+xZ8tiHhBV0QwzZT7jnE3LYfnZ7PXS6XbFvYTU0IoRSH9/Kz4Kd78iwrgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Full Sync time&quot;
        title=&quot;&quot;
        src=&quot;/static/0d65a667b24a5fecf73c30627452b60a/8c557/FullSyncTime.png&quot;
        srcset=&quot;/static/0d65a667b24a5fecf73c30627452b60a/4edbd/FullSyncTime.png 175w,
/static/0d65a667b24a5fecf73c30627452b60a/13ae7/FullSyncTime.png 350w,
/static/0d65a667b24a5fecf73c30627452b60a/8c557/FullSyncTime.png 700w,
/static/0d65a667b24a5fecf73c30627452b60a/6bff2/FullSyncTime.png 957w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Synchronize operation is IO and CPU-intensive task. Local VM has a more powerful IO system, and a more powerful CPU, that explains the better result. SSD VM performed much better compared to HDD in this test due to faster disks.&lt;/p&gt;
&lt;h2 id=&quot;daily-task-tests&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#daily-task-tests&quot; aria-label=&quot;daily task tests permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Daily task tests&lt;/h2&gt;
&lt;p&gt;In order to test performance for more frequent developer tasks I chose 2 tasks - time to hit breakpoint and time to display &apos;Hello world&apos; message from the job. In AX2012 both these tasks have near-zero execution time, you don&apos;t need to wait.&lt;/p&gt;
&lt;h3 id=&quot;time-to-hit-breakpoint-test&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#time-to-hit-breakpoint-test&quot; aria-label=&quot;time to hit breakpoint test permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Time to hit breakpoint test&lt;/h3&gt;
&lt;p&gt;Before the test I opened the AX main screen, to warm the system cache.&lt;/p&gt;
&lt;p&gt;To prepare for this test I switched off &apos;Load symbols for items in the solution&apos;. Then I opened AOT, searched for &lt;strong&gt;SalesTable&lt;/strong&gt; form and added it into the new project. Marked the form as a startup object. After that opened the code and added a new breakpoint to the &lt;strong&gt;init()&lt;/strong&gt; method.&lt;/p&gt;
&lt;p&gt;Time in this test - is the time between I pressed &lt;strong&gt;Start&lt;/strong&gt; and the time when the breakpoint was hit.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/f1e913952f6a2cd0101033934b9738c7/c1eae/HitTheBreakpoint.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 30.28571428571429%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAGABQDASIAAhEBAxEB/8QAFwABAAMAAAAAAAAAAAAAAAAAAAECBf/EABUBAQEAAAAAAAAAAAAAAAAAAAAB/9oADAMBAAIQAxAAAAHVsJIX/8QAFxAAAwEAAAAAAAAAAAAAAAAAAAISAf/aAAgBAQABBQJVIwg//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAFxAAAwEAAAAAAAAAAAAAAAAAAAExkf/aAAgBAQAGPwJWFelen//EABoQAAICAwAAAAAAAAAAAAAAAAERABAhMVH/2gAIAQEAAT8hEieXUKjtp3//2gAMAwEAAgADAAAAEP8A7//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8QP//EABURAQEAAAAAAAAAAAAAAAAAAAAR/9oACAECAQE/EKr/xAAaEAEAAgMBAAAAAAAAAAAAAAABABEhMYGR/9oACAEBAAE/EFuRBbe6GXr0IOs8HP/Z&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Breakpoint image&quot;
        title=&quot;&quot;
        src=&quot;/static/f1e913952f6a2cd0101033934b9738c7/29d31/HitTheBreakpoint.jpg&quot;
        srcset=&quot;/static/f1e913952f6a2cd0101033934b9738c7/e52aa/HitTheBreakpoint.jpg 175w,
/static/f1e913952f6a2cd0101033934b9738c7/70ebb/HitTheBreakpoint.jpg 350w,
/static/f1e913952f6a2cd0101033934b9738c7/29d31/HitTheBreakpoint.jpg 700w,
/static/f1e913952f6a2cd0101033934b9738c7/c1eae/HitTheBreakpoint.jpg 949w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Two tests were performed to see how the cache changes this time&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/b0990ed9b088e3eadeee9e64b3b42310/1dbe8/TimeToHitBreakpoint.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 48.57142857142858%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAB2HAAAdhwGP5fFlAAABDUlEQVR42qVR0UoDMRDM/78q/oIgtuKD4EFBsEWvZ9tooa3SWu9U6IOC2CbWmMtOkxyphwg9bciwk81kmd0wuZCYzwWE/IDROcjQv+EWU8tPaDLQMCAqktsslvEpkv0merVLdC2uj9rg9difXayC3qF9d5JAKQXWHM2wGw2x17jFQWOA8cUQafceaWeCzMYqcNqnmwfkeQ427ado1WLEx1eYPb/CTgN+V2y/rHOctazDnWiETjKGeHkrLuyAjSlmugk/ddZhZh220T/lkO+icIgtHJ7xDOcRx2NyB7VUoF+Efyr4RbQu4uyjxIM4tBPyQRdaDtx/ik/QdyI81Fp77uJCCEgp1xqHULzMnXYFJJr7vQqGkmQAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;TimeToHitBreakpoint results&quot;
        title=&quot;&quot;
        src=&quot;/static/b0990ed9b088e3eadeee9e64b3b42310/8c557/TimeToHitBreakpoint.png&quot;
        srcset=&quot;/static/b0990ed9b088e3eadeee9e64b3b42310/4edbd/TimeToHitBreakpoint.png 175w,
/static/b0990ed9b088e3eadeee9e64b3b42310/13ae7/TimeToHitBreakpoint.png 350w,
/static/b0990ed9b088e3eadeee9e64b3b42310/8c557/TimeToHitBreakpoint.png 700w,
/static/b0990ed9b088e3eadeee9e64b3b42310/e996b/TimeToHitBreakpoint.png 1050w,
/static/b0990ed9b088e3eadeee9e64b3b42310/1dbe8/TimeToHitBreakpoint.png 1374w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;HDD VM was very slow in this test. You need to wait almost 5 minutes to see your first breakpoint! SSD and Local VMs first run was the same, but the second run Local VM was faster.&lt;/p&gt;
&lt;h3 id=&quot;hello-world-test&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#hello-world-test&quot; aria-label=&quot;hello world test permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Hello world test&lt;/h3&gt;
&lt;p&gt;This test was performed straight after the breakpoint test, but I restarted Visual Studio. In this test I created a new project and added a Runnable class with the following code&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token function&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Hello world&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;On the second run, I changed this test to &quot;Hello world2&quot;. On the Third run I didn&apos;t change the text, just run the same job.&lt;/p&gt;
&lt;p&gt;I measured the time between pressing Start and the time when the message displayed in the browser.&lt;/p&gt;
&lt;p&gt;Here are the results:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/8e6252d354a5ffddb624b450856344af/8dd93/HelloWorldTest.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 49.142857142857146%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAB2HAAAdhwGP5fFlAAABfElEQVR42pWSTU/CQBCG++eN8cYf8KZnTxqR0hZbQYMgLZSvkEgCgmBiYiztFnb3dXa1TSV6YJMnOzOdbJ6drsHSFEkUYxMzJPEG2zSGEBLyEKREtowkSZDGMVIpIGQMzj9Q+H7wMviOo99comVN0XZmaFsTtKtdPJq/aVaCPG5Ve9RDWCGaZR9jf4qEMW1Lhhs8tE5h1o5hu0ewHy9h9dfwxiu4oxXta00WO4NXmMELTH+uuXmaoT55w4ZuKoVQhjuMGi46N5cIzCsEdh1db0j0ERBdb5Dj10IsRnNwsc2vWJyfig3GYtx3zmHelWA3SrDapjZ0yfCWrFxl90ON8tnqA3y31XNW6B8oCwd+G3roVK7J8IIMHQTuCD1l5Q5oH+aofHg/RvQZ5WZ/GtabZyhbJ6i0fFTDdzjhAna4LLDQNbO3gD9Zgal5/XdlSc9F8meAD6gSofhi9puzJWj4Wb4fGyoRhPwpcM51QzFOEoYoisBYqueV1fcPVPUvQhnp66Hdj+wAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Test&quot;
        title=&quot;&quot;
        src=&quot;/static/8e6252d354a5ffddb624b450856344af/8c557/HelloWorldTest.png&quot;
        srcset=&quot;/static/8e6252d354a5ffddb624b450856344af/4edbd/HelloWorldTest.png 175w,
/static/8e6252d354a5ffddb624b450856344af/13ae7/HelloWorldTest.png 350w,
/static/8e6252d354a5ffddb624b450856344af/8c557/HelloWorldTest.png 700w,
/static/8e6252d354a5ffddb624b450856344af/e996b/HelloWorldTest.png 1050w,
/static/8e6252d354a5ffddb624b450856344af/8dd93/HelloWorldTest.png 1369w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;You need to wait almost a minute for the HDD to see the results of a simple job. For Local and SSD it is 70% faster. Local VM also executed the job faster if it was not changed - probably due to a high single-core CPU speed(but you still need to wait 7 second, it is not instant)&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#conclusion&quot; aria-label=&quot;conclusion permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;For D365FO typical development actions can take longer time comparing to AX2012 where most operations were near-instant. But, by choosing a proper hardware for Development VM you can compensate this time to some extent. There is no right answer what to choose, you need to consider your situation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If you want maximum performance and can buy a new hardware(and now you can buy a PC that has 10-20% more &lt;a href=&quot;https://www.cpubenchmark.net/singleThread.html&quot;&gt;speed&lt;/a&gt; than mine) - Local VM is the best choice, but this VM is hard to manage.&lt;/li&gt;
&lt;li&gt;Azure Premium disks VM(SSD) is the best choice if you can spend a little bit more for the cloud. It costs 6$ more per day(10 hours) than HDD, but provides a noticeable performance boost. But you need to pay for the storage - if you use this VM only sometimes it can be expensive.&lt;/li&gt;
&lt;li&gt;Azure standard disks(HDD) VM is the most commonly used configuration, but according to my tests, it is not the best choice for an active project. If you just do a simple math(typical consulting rate is 180$ per hour(3$ per minute), 5 minutes wait for the first breakpoint will cost you more than the daily price difference with SSD VM)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I also will try to repeat the same tests after the next D365FO release, it will be interesting to compare the progress in this area.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[How to increase your AX2012R3 database synchronisation speed]]></title><description><![CDATA[Describes custom plan command that can increase AX2012 database synchronisation speed]]></description><link>https://denistrunin.com/ax2012-syncfix/</link><guid isPermaLink="false">https://denistrunin.com/ax2012-syncfix/</guid><pubDate>Wed, 04 Sep 2019 22:12:03 GMT</pubDate><content:encoded>&lt;p&gt;Time to synchronise AX2012 database was always a pain point for production databases. Recently I found an interesting AxForum &lt;a href=&quot;https://translate.google.com/translate?hl=en&amp;#x26;tab=TT&amp;#x26;sl=ru&amp;#x26;tl=en&amp;#x26;u=http%3A%2F%2Faxforum.info%2Fforums%2Fshowthread.php%3Fp%3D418755%23post418755&quot;&gt;topic&lt;/a&gt; by Masel that is probably worth sharing.&lt;/p&gt;
&lt;p&gt;If you want to execute database synchronisation faster, you need to create the following plan guide in the main AX database(not the _model):&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;sql&quot;&gt;&lt;pre class=&quot;language-sql&quot;&gt;&lt;code class=&quot;language-sql&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;DECLARE&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;@stmt&lt;/span&gt; nvarchar&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;max&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;DECLARE&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;@params&lt;/span&gt; nvarchar&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;max&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;EXEC&lt;/span&gt; sp_get_query_template
    N&lt;span class=&quot;token string&quot;&gt;&apos;select name, change_tracking_state_desc from sys.columns AS Cols inner join sys.fulltext_index_columns AS FTSCols inner join sys.fulltext_indexes as FTS on FTSCols.object_id = FTS.object_id on Cols.object_id = FTSCols.object_id where Cols.column_id = FTSCols.column_id and Cols.object_id = object_id(&apos;&apos;SYSINETCSS&apos;&apos;)&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token variable&quot;&gt;@stmt&lt;/span&gt; OUTPUT&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token variable&quot;&gt;@params&lt;/span&gt; OUTPUT&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;select&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;@stmt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;EXEC&lt;/span&gt; sp_create_plan_guide
    N&lt;span class=&quot;token string&quot;&gt;&apos;SyncTemplateGuide&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token variable&quot;&gt;@stmt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    N&lt;span class=&quot;token string&quot;&gt;&apos;TEMPLATE&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token boolean&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token variable&quot;&gt;@params&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    N&lt;span class=&quot;token string&quot;&gt;&apos;OPTION(PARAMETERIZATION FORCED)&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I tested this script on 2 different systems(the slow and fast one):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;AX2012R3 CU9, Database on HDD disks, CPU: E5-2630 2.3GHz&lt;/li&gt;
&lt;li&gt;AX2012R3 Feb2019, Database on SDD disks, CPU: Core i7-8700 3.5GHz&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In both cases it gave a considerable synchronisation speed boost(about 300% for the fast system). You can see the sync time before and after applying this fix below:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/a61cad5f7eb68cde716548a7497bd89e/cdef6/SyncGraph.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 58.285714285714285%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAB2HAAAdhwGP5fFlAAABf0lEQVR42pWSwS8DQRTG989yEQfiJg4SocIBdRU3FyEq7gSJk0jcenSVaOihEj2IRKhQaUXLdqs7O7vb3Z2dz8y2Zbst1Um+vHkz7/0y771RiGGAWhaoaYLoBJSasG0b9XodVtNyzvHfpVBKodtOAK18qDCE3w+gAxg9iML+gneLbQPK65rPoflAtSXGf/YhlS0PJdMNrJTDfEmE4nnCcRy4jgvHdXGYfcFa6gGJixw2I0pcNrSVfsTeXQUH9xr2haR9JXbwJMUVEDkECZV2fWkVs4MTiI/OYHEk9q0FobnhGKaHJhEfm0dV+wwqYqIin/9WsjjIVQhuyjVkCyoyT2+4ei4hI5TNl6G+q6ipGnQJ8xsldvTQEtOVkq+T32Q3dYuVZBo71wWcFC0c5wmO8gaSRQrqeL2H4ooeSjHGgrK3lzcwNTCO89OzIMgX5+GEMKTnlKNB3QB9Absl+CHfF33jEb8tVvgdwHCQ3LNmyZ74DTohQZ9bS345Hsr1PIYvAsmLcHgb4OwAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Compare the time&quot;
        title=&quot;&quot;
        src=&quot;/static/a61cad5f7eb68cde716548a7497bd89e/8c557/SyncGraph.png&quot;
        srcset=&quot;/static/a61cad5f7eb68cde716548a7497bd89e/4edbd/SyncGraph.png 175w,
/static/a61cad5f7eb68cde716548a7497bd89e/13ae7/SyncGraph.png 350w,
/static/a61cad5f7eb68cde716548a7497bd89e/8c557/SyncGraph.png 700w,
/static/a61cad5f7eb68cde716548a7497bd89e/e996b/SyncGraph.png 1050w,
/static/a61cad5f7eb68cde716548a7497bd89e/cdef6/SyncGraph.png 1163w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The technique of this optimization is quite unusual, by creating this plan_guide you disable SQL plan creation based on actual SQL statement parameters. It is in general very similar to X++ &lt;strong&gt;forceplaceholders&lt;/strong&gt; command. AX database synchronisation process sends a lot of small requests, and excluding the plan creation step gives this performance effect.&lt;/p&gt;
&lt;p&gt;Enjoy and thank Masel for sharing this.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[How to read Excel and CSV files in D365FO using X++]]></title><description><![CDATA[Helper classes to read the data from Excel(xlsx) and CSV files using X++ code]]></description><link>https://denistrunin.com/xpptools-readexcelfile/</link><guid isPermaLink="false">https://denistrunin.com/xpptools-readexcelfile/</guid><pubDate>Wed, 03 Jul 2019 20:12:03 GMT</pubDate><content:encoded>&lt;p&gt;Sometimes you need to write X++ code to read the data from Excel(xlsx) or CSV files in D365FO.&lt;/p&gt;
&lt;p&gt;Typical scenario for this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;User interface operation, for example, a dialog with some parameters, where user can  specify a file. Then this operations reads the file and performs some actions(in some cases standard Excel add-in or Data management module or &lt;a href=&quot;https://ievgensaxblog.wordpress.com/2019/07/02/msdyn365fo-how-to-import-csv-file-using-electronic-reporting-part-5-run-import-from-x-code/&quot;&gt;Electronic reporting&lt;/a&gt; can perform the same task)&lt;/li&gt;
&lt;li&gt;A batch job that reads files from the network share(Azure storage, see &lt;a href=&quot;https://ievgensaxblog.wordpress.com/2017/07/16/d365fo-working-with-azure-file-storage/&quot;&gt;example&lt;/a&gt;) and processes them(as standard DMF doesn&apos;t support import in transaction, in case you have multi-line documents, you need to write custom code)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In this blog post, I provide an example of X++ classes that can be used to read XLSX and CSV files.&lt;/p&gt;
&lt;h2 id=&quot;file-reading-engines&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#file-reading-engines&quot; aria-label=&quot;file reading engines permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;File reading engines&lt;/h2&gt;
&lt;p&gt;To read an Excel file I use &lt;strong&gt;EPPlus&lt;/strong&gt; library(&lt;a href=&quot;https://github.com/JanKallman/EPPlus&quot;&gt;https://github.com/JanKallman/EPPlus&lt;/a&gt;). The big advantage of this library that it is already a part of D365FO installation, you don&apos;t need to add external references.&lt;/p&gt;
&lt;p&gt;With CSV file it is more complex. Standard D365FO installation doesn&apos;t include libraries that can read CSV format(it is quite complex). Often people use &lt;strong&gt;TextIO&lt;/strong&gt; class that can read simple delimiter separated files, but this class can&apos;t handle more complex scenarios(for example delimiter symbol is presented in the data, or &quot;new line&quot; symbol is in the data). To read such files I use &lt;strong&gt;Microsoft.VisualBasic.FileIO&lt;/strong&gt; library. It contains the proper CSV format reader, so if a file can be opened in Excel, this library can read it. (Note: This library is a part of D365FO installation and exists in .NET Core if you concern about future, but if you don&apos;t want to add a reference for some reason, I also included comments in DEVFileReaderCSV how to switch it to TextIO)&lt;/p&gt;
&lt;h2 id=&quot;reader-classes&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#reader-classes&quot; aria-label=&quot;reader classes permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Reader classes&lt;/h2&gt;
&lt;p&gt;As reading CSV and XLSX is very similar from the programming perspective I created one base class &lt;strong&gt;DEVFileReaderBase&lt;/strong&gt; and two derived &lt;strong&gt;DEVFileReaderCSV&lt;/strong&gt; and  &lt;strong&gt;DEVFileReaderExcel&lt;/strong&gt;. Reading often includes the following stages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Open the file and read its content to the container, close the file&lt;/li&gt;
&lt;li&gt;Read the header row (if your file contains headers)&lt;/li&gt;
&lt;li&gt;Loop though rows&lt;/li&gt;
&lt;li&gt;Get the cell value for the current row (this can be done by column name - if you have the header row, or by column index)&lt;/li&gt;
&lt;li&gt;Try to convert the cell value to the required type(for CSV it will be always &quot;string to type&quot; conversion, for xlsx - convert from the type of cell to the required AX type)&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;//Sample code to read an Excel file&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;DEVFileReaderExcel&lt;/span&gt;   fileReader   &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;DEVFileReaderExcel&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
fileReader&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;openFile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;memoryStreamFile&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
fileReader&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;readHeaderRow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fileReader&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;readNextRow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;strFmt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;row: %1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; fileReader&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getCurRow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;strFmt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;%1, %2, %3&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                fileReader&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getStringByName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Main account&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                fileReader&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getStringByName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;BusinessUnit&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                fileReader&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getRealByName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Amount&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
               &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//Sample code to read a CSV file&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;DEVFileReaderCSV&lt;/span&gt;   fileReader   &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;DEVFileReaderCSV&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
fileReader&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;readCSVFile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;memoryStreamFile&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
fileReader&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;readHeaderRow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fileReader&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;readNextRow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;strFmt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;row: %1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; fileReader&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getCurRow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;strFmt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;%1, %2, %3&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                fileReader&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getStringByName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Main account&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                fileReader&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getStringByName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;BusinessUnit&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                fileReader&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getRealByName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Amount&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
               &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Both examples print out the file content to the infolog&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/eed912099c56f1cb1e6b488559272d53/f793b/FileToInfolog.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 43.99999999999999%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAB2HAAAdhwGP5fFlAAACL0lEQVR42iWRzW7TUBCF8ya8AGwQYscDdNWIAgUJxAIegA0bEAipiwpRqQWVBWwREmuEWECB1AVaoGnjps2PHec/TmzHjn/bJE75uDaWjs7M3Htnzhxn3h32mcVjXG9EPDlhOj1JORYsDhi5FpeWbnPxyXVefnrLvTfLnH0wL5DlwuOrnHuYTXH+0UJaz5y5/5FrazmyKxssrm1y44WUcnblK3PLG8w/+8IH6T27R38I3QjHdcirRfJKEUVvcthSOGhU2dfK/K7IZK6Ih4vPJe682uHm+ndurUvcfb3DwqrE3NMcl1c3KSsVLL1LrV7HGBj4rsdo6BC4PpEfEfgmXq+NZwzJRIE49HxcPyCIEgUek3jGNI5Jvmk8RTcMTIFer4dhmJimiW3bWJbFYDDAdixsyxS5SSaMjtnSfCTFZq97jNyfUDRmFM1TwacU9DGNTpcwCPE8738D20lz13VxHKFUxGEY4fs+mUAE31SfzyWLH5rLz3rAXn9GwfiLbCJiMaBSpdNu0Wg0aLfbQqVBq9VCVVWazSa6rlOr1eh0OqKh6H7Udih1HOpmRNMeow4CYbiH2g+o9kb82s+zvb2dPkpWDaOQglxAUZRUcTJA07TUEqEwYNDXqZRLaDU15SS3h0MBS1wekJf3kGVZrBYwHo/xA59StUQkPJ9MJoxGo7SeeJsJw5Cu6CxJW+RyuRQHB8V0eoJSuSwU7qbrJn75yQ8U3rU6rTRPfE1UJ7VE6T/QQHS0XS6DggAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;FileToInfolog&quot;
        title=&quot;&quot;
        src=&quot;/static/eed912099c56f1cb1e6b488559272d53/8c557/FileToInfolog.png&quot;
        srcset=&quot;/static/eed912099c56f1cb1e6b488559272d53/4edbd/FileToInfolog.png 175w,
/static/eed912099c56f1cb1e6b488559272d53/13ae7/FileToInfolog.png 350w,
/static/eed912099c56f1cb1e6b488559272d53/8c557/FileToInfolog.png 700w,
/static/eed912099c56f1cb1e6b488559272d53/e996b/FileToInfolog.png 1050w,
/static/eed912099c56f1cb1e6b488559272d53/2cefc/FileToInfolog.png 1400w,
/static/eed912099c56f1cb1e6b488559272d53/f793b/FileToInfolog.png 1404w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;generate-user-dialog&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#generate-user-dialog&quot; aria-label=&quot;generate user dialog permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Generate user dialog&lt;/h2&gt;
&lt;p&gt;To create a user dialog for the file import I extended my &lt;strong&gt;Create RunBase class&lt;/strong&gt; utility(&lt;a href=&quot;https://github.com/TrudAX/TRUDUtilsD365#runbase-class-builder&quot;&gt;https://github.com/TrudAX/TRUDUtilsD365#runbase-class-builder&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/a966c17a6e6f7c1e11ce9e5cfb0be4f5/6f464/CreateRunBase.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 40.57142857142858%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAB2HAAAdhwGP5fFlAAABwElEQVR42k1Sa4vTQBTN///gV0EXWRF2XVRW3F0KFkSFLWubNTZN0rwfTdMmqUm6zaM1jx5vBipeOJyZIXPmnnPDRXGM5HeMmDjLUrRtg2PXEbc4Hjt0XfsPTVPjcDigqirkeY79vkZRtCjLHiV2ux04SXMgzzVMJQXTmQLNtOH6AVsLUwm26zM43hL+cgXLMgk2ZjMRth0Qh1DVGIZhsjPu/MMQZ1d3OHt7h5eXt3j1bkB8g+dvPhKu6fyW4WowAi/b2JCTIFgRAnieg/V6icWi5zXtPXBj+mgs6hDmLkTdx0SyMZEdPM4X4BUPY9rfCxpGvwxozhJZmkJRFGy3W4rkyCKQZYXEFgjDEBwvmfghKJB0D6PJFLwwY7YtdwF/FWKblwjWMTZJhvSpYNlFUcQy66tpGiaeZRnLnRvyBgb3Ei5uvuHZi0vKUsW+KtnFjobTd3GqgoYQRTFEUaQcLWaR53lmP0kSmKZJgmMV18MHvH5P2V18wkQQkaYJe7F/ua+TaHGoWXcnMcdxGPdifQO+74P78mjiu2Dh608Dnx8UmO6SfqMNy6aua/xfefUHO7qoqip0XafJGqy73smp/gIlnERLWuXx0gAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;CreateRunBase&quot;
        title=&quot;&quot;
        src=&quot;/static/a966c17a6e6f7c1e11ce9e5cfb0be4f5/8c557/CreateRunBase.png&quot;
        srcset=&quot;/static/a966c17a6e6f7c1e11ce9e5cfb0be4f5/4edbd/CreateRunBase.png 175w,
/static/a966c17a6e6f7c1e11ce9e5cfb0be4f5/13ae7/CreateRunBase.png 350w,
/static/a966c17a6e6f7c1e11ce9e5cfb0be4f5/8c557/CreateRunBase.png 700w,
/static/a966c17a6e6f7c1e11ce9e5cfb0be4f5/e996b/CreateRunBase.png 1050w,
/static/a966c17a6e6f7c1e11ce9e5cfb0be4f5/2cefc/CreateRunBase.png 1400w,
/static/a966c17a6e6f7c1e11ce9e5cfb0be4f5/6f464/CreateRunBase.png 1464w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Right now it accepts Excel or CSV value in the &quot;Add file upload&quot; parameter.&lt;/p&gt;
&lt;p&gt;If you enter the following parameters into this utility&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;DEVReadFromFileExample2
Read From Excel


excel

LedgerJournalNameIdDaily*
TransDate*&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;it automatically generates the required code to read a file in a RunBase dialog&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/604ef6875fed0de8702d0a4f1ec6a2e6/a8979/ExcelDialog.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 47.42857142857142%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAB2HAAAdhwGP5fFlAAAB50lEQVR42m2RTW/TQBCG89MQd8R/4MCZ/wDigOgBUDkmQglNAgVB1EKrgoA7gqZVGydtPto4dmN7HX/Fju3EDxu3NCpipdGOVjvPvO9MYf9ng4PmDof7O5y2v/Cr+YP61lfeffom4zubjT3WXu9y98kWj1595unGHrphEc8iwjDE9z3cwM/zSEbBFC7TOGUxX+CECSPbQR+rxHFMIt9gQVMZcPveQ27df8ydB2u0u2eMVBVN01HVy79/T0GzJoRJKtOMNJ3jBzGBFxBPp0SOSyahhiVovH/L9odNdrc/YguB53m5qvl8TpZl/wOCF8V0z7q5QmGOsfURE2FydNyiVnvD+vpLnj1/gWmasnmaw/49N4CGPeGwo6H0hLTio7QMen2f3wdD6vUapVKJYrEogVaubqlyKp0sFcbpIo+CfgPoctTpczIYonRO6Zx0ZVHIuW5RrVWpVCpSaR3btkmThCiK8uUkUq3hRGgioHAhHEm+lL7sYBgGY10jkEWuZcnNTVH1C6rVKuVyOb8tYcvmDl44I0ozomRlfQW8GqwQFm2lzWgwoNNqMez36R0rUmHtGihkoySakczi/A79YAVUTZvpleXlLGbShi1n6ToOpiwMfR/tXL0GbkjgcsvSM4soJJOzTIIV8A8kGZBotULjRQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;ExcelDialog&quot;
        title=&quot;&quot;
        src=&quot;/static/604ef6875fed0de8702d0a4f1ec6a2e6/8c557/ExcelDialog.png&quot;
        srcset=&quot;/static/604ef6875fed0de8702d0a4f1ec6a2e6/4edbd/ExcelDialog.png 175w,
/static/604ef6875fed0de8702d0a4f1ec6a2e6/13ae7/ExcelDialog.png 350w,
/static/604ef6875fed0de8702d0a4f1ec6a2e6/8c557/ExcelDialog.png 700w,
/static/604ef6875fed0de8702d0a4f1ec6a2e6/e996b/ExcelDialog.png 1050w,
/static/604ef6875fed0de8702d0a4f1ec6a2e6/2cefc/ExcelDialog.png 1400w,
/static/604ef6875fed0de8702d0a4f1ec6a2e6/a8979/ExcelDialog.png 1828w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;performance-testing&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#performance-testing&quot; aria-label=&quot;performance testing permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Performance testing&lt;/h2&gt;
&lt;p&gt;Let&apos;s test the performance. To perform a test I created an Excel file with 10k lines and 10 columns with different types(100k cells total)&lt;/p&gt;
&lt;p&gt;The main code for this performance testing is the following(full example is available in the &lt;strong&gt;DEVReadFromFileExamplePerf&lt;/strong&gt; class) :&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/b262ba1b30b475d61a1b1ab430a6b73e/f941f/PerfCode.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 61.71428571428571%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAB2HAAAdhwGP5fFlAAABwUlEQVR42p1T2Y6jMBDk/z9slHmYzUMSEpINGSBc5jI2EO6aglmttA8rsWvJ6na7XW5Xlw1dt8iyDHEUrTbhLKRCVVWo6hpKSry6DtM0YcswhqGH1gppmqJ9vTDwnGwH5PTTpkHedshoFS/YBChUj/HX5fM8/57/O4y+71EUBYIgQMMn9iNYWQdRV4h0hZgxUUoseZsAn56Lz8cDsYjheR5cx4XjOOs6SRKIRKAfhu0VurHE5TOCH0aI4xgiFquVssQ4jBjHEfM0/0HH3+YKGKkRsunXpqRphoYNWPw8y6GU+ncOx3FAwucJIaC0hiSfJaWygFdKoy1ydOSxqmpkjJWsXHK/LOV68bf/HVukZczzhOvVwo/9HpZlwTSPME8nvO12sK0L0sMB6cKr62D/8YGzeWaOSWviffdO/4SIeR7PdGycsaA+2JTz+QL7fsftesPxcFwPJYyL6xW6VPADfwW5323cbj9X4APzQubkLCT3A7T8AMaLnC2NcN0nRBQj4Eb49FcZ1fw1mrGO4l5o8FwPIZsXBCF85rlUhSLXmjFdSGjSYmQZG5BnlI4NnxXmBApsGxHXEeUTLHapIgw3Cf4LVAaWTDdCv3cAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;PerfCode&quot;
        title=&quot;&quot;
        src=&quot;/static/b262ba1b30b475d61a1b1ab430a6b73e/8c557/PerfCode.png&quot;
        srcset=&quot;/static/b262ba1b30b475d61a1b1ab430a6b73e/4edbd/PerfCode.png 175w,
/static/b262ba1b30b475d61a1b1ab430a6b73e/13ae7/PerfCode.png 350w,
/static/b262ba1b30b475d61a1b1ab430a6b73e/8c557/PerfCode.png 700w,
/static/b262ba1b30b475d61a1b1ab430a6b73e/f941f/PerfCode.png 736w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Results:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&quot;left&quot;&gt;File type&lt;/th&gt;
&lt;th align=&quot;left&quot;&gt;Time to read 10k lines(sec)&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;Excel&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;1.54&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;CSV&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;0.56&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;As you see, reading itself is quite fast, in most cases you spend more time to process this data.&lt;/p&gt;
&lt;h2 id=&quot;more-complex-example---journal-creation&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#more-complex-example---journal-creation&quot; aria-label=&quot;more complex example   journal creation permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;More complex example - Journal creation&lt;/h2&gt;
&lt;p&gt;Let&apos;s consider more complex example - create a ledger journal based on the data from Excel file.&lt;/p&gt;
&lt;p&gt;In this case we will use an Excel file with 3 columns(Main account, BusinessUnit, Amount) and a user dialog with a &quot;Journal name&quot; parameter.&lt;/p&gt;
&lt;p&gt;To generate a dialog class we need to specify the following parameters in &lt;strong&gt;Create RunBase class&lt;/strong&gt; utility:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;DEVReadFromFileExampleCreateJournal
Create ledger journal from Excel


excel

LedgerJournalNameIdDaily*&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Journal creation logic can be copied from my previous post - &lt;a href=&quot;https://denistrunin.com/xpptools-createledgerjournal/&quot;&gt;https://denistrunin.com/xpptools-createledgerjournal/&lt;/a&gt;, dimension processing is from the following post - &lt;a href=&quot;https://denistrunin.com/xpptools-devfindim/&quot;&gt;https://denistrunin.com/xpptools-devfindim/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In our case this code is used for journal creation:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createLedgerJournal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;LedgerJournalTable&lt;/span&gt;      ledgerJournalTable&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;LedgerJournalEngine&lt;/span&gt;     ledgerJournalEngine&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;ledgerJournalTrans&lt;/span&gt;      ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

ttsbegin&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fileReader&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;readNextRow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;ledgerJournalTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;RecId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        ledgerJournalTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;clear&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        ledgerJournalTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;initValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;        ledgerJournalTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;JournalName &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ledgerJournalNameIdDaily&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;        ledgerJournalTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;initFromLedgerJournalName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        ledgerJournalTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;JournalNum &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; JournalTableData&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;newTable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ledgerJournalTable&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;nextJournalId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        ledgerJournalTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;strFmt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Excel file, Date %1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token named-parameter punctuation&quot;&gt;DEV&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;systemdateget&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        ledgerJournalTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;insert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token function&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;strFmt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Journal %1 created&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ledgerJournalTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;JournalNum&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        ledgerJournalEngine &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; LedgerJournalEngine&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;construct&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ledgerJournalTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;JournalType&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        ledgerJournalEngine&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;newJournalActive&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ledgerJournalTable&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;clear&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;initValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
ledgerJournalEngine&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;initValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;JournalNum           &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;   ledgerJournalTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;JournalNum&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;TransDate            &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;   DEV&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;systemdateget&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;AccountType          &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;   LedgerJournalACType&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;Ledger&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;modifiedField&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fieldNum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LedgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; AccountType&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;LedgerDimension &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; LedgerDimensionFacade&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;serviceCreateLedgerDimension&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
&lt;span class=&quot;token named-parameter punctuation&quot;&gt;LedgerDefaultAccountHelper&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getDefaultAccountFromMainAccountId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fileReader&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getStringByName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&apos;Main account&apos;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;&lt;span class=&quot;token named-parameter punctuation&quot;&gt;DEVDimensionHelper&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setValueToDefaultDimension&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token named-parameter punctuation&quot;&gt;DEVDimensionHelper&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;BusinessUnit&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; fileReader&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getStringByName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&apos;BusinessUnit&apos;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;LedgerDimension&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Missing or invalid ledger dimension for journal process&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;modifiedField&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fieldNum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LedgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LedgerDimension&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
ledgerJournalEngine&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;accountModified&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LedgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;//amounts&lt;/span&gt;
ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;CurrencyCode         &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;   Ledger&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;accountingCurrency&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
ledgerJournalEngine&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;currencyModified&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LedgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;amountCur2DebCred&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fileReader&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getRealByName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&apos;Amount&apos;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//additional fields&lt;/span&gt;
ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Approver           &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; HcmWorker&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;userId2Worker&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;curuserid&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Approved           &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; NoYes&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;Yes&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

DEV&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;validateWriteRecordCheck&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;insert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
ledgerJournalEngine&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
ttscommit&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As the result a new journal will be created&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/cc874ff46bde79771b22a66c30b39beb/4cd27/LedgerJournalCreated.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 42.285714285714285%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAB2HAAAdhwGP5fFlAAAB2ElEQVR42lWQS2/TUBCF/RcrWMCOXwASKyhIqKhCLFCKBGLdDZRSgsSqXSIerZBQQwG1cRI7fiSxr583wU5KXh/jUCRYHJ2ZuXfOmRnj7WeL/UaPg4bHmyOLnQ8tXn3qsPuxzc5784KldmhRP3TYrL/mUu0215494PLWXdZq66xtrXPlyT2uPt3ASAIf1zIJew5FHjMfj5iVQ6alZlro/2Km57x4t8fG3mPqR/vcfP6QWy8fcX37Pje2N7mzW8MwW22Ov57w7fsPHNcjUBGDIPyDUAmrC67yiL7fJQ0GpHFKkSjG+Yg4jImDiDzJMaIooiwKzidjdJ4ThiGRUkSRQlX8D5QK8Xo9siwnSRP5E6K1FrMBcRyRphlG1/UxLQfTdvE8D9/3saqa5NWb7fjCHh1hr9enbbfpWBau65IkKbZtr/paVpuW3ZEbSjFdOebCGZlMGYtTpoeMZPLRqCAfDqWuKcsxp+apnOhYttEo2cKyLXLpGagAP+hjDOWz1iISxzJyKsIp1Rmq1WezGcvlcoXFYsF0OuXMPKPrdJlMJiuhSFat4uJnwVCGMA6+2DRMD9tXdAKN1Y9pOgEnTZtBVhKNfhHkY5SeEAiane5KuDKZz+crowp/499G/z8JoDhFZwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;LedgerJournalCreated&quot;
        title=&quot;&quot;
        src=&quot;/static/cc874ff46bde79771b22a66c30b39beb/8c557/LedgerJournalCreated.png&quot;
        srcset=&quot;/static/cc874ff46bde79771b22a66c30b39beb/4edbd/LedgerJournalCreated.png 175w,
/static/cc874ff46bde79771b22a66c30b39beb/13ae7/LedgerJournalCreated.png 350w,
/static/cc874ff46bde79771b22a66c30b39beb/8c557/LedgerJournalCreated.png 700w,
/static/cc874ff46bde79771b22a66c30b39beb/e996b/LedgerJournalCreated.png 1050w,
/static/cc874ff46bde79771b22a66c30b39beb/2cefc/LedgerJournalCreated.png 1400w,
/static/cc874ff46bde79771b22a66c30b39beb/4cd27/LedgerJournalCreated.png 2039w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The full code is available in &lt;strong&gt;DEVReadFromFileExampleCreateJournal&lt;/strong&gt; class&lt;/p&gt;
&lt;h2 id=&quot;summary&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#summary&quot; aria-label=&quot;summary permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Summary&lt;/h2&gt;
&lt;p&gt;The following classes are used in this post:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;DEVCommon&lt;/strong&gt; model:&lt;/p&gt;
&lt;p&gt;Classes: &lt;a href=&quot;https://github.com/TrudAX/XppTools/blob/master/DEVCommon/DEVCommon/AxClass/DEVFileReaderBase.xml&quot;&gt;&lt;strong&gt;DEVFileReaderBase&lt;/strong&gt;&lt;/a&gt;,  &lt;a href=&quot;https://github.com/TrudAX/XppTools/blob/master/DEVCommon/DEVCommon/AxClass/DEVFileReaderCSV.xml&quot;&gt;&lt;strong&gt;DEVFileReaderCSV&lt;/strong&gt;&lt;/a&gt; and  &lt;a href=&quot;https://github.com/TrudAX/XppTools/blob/master/DEVCommon/DEVCommon/AxClass/DEVFileReaderExcel.xml&quot;&gt;&lt;strong&gt;DEVFileReaderExcel&lt;/strong&gt;&lt;/a&gt;  - read from CSV and XLSX files&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;DEVTutorial&lt;/strong&gt; model:&lt;/p&gt;
&lt;p&gt;Class &lt;a href=&quot;https://github.com/TrudAX/XppTools/blob/master/DEVTutorial/DEVTutorial/AxClass/DEVReadFromFileExamplePerf.xml&quot;&gt;&lt;strong&gt;DEVReadFromFileExamplePerf&lt;/strong&gt;&lt;/a&gt; - measure read from file performance&lt;/p&gt;
&lt;p&gt;Class &lt;a href=&quot;https://github.com/TrudAX/XppTools/blob/master/DEVTutorial/DEVTutorial/AxClass/DEVReadFromFileExampleCreateJournal.xml&quot;&gt;&lt;strong&gt;DEVReadFromFileExampleCreateJournal&lt;/strong&gt;&lt;/a&gt;  - sample code to create a ledger journal from Excel file&lt;/p&gt;
&lt;p&gt;Excel files used in this post can be downloaded &lt;a href=&quot;https://github.com/TrudAX/XppTools/blob/master/assets/ImportFromExcelExample.zip&quot;&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Comments are welcome.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Dynamics AX performance audit]]></title><description><![CDATA[How to perform Dynamics AX performance audit to resolve performance problems]]></description><link>https://denistrunin.com/performance-audit/</link><guid isPermaLink="false">https://denistrunin.com/performance-audit/</guid><pubDate>Wed, 05 Jun 2019 20:12:03 GMT</pubDate><content:encoded>&lt;h2 id=&quot;introduction&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#introduction&quot; aria-label=&quot;introduction permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Are your Dynamics AX users complaining about slow system performance? You started a research, found many tips on what to do, and still don’t know where to start.
In this post I will discuss how to perform Dynamics AX performance audit to resolve performance problems.
I will cover the following areas:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Current hardware analysis&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;SQL Server settings and blocking monitoring&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;AOS settings&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;X++ code optimization&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I will also outline common performance myths and mistakes based on real-life scenarios.&lt;/p&gt;
&lt;p&gt;The main principle of the performance audit is to start from the highest level(that allows to identify the performance problem with the minimum effort) and to continue by going deeper in the analysis. The described technique was used for more than ten customers with a number of users from 50 to 500 and database size from 100GB to 1TB. For all these customers, basic steps were the same and helped to identify and solve the problems.&lt;/p&gt;
&lt;h2 id=&quot;current-hardware-analysis&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#current-hardware-analysis&quot; aria-label=&quot;current hardware analysis permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Current hardware analysis&lt;/h2&gt;
&lt;p&gt;The initial task to begin with is to compare the used hardware with the specified one in a project Technical design document. It will not be good if you see a server design specification like &quot;8-core CPU&quot;. Such phrases in Technical design means that you don&apos;t have a proper technical design. &quot;8-core CPU&quot; can mean any performance level. Try to filter &quot;8 core CPU&quot; on the Amazon, and you will see a considerable price variation&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/cb9c6cdef04b2174579dba6ce0940f98/715a3/CPUPrice.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 50.28571428571429%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACYUlEQVR42oWQ3UtTYRzHz7/RlZC9EFSaBEvCzIWrwS7UCAqsuy68iQgiu4sWQngRhBeKqzRSS4ssX/am02141DXFSWlNtrM53XZe9nq26V7O8+2cgxde9PKDD7/v8734Ps/3oSambZi2OmB3uGCbdcJNe7CwvAJaZmHJK+9VzJnuQa+7gqqzTTh+7jKO1jSi6kwD6hoMqG9ug0bbUtE030C1ttVIaQ23oDXcxNXW21D0tbY7KrrWduivy7ulHU1aOezUeRw5ocGx2kac1uhQe1GP6ppLOFnXpFCp1xpQe0FnpEwDw+iXGXg3ileDIzDJvH47gv43Q6o3MDSKD+MWjI2bMT5lhdk+jzn3otrEOuPClykbPk9YK5YZJ6ZtDiNFpAoODzmkiCSBEIJ/TalUQrFYVEOKxT0jtRuJYHF+Hl6aBu1yqiy53djwrSOZEBAKhcEwDELhEFiOQyKRBM/z4GTN8wLS6TRSqVSlXC4jI4rPqB++NTzouItH9zvQbexE19PHeNn9HJOjY0jmSwjuCgju8EhlxD++UGkgSQc1JRipoN+PJ50P0fuiC27rJ9DOSQz298FhtiAZCIDfjUPIFLC3X/5LoBp68G9SD1Uplch2LEbo9e9kZWODOL55yFY4TBSf+7lJ+O0wEQSBxKJRItckyWRC3SzLkng8rqKcOY4Fy3I5Ssn1bW3B7FrGR5sHfe/N8P3yq/cJ+X1E0zlEE1mkM1lkshnk8nnkxBxEUVQpFArI5wvIZrOqVgKZQDDEWGY9TJ/dz/QO25ml1TVG9T3emPfrVHxnMxCRz0HF+w/B3/WKj0YB8IhbAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;CPUPrice&quot;
        title=&quot;&quot;
        src=&quot;/static/cb9c6cdef04b2174579dba6ce0940f98/8c557/CPUPrice.png&quot;
        srcset=&quot;/static/cb9c6cdef04b2174579dba6ce0940f98/4edbd/CPUPrice.png 175w,
/static/cb9c6cdef04b2174579dba6ce0940f98/13ae7/CPUPrice.png 350w,
/static/cb9c6cdef04b2174579dba6ce0940f98/8c557/CPUPrice.png 700w,
/static/cb9c6cdef04b2174579dba6ce0940f98/715a3/CPUPrice.png 830w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;For a CPU price defines the performance level, and there will be noticeable differences of a system working on 10$ CPU compared to 10K$ CPU.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;One of the clients complained about slow overall system performance. While comparing recommended hardware with the actual one, I have found that instead of 4-core 3.5GHz CPU, they had used 20-core 2.0GHz CPU. The client&apos;s original intention was correct, they thought that more cores mean more performance, but in that case, 4 cores were more than enough, but these should be the fast cores.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;hardware-recommendations&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#hardware-recommendations&quot; aria-label=&quot;hardware recommendations permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Hardware recommendations&lt;/h3&gt;
&lt;p&gt;For Ax2012 use the following guidance as a baseline.&lt;/p&gt;
&lt;h4 id=&quot;aos-and-terminal-servers&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#aos-and-terminal-servers&quot; aria-label=&quot;aos and terminal servers permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;AOS and Terminal servers&lt;/h4&gt;
&lt;p&gt;For AOS and Terminal server - CPU with the single thread performance equal to Azure Dv3 series. Memory - about 300-500MB per user&lt;/p&gt;
&lt;p&gt;These are the average values. The current Intel CPU &lt;a href=&quot;https://www.cpubenchmark.net/singleThread.html&quot;&gt;models&lt;/a&gt; give you about 30-50% more speed than Azure Dv3.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/28f4af9568417e2c033e9f1bbbb428a7/764be/E52673CPUMark.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 46.28571428571429%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB/klEQVR42n2R247SUBSGO3rns+jreOGjeOmDqMDgBV4MwyE6MRzMMBDOiMhUBlpOA22Hls1uy2Ha3d/VmhgvjDv5sw7Z68s6SACeSfR8339FPhaqKnrVG8jfuhi2W5gM+pG97XVwv1xioqiwXRemZeJuOsVU0zCZzcC4jYDqJdLTEAjffxkCDcMQw8EAqqLANM0wBSECBEIgrAj9KOf78AwdvjqFsCw8UizoTwh8wzl/zRj7eDqdoOta0Go1Icsy5vMZdTQG2zEcDns4rg3Pe8Qf4t3IQ6frQTc8D/BoSk8KqeTgeDyCoCSbAC64fQDnLoyHLbbMoZxDY3IcT7+B+6mKTbcDvd+HczvEabGACEemffhbzn2L22JnO9jNR9hOvsMc98GUQSSLYqb8AKPcvTKCZppiYxhNeSgXx7Jcds1x2XVY2ReiLFk7joWmY7paY77WULq5QK4QQ74Yx+dykmyC4jiuSklkvrwNvjYLmK31Pa3nebR74In09wu7WhkPWOoGlgRuXZRw/T6H61ge1fNPqMTzkSL/XTYYNHpYmebetqwXYX0qlQqPehaK4GcSd1zodE1tY0a23U2jUo2REqjVk6jUEpFq9XOyH4Kf6hjrzWZv2/a/O3QPB1i7HTaMtGXoFwtopNOoX16incuikcmQyM9mUM/ng5Gq/hf4C+ouQ0hN67F8AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;E52673CPUMark&quot;
        title=&quot;&quot;
        src=&quot;/static/28f4af9568417e2c033e9f1bbbb428a7/8c557/E52673CPUMark.png&quot;
        srcset=&quot;/static/28f4af9568417e2c033e9f1bbbb428a7/4edbd/E52673CPUMark.png 175w,
/static/28f4af9568417e2c033e9f1bbbb428a7/13ae7/E52673CPUMark.png 350w,
/static/28f4af9568417e2c033e9f1bbbb428a7/8c557/E52673CPUMark.png 700w,
/static/28f4af9568417e2c033e9f1bbbb428a7/764be/E52673CPUMark.png 806w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;If your current CPU speed is below these D3 values, upgrading your servers can give you some noticeable performance boost. &lt;a href=&quot;https://www.cpubenchmark.net/&quot;&gt;https://www.cpubenchmark.net/&lt;/a&gt; is a web site where you can check the CPU performance level(you need to check single thread performance and total performance). If you don&apos;t like comparing these numbers, search on Amazon or eBay your current CPU price.&lt;/p&gt;
&lt;h4 id=&quot;sql-server&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#sql-server&quot; aria-label=&quot;sql server permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;SQL Server&lt;/h4&gt;
&lt;p&gt;The same principles apply to SQL Server CPU, but they are not so simple. SQL Server is licensed by cores. For the wrong selected CPU model, your SQL Server license can cost more than the actual hardware. Check this &lt;a href=&quot;https://sqlperformance.com/2014/01/system-configuration/selecting-a-processor-for-sql-server-2014-1&quot;&gt;blog post&lt;/a&gt; that explains the process in details. It is old, but the basic idea is that in every Intel model line there is a 4-core CPU with the maximum performance-per-core value, the more cores you get, the less performance per core there will be, so you should not use CPUs with more cores than your system needs.&lt;/p&gt;
&lt;p&gt;As AX is an OLTP system, current CPU power for a SQL Server should allow processing data from a certain amount of memory. The amount of this memory is either the maximum amount supported by the SQL Server standard edition(64GB - pre-2016 and 128GB - for SQL 2016) or the maximum &quot;active data&quot; in the database.&lt;/p&gt;
&lt;p&gt;From the practical experience modern 2 * 4 cores CPU can easily handle 128GB memory. 2 * 8 cores can work with 512GB. If you need more memory, probably it&apos;s time to think about 4-sockets server.&lt;/p&gt;
&lt;h4 id=&quot;storage-system&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#storage-system&quot; aria-label=&quot;storage system permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Storage system&lt;/h4&gt;
&lt;p&gt;Nowadays we have HDD, SSD, and NVMe storage. The main difference is the number IOPS they can handle(very simple 1K+, 20k+ 200k+). So if you have some storage problem(the main indication for this is IO related SQL waits), you can just upgrade to the next level.&lt;/p&gt;
&lt;h2 id=&quot;aos-settings&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#aos-settings&quot; aria-label=&quot;aos settings permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;AOS settings&lt;/h2&gt;
&lt;p&gt;There are several blog posts that cover optimal settings for the AOS.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://community.dynamics.com/365/financeandoperations/b/axsupport/archive/2014/09/05/ax-performance-troubleshooting-checklist-part-1b-application-and-aos-configuration&quot;&gt;https://community.dynamics.com/365/financeandoperations/b/axsupport/archive/2014/09/05/ax-performance-troubleshooting-checklist-part-1b-application-and-aos-configuration&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blogs.msdn.microsoft.com/axinthefield/dynamics-ax-performance-step/&quot;&gt;https://blogs.msdn.microsoft.com/axinthefield/dynamics-ax-performance-step/&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;sql-server-analysis&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#sql-server-analysis&quot; aria-label=&quot;sql server analysis permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;SQL Server analysis&lt;/h2&gt;
&lt;p&gt;The first thing to check is the current AX database size per table.&lt;/p&gt;
&lt;h3 id=&quot;analyzing-database-size&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#analyzing-database-size&quot; aria-label=&quot;analyzing database size permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Analyzing database size&lt;/h3&gt;
&lt;p&gt;You don&apos;t need an exact table size(that takes time to perform), but you can get the size using the saved statistics from the &lt;strong&gt;sp_space_used&lt;/strong&gt; procedure(execution time is quite fast). This &lt;a href=&quot;https://github.com/TrudAX/TRUDScripts/blob/master/Performance/AX%20Technical%20Audit.md#database-size&quot;&gt;script&lt;/a&gt; provides you the size per table. Copy the result to Excel and sort by size. Sometimes you see the picture like this:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 621px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/b66295d9011951750fdd97a30115892f/3075e/DataBaseSizeTopTables.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 34.285714285714285%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAAA7EAAAOxAGVKw4bAAABgUlEQVR42mWSu07CYBiGezuKC0FM1EnuwYnFSFw0Orm6yD14Dyye4igLIZwKPUNpAWkAoQ0nOarT69tOGIYn+Tt87/+8319Bkh7Q66UwHr+RV8znL/j6etpiNntEq5VHo9HGdDqFpeuQMxnIuRzsahXFdBpuvw9BFK8gipeoVK6h6zdw3Vus10msVvcbJLFc3mE4zEJVTaIEw3XDQC6bxUezCV1RUDdNCIoShiSFUCrtMniH5z0a79MoQpMI7XyiPIfgeSnUag4vL+GTgc1WC4ViEY7jUEYPEDQtDlk+hWmeod2+4GACi8U5rTZJ0DCOyeQd9boDTaOh67J+gwIS59q8qBYglMsWCgWTHz1WBcNAo224NgwGY4ZpKJcr6HQ6MFg5n8/Dtm0orKyqql9ZZwUZlmWj33dpMafRL41+/rFYfGM0GqPKB/AHPc9Dk7sTRRHdbjewM/0dGsYRux9QPcobw7Q5ZmCMnGwQY+gh/4LnYIeGoQWVLcsKKvs79G39yn/g3d+cO1+iuwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;DataBaseSizeTopTables&quot;
        title=&quot;&quot;
        src=&quot;/static/b66295d9011951750fdd97a30115892f/3075e/DataBaseSizeTopTables.png&quot;
        srcset=&quot;/static/b66295d9011951750fdd97a30115892f/4edbd/DataBaseSizeTopTables.png 175w,
/static/b66295d9011951750fdd97a30115892f/13ae7/DataBaseSizeTopTables.png 350w,
/static/b66295d9011951750fdd97a30115892f/3075e/DataBaseSizeTopTables.png 621w&quot;
        sizes=&quot;(max-width: 621px) 100vw, 621px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;in this case, a lot of space consumed by some temporary/tracing data and can be deleted.&lt;/p&gt;
&lt;p&gt;Check the number of closed records in InventSum. If most of the records are closed, removing them can considerably increase the performance.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 307px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/6bab26b1b643384af47cd5b2ceb518c6/4651d/InventSumSize.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 24.571428571428573%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAYAAABFA8wzAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABDklEQVR42jVQyYqDUBDM/39HIPfgKB4SmEMyQhB0XMbEgwhB474vCYaa7jfjQaq6n13V1ZtlWVDXNZqmQVVVgq91WZYoikL0ueZ+27bI8xwl8ZJ6bd+j6ToU9E9HuHm9XvA8D4qiQJIknM9nzPOM5/MpBF3XhSzLUFUVQRBgmiZEUYSv4xH77RafNPOx2+F0OCAn8804jkiSRLizQxiGME0TjuPAsiyxzbrtMAyI4xjX6xU/mgbvdEJNJgXV1f2OJE3/BFMi7MxxfN+HrutC9HK5iMgs1FM0xsfjgdvthm9K4pPh/H6jp9nu/00IMuEBRsMwxAls24ZGW2RZJozW+3EaNuUEjD2lavj29LHgLw0Zbl4UdtwwAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;InventSumSize&quot;
        title=&quot;&quot;
        src=&quot;/static/6bab26b1b643384af47cd5b2ceb518c6/4651d/InventSumSize.png&quot;
        srcset=&quot;/static/6bab26b1b643384af47cd5b2ceb518c6/4edbd/InventSumSize.png 175w,
/static/6bab26b1b643384af47cd5b2ceb518c6/4651d/InventSumSize.png 307w&quot;
        sizes=&quot;(max-width: 307px) 100vw, 307px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;For example, if you get the following results, you can drop closed records(the only problem here is that some reports, for example, &quot;On hand by date&quot; can use closed records to display historical data, check this before deleting).&lt;/p&gt;
&lt;p&gt;Use this link to find all standard cleanup jobs - &lt;a href=&quot;https://blogs.msdn.microsoft.com/axsa/2018/09/05/cleanup-routines-in-dynamics-365-for-finance-and-operations/&quot;&gt;Cleanup routines in Dynamics 365 for Finance and Operations&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Also, check some system &lt;a href=&quot;https://github.com/TrudAX/TRUDScripts/blob/master/Performance/AX%20Technical%20Audit.md#table-statistics&quot;&gt;statistics&lt;/a&gt;. Often, you need to know the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Transactions per day(for logistics companies it will be a number of sales lines or invent trans per day) and the difference between peek and regular days)&lt;/li&gt;
&lt;li&gt;Active users per day, per hour&lt;/li&gt;
&lt;li&gt;Batch jobs and their timings&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Compare these numbers with the numbers from the technical design, very often clients exceed them but &quot;forget&quot; to upgrade the hardware.&lt;/p&gt;
&lt;h3 id=&quot;sql-server-settings&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#sql-server-settings&quot; aria-label=&quot;sql server settings permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;SQL server settings&lt;/h3&gt;
&lt;p&gt;To check the current SQL server settings, you need just one script - &lt;a href=&quot;https://github.com/TrudAX/TRUDScripts/blob/master/Performance/AX%20Technical%20Audit.md#sp_blitz&quot;&gt;sp_Blitz&lt;/a&gt;. it performs thousands of checks and displays summarized recommendations with explanation links.&lt;/p&gt;
&lt;h3 id=&quot;missing-indexes&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#missing-indexes&quot; aria-label=&quot;missing indexes permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Missing indexes&lt;/h3&gt;
&lt;p&gt;Missing indexes &lt;a href=&quot;https://github.com/TrudAX/TRUDScripts/blob/master/Performance/AX%20Technical%20Audit.md#missing-indexes&quot;&gt;script&lt;/a&gt; provides an overview of indexes that are considered missed by the plan guide engine&lt;/p&gt;
&lt;p&gt;Output contains the following columns:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Table name&lt;/li&gt;
&lt;li&gt;Equality columns: &apos;&apos;=&apos;&apos; condition in the WHERE clause&lt;/li&gt;
&lt;li&gt;Inequality columns: some logical condition(&amp;#x3C;&quot;, &quot;!=&quot;) in the WHERE clause&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Don&apos;t just follow these recommendations, every recommendation should be analysed from a logical point of view, and only indexes that really limit the actual search should be created. You don&apos;t need to analyse the whole output, often 30-50 top recommendations are enough.&lt;/p&gt;
&lt;p&gt;Sometimes you can see recommendations that were caused by wrong conditions(mandatory fields missed in the SQL statement). In this case it is better to find and correct the statement, rather than trying to create an index(in the example below RefCompanyId field is missing for DocuRef selection)&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 625px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/3138f601dab5c38e0f2950cbafa65a04/80d71/MissingIndexesMissingField.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 32%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABXUlEQVR42o1Qy0rDQBSNoJ8h+FMu4jf4CYILQRB0o7hzoSIIXbhyo1CCVrGLUiymhjzapmlq85okjdLaZGaOk+hGVx44nMvl3nMfUhzHCMMQnueBEIIkSRAEAdKUIE0IYhJ+xxVjZFkCdxJBMwboqmpVm2UZSp/ZbAZpPB5TkaS+71NhXMWhoD2c0IHtCfXo2ySm7phQxw2pF6SUxFO0XlxYZh9ZOgVnDCUWecGlXs+qNizBOQNjHJQVeNaP8NTZQlvbgWYfwPaP0fcPMV2co8jnMK0RNF30kggFLVAIz5yGkFS1I7+qakVd12VVqDhfbnZO5dv7Pbn+uC9fK7uy4dQ2huRqPXpvbIqpRbmAobn87uQC7csaCxsPyD/SkfRfiP6lH11ljC1KQ9NJ+Fndxk3TYsg/QSlTJUVRlv9S1Ard/sUWsFIazjFfK98FDvSdiHc1A4ZuMir+mBd59wvj2nF+SGHxYQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;MissingIndexesMissingField&quot;
        title=&quot;&quot;
        src=&quot;/static/3138f601dab5c38e0f2950cbafa65a04/80d71/MissingIndexesMissingField.png&quot;
        srcset=&quot;/static/3138f601dab5c38e0f2950cbafa65a04/4edbd/MissingIndexesMissingField.png 175w,
/static/3138f601dab5c38e0f2950cbafa65a04/13ae7/MissingIndexesMissingField.png 350w,
/static/3138f601dab5c38e0f2950cbafa65a04/80d71/MissingIndexesMissingField.png 625w&quot;
        sizes=&quot;(max-width: 625px) 100vw, 625px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h3 id=&quot;unused-indexes&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#unused-indexes&quot; aria-label=&quot;unused indexes permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Unused indexes&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/TrudAX/TRUDScripts/blob/master/Performance/AX%20Technical%20Audit.md#unused-indexes&quot;&gt;The script&lt;/a&gt; provides some unused indexes statistics for the large tables.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 358px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/56ec1cd1ebaae029855004e10893c2cf/39185/NotUsedIndexes.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 33.142857142857146%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAAA7EAAAOxAGVKw4bAAABbElEQVR42jWRC2+CQBCE+f8/ysbaarVtUsGDO95iI6iRKoi8xOneRi/ZQGB3Zuc7YzR6QZ7nuN/vaLsOfd+jo6rrmt83mwTj8StcKWFZFmazGYrygktZYPo+hR+E+JzPMZm8wXEcGELY2CQbGvzl4TiOkGYZhuEOfQoaXMcxTHNJAxJJkvD3vu9QVRX2WUr/LCilEIYRDNu2IYSAFhbColrheMxZcBgGlGWJKAqwNH/geR7W6zUbb9OUhetrBUlikhJIqWBIcg2CAL7vs4vnuWjalhHoOhcF4iikuCaL+b7Hvdlux4bD7cYJHVosoPiGjuG5LrsrcnFdhaZp8TzlpWQMmk9M0YW9wul0ZqGBDG/EOQpDYvtBPAPNUEBSs1Iux5XSwfXasPuNhjTDOAzw9f0FjUdvsqJt94cDJ+jpIjXXxWLB0Q2L2GkRW4tKm586zvPkf0e41GiZJhQl2W63j0vpH4ItmTjcE0Ux/gFTwgHpEuHToQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;NotUsedIndexes&quot;
        title=&quot;&quot;
        src=&quot;/static/56ec1cd1ebaae029855004e10893c2cf/39185/NotUsedIndexes.png&quot;
        srcset=&quot;/static/56ec1cd1ebaae029855004e10893c2cf/4edbd/NotUsedIndexes.png 175w,
/static/56ec1cd1ebaae029855004e10893c2cf/13ae7/NotUsedIndexes.png 350w,
/static/56ec1cd1ebaae029855004e10893c2cf/39185/NotUsedIndexes.png 358w&quot;
        sizes=&quot;(max-width: 358px) 100vw, 358px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Remove the indexes only if they are related to not used functionality or a different country. In some specific cases for large tables, you can also consider disabling Partition and DataArea fields.&lt;/p&gt;
&lt;h3 id=&quot;wait-statistics&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#wait-statistics&quot; aria-label=&quot;wait statistics permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Wait statistics&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/TrudAX/TRUDScripts/blob/master/Performance/AX%20Technical%20Audit.md#wait-statistics&quot;&gt;Script&lt;/a&gt; gives you an overview of current wait events. If you see some IO related events here, &lt;a href=&quot;https://github.com/TrudAX/TRUDScripts/blob/master/Performance/AX%20Technical%20Audit.md#disk-i--o&quot;&gt;analyze&lt;/a&gt; disk activity by disk and by file.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 335px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/a28883fd9794b2209d49ade0a7fb6ebf/c0051/Waits.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 24.571428571428573%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAYAAABFA8wzAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABGUlEQVR42k1Qa2+DMAzk//+s9cPGgDIeIZCQQGm6lvJov1AVBrsZpE2LZMWxfb7LWY7rwnNc2G+vKCuDZVkwjiOezyeGYaB8gjEVXnY7CCHRti3med76TVPDISyLGd5tG7btwEo5R8IYgg8fqijREKBvG/S3O35PdSnh+h4BY5SHAy51vdXr/gzP30MSUXO9oqqOsFSeIxMCOd1SSgrKKfr7v4V1iZjH0FohVwpK661+7k5gaQJzNH+zVpIkkLRMiBSc1EqZEUBhnCY8HgPmrxnaSDh7d1OyknZ9t4Ev3SciHuFAqlcb1rCEyJDQoqLQW0Mrjb3vIwwDcCKLyJ9cZwjCECt5TO+avrws32hvVzBOCo3BRAJW738AOfZt7t8qxjkAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Waits&quot;
        title=&quot;&quot;
        src=&quot;/static/a28883fd9794b2209d49ade0a7fb6ebf/c0051/Waits.png&quot;
        srcset=&quot;/static/a28883fd9794b2209d49ade0a7fb6ebf/4edbd/Waits.png 175w,
/static/a28883fd9794b2209d49ade0a7fb6ebf/c0051/Waits.png 335w&quot;
        sizes=&quot;(max-width: 335px) 100vw, 335px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h3 id=&quot;top-sql-analysis&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#top-sql-analysis&quot; aria-label=&quot;top sql analysis permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Top SQL analysis&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/TrudAX/TRUDScripts/blob/master/Performance/AX%20Technical%20Audit.md#get-top-sql&quot;&gt;The script&lt;/a&gt; provides active Top SQL commands, their statistics and saved plan from the SQL server statistics(to clear the list use &lt;strong&gt;DBCC FREEPROCCACHE&lt;/strong&gt; command).&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 672px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/7181a1a28bef5b56a657abd567434bb6/30d16/TopSQL.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 18.285714285714285%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAYAAACOXx+WAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAA20lEQVR42jWQjW6DMAyEef9nazvQlIz8JxQ6xioVEEm1rnAz2RbJ+uzEubNcSKnQf/RwziGliLgsiDFRnogL8Y5pGqGor+06ND7AO4+maSDqGkpJaK1x6S5UCxT7BWOvkKIGe+NgnKGqKpxOR5TlC0WZP/+feZ5wPrc57/t3HI4HGsbnejcurDGQUkDvTkZDaQVjLYQQcMSa6L3D4/GFbduQYsTn9forMI7ZMIRAb6BYUQRqzoIklEmimkyMNXkNUkqixfP5jXVdcae1DMOQBcfbDZxztG33N/2MH/nfJxI26Mw7AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;TopSQL&quot;
        title=&quot;&quot;
        src=&quot;/static/7181a1a28bef5b56a657abd567434bb6/30d16/TopSQL.png&quot;
        srcset=&quot;/static/7181a1a28bef5b56a657abd567434bb6/4edbd/TopSQL.png 175w,
/static/7181a1a28bef5b56a657abd567434bb6/13ae7/TopSQL.png 350w,
/static/7181a1a28bef5b56a657abd567434bb6/30d16/TopSQL.png 672w&quot;
        sizes=&quot;(max-width: 672px) 100vw, 672px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Ideally, you should know first 5-10 statements from this list and analyse the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;They logically make sense for the current implementation - the number of executions and the statement itself relate to the current system functions. Very often I saw some statements here caused by incorrect system setup, by not used functionality or they are not related to AX at all.&lt;/li&gt;
&lt;li&gt;They use optimal plans and indexes&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;FETCH_API_CURSOR here means some query from an AX form. To find the original query use &lt;a href=&quot;https://github.com/TrudAX/TRUDScripts/blob/master/Performance/AX%20Technical%20Audit.md#cursors-for-the-session&quot;&gt;Cursors for the session&lt;/a&gt; script.&lt;/p&gt;
&lt;h3 id=&quot;ax-long-sql-statements-tracing&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#ax-long-sql-statements-tracing&quot; aria-label=&quot;ax long sql statements tracing permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;AX long SQL statements tracing&lt;/h3&gt;
&lt;p&gt;You can enable tracing of long SQL statements in the user options. Use this &lt;a href=&quot;https://github.com/TrudAX/TRUDScripts/blob/master/Performance/AX%20Technical%20Audit.md#enabling-tracing&quot;&gt;job&lt;/a&gt; to enable it for all users. Often you need to analyse statements with the execution time more than 2-5 seconds.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 662px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/32fee816d87a64e843bf7620dfaf842f/be86f/AXSQLLog.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 66.85714285714286%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACU0lEQVR42m2Sy27TQBSG/ZgseKlKIIpSsWGDWHVfCaHuuSRtmqYQt05iO+PxbTy+ezw/Z8YpgsBIJydz8Xcu/3Fevp/jxUcXZ98jvF0leHXLcX6f4mzO8PouweynwOzHZBebAud3dP51ize3B3t3cbTZ0Zx3n3x8+LzHNhRgcYmACSRZhTjKUBYlVN9jMNYZ6+xeDYr88Pusb+n8eOc8iQGbQ4VdOiAoAJ8srjTqToFnDcK8BRMdwqQBzxuwtIIflbSvEPDJR2mNQ1IjES2cJesxdwXWfgVeAXuhQe/Q9gpd00KXFfokxVDX0BpQ40imrR/Jm2V+R7o0e2fNOywIuOEDKDDCQoORF7LE4tsXrK6usLi8hLdc4nQppeC6LlgU2f+aoM5j2uPmMcfdvrblTlCgajpwHiEvS6QEb/ruH+BIWUYEE0Kgoncd9dFZEWW9l3ApQy8DmJygVdNboCwKlPTYZHC6NAHjOEaeC8hnoJu02AQSD2EDLzc9hO1l3fZI0wRSStTUP2PDMKAnJf+0PMsImKNpGhvY8bIOri/gJQO2BPQIeLBAKpnKKY0oFFnQRwVla8p7NhPMvCkKacs3YGdbKERSgdGobAn2ZLKUEzAMA/CYY6ByazOLlKH50DRfW1VHBL6PmKZAqdHunV2pQVUjrmkGpbbAnRGFSo7YAQUJwm4W8K6vaYBb6FNROLd9NtnaHu4NsJ6AUTWVvD0C0yRGQxAZJ+ioxP+pHAShVdqIY/r8F3DK8giksYlJZUHRQ5rBbHUPO9knQMYYTQO3Kpse/wLfzdtiiKk9LAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;AXSQLLog&quot;
        title=&quot;&quot;
        src=&quot;/static/32fee816d87a64e843bf7620dfaf842f/be86f/AXSQLLog.png&quot;
        srcset=&quot;/static/32fee816d87a64e843bf7620dfaf842f/4edbd/AXSQLLog.png 175w,
/static/32fee816d87a64e843bf7620dfaf842f/13ae7/AXSQLLog.png 350w,
/static/32fee816d87a64e843bf7620dfaf842f/be86f/AXSQLLog.png 662w&quot;
        sizes=&quot;(max-width: 662px) 100vw, 662px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;A great advantage of this in AX is that you can see a stack trace of the statement. Also, keep in mind that a long execution time can be caused by 2 reasons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A statement is heavy and it takes a long time to execute it&lt;/li&gt;
&lt;li&gt;A statement is blocked by another session&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;blocking-analysis&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#blocking-analysis&quot; aria-label=&quot;blocking analysis permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Blocking analysis&lt;/h2&gt;
&lt;p&gt;The following reasons can cause unwanted blocking:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Group update operation(like &lt;strong&gt;update_recordset&lt;/strong&gt;) in X++. Check this &lt;a href=&quot;https://denistrunin.com/understanding-sql-blocking/&quot;&gt;article&lt;/a&gt; that explains the problem in detail. To resolve this, you need either replace &quot;&lt;strong&gt;update_recordset&lt;/strong&gt;&quot; with &quot;&lt;strong&gt;while select forupdate&lt;/strong&gt;&quot; or adjust indexes&lt;/li&gt;
&lt;li&gt;Blocking escalation - if you modify more than 5000 records in one transaction sometimes, SQL Server decides to escalate the blocking level. If you have a lot of memory, you can disable this behaviour(ALTER TABLE myTable set (LOCK_ESCALATION = DISABLE)), but first, check that you really need to update all records in one transaction.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A great instrument to deal with the blocking is to enable AX long SQL statements tracing(see above) - in this case, you will see the statement, user and actual operation(by using X++ stack trace).&lt;/p&gt;
&lt;p&gt;It is also useful to enable &lt;a href=&quot;https://github.com/TrudAX/TRUDScripts/blob/master/Performance/AX%20Technical%20Audit.md#show-sql-query-for-the-ax-user&quot;&gt;context_info&lt;/a&gt; for the SQL session. This allows you to link AX session with the SQL Server SPID and find a blocked user.&lt;/p&gt;
&lt;p&gt;The most challenging part of resolving blocking problems is to find an operation that causes blocking. The primary technique is to try to search blocking on the TEST version. In this case, you run the client, execute the operation(for example, post the sales order) and put a breakpoint to the last &lt;strong&gt;ttscommit&lt;/strong&gt; statement for this operation. Then run another client and start executing operations(like another sales order or journal posting). If you catch a SQL block, you can easily implement and test a fix for it.&lt;/p&gt;
&lt;h3 id=&quot;parameters-sniffing&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#parameters-sniffing&quot; aria-label=&quot;parameters sniffing permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Parameters sniffing&lt;/h3&gt;
&lt;p&gt;Parameters sniffing quite often becomes a reason for performance problems. For example, you have a warehouse where most of the items have one batch ID, but there are some Items and Batches with generic names (like “No batch”, “Empty”). In this situation, when you query item by batch, your actual plan depends on the first query values. If your query contains “generic” batch values, SQL Server creates a plan, that starts execution with the ItemId, as a “generic batch value” is not selective in this case. But for most of your items, it will be wrong and gives a huge overhead, as in most cases Batch is a unique value.&lt;/p&gt;
&lt;p&gt;There is no universal way to resolve Parameters sniffing issues(refer to the excellent BrentOzar post that describes this &lt;a href=&quot;https://www.brentozar.com/archive/2013/06/the-elephant-and-the-mouse-or-parameter-sniffing-in-sql-server/&quot;&gt;https://www.brentozar.com/archive/2013/06/the-elephant-and-the-mouse-or-parameter-sniffing-in-sql-server/&lt;/a&gt; ), but there are several ways to deal with it in AX:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Create new indexes – you can create new indexes, to help SQL server always choose the best plan. This often works only if you have conditions to one table only&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Use the &lt;strong&gt;sp_create_plan_guide&lt;/strong&gt; &lt;a href=&quot;https://github.com/TrudAX/TRUDScripts/blob/master/Performance/AX%20Technical%20Audit.md#create-a-plan-guide&quot;&gt;command&lt;/a&gt; to force the actual plan – using this option creates a big admin overhead as you need to maintain these created plans. If you add a new field to the AX table you will need to change all the plan guides in which this table is used. Often you need to provide just a OPTIMIZE FOR UNKNOWN hint to disable sniffing for the  SQL statement, better do not specify specific indexes&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;forceLiterals&lt;/strong&gt; X++ hint –you send actual values to the SQL Server, and it chooses the best plan for these values. The overhead is that the plan will need to be compiled every time&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Use index hint (new feature D365FO only)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can view created plan guides in the Programmability section:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 217px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/68a3d7e1c815801f9874b98d29b46b2f/7ba77/PlanGuides.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 141.7142857142857%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAcCAYAAABh2p9gAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAEA0lEQVR42pVVeW/idhTMN2//WO1HyFfoX1VXVRWpUqtqs5sLSDiM7wPj+7Yx5OSYjh2yDVnSZC39AIE9zHszb96B7/s4OjrC4eEhdM3E8ZcTnHz9is55B/1+H50O3y+vtucS3YsOzk5PYVk29l0H6/UaSRxjYjuovAFC8xKGYRFchSRKfNDCxJpAU5QWxDJNqPw8q+f7AZuXxXyOvJhh7nYw8/oEMzAejyEMBYiSBE0niCTi4rzb/okyllDWixZgs9l8D1hVFcI4RU3AYnoFz/ExHo4gkcni5vbbze3DLwD2Mpy3DCvMgwHmkYwkyVimhenUweL6pgVqWvP8vAa8ZVi2DKvJMUr7HCpLHgyHMO0pfvRqAa8XCxRVjXk4QuUL8NwA9mSCMAgQ+gFU1UBE4YosR5qkrCDB+i2GQZSgds5QOpcwDRuyLLdlm7oO05xAkmQookyFVYqk4f5h9TpgXddI85KAFwTswXY82LSKRftMTLsFXK6WT9L8SMkCRZFa3zmOA5enYWlNbCx4zw0FWiyusVqtWqE2e8puAWezClGSozL+RmF+YblTjIUxhRlB5rtlmLjs9HBxeoZut0dT7/fgN8DmH5fLJUuftUwWfg95oENWdMRhhMAPockKUooShQHcqYc4TlCU5XfAB8+/CKMIWZahJNM6s6FpzYRQDFWD77gcTxvimNND1oIgwt7a6lXABqxRvFCPUPgEkkzOrkWAEcYjgU6IXy11B/DpKllCPac4bg/z3KUwHksMERGoKT0MwrYl6/UKd7e3bav2An4rmQ9naYpc/gNVpGBwNUKPIvR6VxAVEa5HkzM0jv/5jLPzCwRhvL/kHYb05Gx6iiq24FGMJtqiKITJcQyDCLe3d3TFjOzWr6v89ENKdg1oZX1GnZjQ2b8mrnTdgERmwwFHc5uDm/8bvV3AArn0O6pAhUmDN7k4pcI7IO8VpSgeS669R1EM2qaZmnzrtya2Nu/Jw5eiVPqfyGkbcahgOBwgq2Zv2mW/KFuGpfnYQ0lg3CsaDFWH63rvAt0rSqPyLLEgj5XW2DJjy6cPn+7dOS++O2gazEDH8tMnJJqOiusgE39D7jIc+mPGGPvIGGty8PzkDHGavaEyf3hoQvbnn5CLIm6Yew+VizILMRrJ8Dwfvuu24siy2jLOGRLNafqd5QVTPEbghUjj6LHkJjrLjx9xz/x7uqZOAKHzC9LQZDjosLmPhZHIRd/lBF3RlyI34xCdbp+G9yD0BUZc55FhC/jhA+6m/y2lkD0b9v5Cngbt9nNsMpQ09LsEY091tRFL5UIzuYOmEEcS9/hgF/D+GWAQJNBGv6JIbRhcAQ6XlqY2E9OAsXTD4L7RMJaUtmSrjToJ/wIPhD4NhHIrdQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;PlanGuides&quot;
        title=&quot;&quot;
        src=&quot;/static/68a3d7e1c815801f9874b98d29b46b2f/7ba77/PlanGuides.png&quot;
        srcset=&quot;/static/68a3d7e1c815801f9874b98d29b46b2f/4edbd/PlanGuides.png 175w,
/static/68a3d7e1c815801f9874b98d29b46b2f/7ba77/PlanGuides.png 217w&quot;
        sizes=&quot;(max-width: 217px) 100vw, 217px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;As a basic rule add &lt;strong&gt;forceliterals&lt;/strong&gt; hint(or &lt;strong&gt;query.literals(true)&lt;/strong&gt;) for the single SQL statements and create a plan guide(with the OPTIMIZE FOR UNKNOWN hint) for small SQL statements. &lt;strong&gt;Forceliterals&lt;/strong&gt; usage can slow down your server. Check this &lt;a href=&quot;https://denistrunin.com/forceliterals-forcePlaceholders/&quot;&gt;article&lt;/a&gt; for the details.&lt;/p&gt;
&lt;p&gt;Determining which statements are affected by parameters sniffing also can be tricky. Often you analyse statements from the Top SQL output(see above), then compare the actual plan with the estimated plan and if they are different, check the XML representation of the actual plan. At the end of this XML you can find initial(sniffed) parameter values and basing on them decide is that an issue and how it should be fixed.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/77e88ac6bc8d4d59d0dc773a64bab0ba/b3ad9/PlanValues.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 31.428571428571427%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABLUlEQVR42p3P207CQBCAYd7/ebhRCQIx4CEcBAxCoVCgoGBpu9tSSrv7u8XDjXdOMtmdyc63mdJq/sBu08Pf92k/9yiXa9xc1alUm9SaHa4bj9yas3HfNXX7Ute/70U2Wl2qd09Uin6rQymKE34ilwnn3QdozX+jJKQwgKIgIi/Aex0TrlZka5e1HZEsN+ipRbJw2W9jMschm81RsxkHNyAMzyilyLKvLEVR9Kuf5JGDAYWzMANznHFEajsw6JOObexpzrvlk1tTGI0uvcDxcTcaz9Nst/wF/QJcGNA24MSA8yUMB5wnNpal8RcH9MS6gPlkysp8OnwpQEWaGlDKAtQos7N48/BnNseDj5KSWGTkUYwOAnIhEVKTxilaCHQYokLzxqwcBprTyRhK8wny18HeKOMdeAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;PlanValues&quot;
        title=&quot;&quot;
        src=&quot;/static/77e88ac6bc8d4d59d0dc773a64bab0ba/8c557/PlanValues.png&quot;
        srcset=&quot;/static/77e88ac6bc8d4d59d0dc773a64bab0ba/4edbd/PlanValues.png 175w,
/static/77e88ac6bc8d4d59d0dc773a64bab0ba/13ae7/PlanValues.png 350w,
/static/77e88ac6bc8d4d59d0dc773a64bab0ba/8c557/PlanValues.png 700w,
/static/77e88ac6bc8d4d59d0dc773a64bab0ba/b3ad9/PlanValues.png 909w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;index-rebuild-and-statistics-update&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#index-rebuild-and-statistics-update&quot; aria-label=&quot;index rebuild and statistics update permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Index rebuild and statistics update&lt;/h2&gt;
&lt;p&gt;Rebuild index and statistics update jobs can cause a lot of problems.&lt;/p&gt;
&lt;p&gt;The main misconception is that these operations can improve system performance but in reality they can&apos;t. The side effect of these operations is that they clear the plan cache(the same can be done just with DBCC FREEPROCCACHE command) and due to parameters sniffing this is often considered as an improvement.&lt;/p&gt;
&lt;p&gt;The typical scenario of going into this trap(Brent call it Index Maintenance Madness, but in my experience, the same relates to statistics update):&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;System suddenly becomes very slow(due to parameters sniffing issue)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Someone decides to run an index rebuild or/and a statistics update job&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;This magically helps and these operations started to be executed daily(but you can&apos;t resolve parameters sniffing issue with this)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Then system slowness happens during the day and statistics update also helps.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Frequency changes to 2 times a day, then 3 times a day and so on...&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;At the end of these events, a customer decides that index rebuild or/and statistics update job should run constantly and the server load they produce can even exceed the AX business logic load, cause blocking and slow down the system.&lt;/p&gt;
&lt;p&gt;Check this article(&lt;a href=&quot;https://www.brentozar.com/archive/2017/12/index-maintenance-madness/&quot;&gt;Index Maintenance Madness&lt;/a&gt; and a great &lt;a href=&quot;https://www.youtube.com/watch?v=iEa6_QnCFMU&quot;&gt;video&lt;/a&gt; from Brent Ozar that explains the theory and psychology in details.&lt;/p&gt;
&lt;p&gt;Recommendations here is that you should not execute these operations in any way they can affect system performance. If you have a free maintenance window, run them once a week using Ola Hallengren‘s &lt;a href=&quot;https://ola.hallengren.com/sql-server-index-and-statistics-maintenance.html&quot;&gt;IndexOptimize&lt;/a&gt; procedure. It is more efficient than the standard SQL agent tasks as they allow you to execute UPDATE STATISTICS command without &quot;WITH PERCENTAGE&quot; clause and for the index rebuild you can specify fragmentation limits. Check this article for the details - &lt;a href=&quot;https://www.brentozar.com/archive/2019/08/dba-training-plan-10-managing-index-fragmentation/&quot;&gt;Managing Index Fragmentation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Don&apos;t use rebuild index and statistics update jobs to resolve any performance problems.&lt;/p&gt;
&lt;h2 id=&quot;code-optimization&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#code-optimization&quot; aria-label=&quot;code optimization permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Code optimization&lt;/h2&gt;
&lt;p&gt;Before individual operations optimization(x++ code) you need to know the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Detailed problem description&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Reproduction steps. That is the most complicated part, sometimes reproducing the problem can take more time than the optimization&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;What is the current and what is the required execution time&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;How you can test the optimization&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Testing is quite easy for reports or operations that don&apos;t modify the data, but can be complex for posting operations. Try to minimize the number of manual testing steps, ideally, the test should be possible to run  by one click(in this case you can try different ideas during the optimization process). For posting often you write a job that opens a transaction at the beginning and then generate a &lt;strong&gt;ttsabort&lt;/strong&gt; at the end.&lt;/p&gt;
&lt;p&gt;Trace Parser is a great tool for analysing operations execution. It will trace all sessions in the AOS and provides detailed output. For production tracing better to have a dedicated AOS as trace file can grow very rapidly when you have a lot of user sessions.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/461e75a65c523c3069ec842afd625d20/cab8c/TraceCockpit.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 44.57142857142857%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABhElEQVR42o2R3W7TQBCF/Yg8CM9RoVJRIQrc0OfgDvUCARWiIEWQJqSm7cbGiR3/rtf2xvbH2G0RgQs60tGcnd05OjPrPHh1xsM3Hk8nIc+mMS9nCS9mKc+nG558dHn8fsHe2zn7kh+9W7B/+oODU5eDDwsOzxSHn645kr6j82SEc/x6ysnnJT9XG9xLjyvl4wehcEWU5gRhSrBOSdIC5YcsvRBTb6ltSyXZ1JbS1L/hzPwV37w1k+WGiR/zNciZRYYvKmLixWP2tWVrLUop5vPvpFlOI+emaRii/wMOtzEW+v6G9+xE1w/oqauKPM/QRYExhjzLpN7tvHX6HcFbLmQHUtOmwZNVDCsJ1jFRkhHGKaWMXTXtiNp2fzvkH4d3NCs0V9eKC9dFa0Mntgtdyt4qWuF2u6WQN/8VvLtr207GzTHVINbJyCXr1WocfZjClCVxHN9TsL/BsLsojEiSZBQoBVY+R2st7gq51/cXHD5lbJamSj5ncJll6egqiqJR0DYNvwDthK1//AEqzAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;TraceCockpit&quot;
        title=&quot;&quot;
        src=&quot;/static/461e75a65c523c3069ec842afd625d20/8c557/TraceCockpit.png&quot;
        srcset=&quot;/static/461e75a65c523c3069ec842afd625d20/4edbd/TraceCockpit.png 175w,
/static/461e75a65c523c3069ec842afd625d20/13ae7/TraceCockpit.png 350w,
/static/461e75a65c523c3069ec842afd625d20/8c557/TraceCockpit.png 700w,
/static/461e75a65c523c3069ec842afd625d20/cab8c/TraceCockpit.png 744w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The advice here is to install and setup it before the actual problem happens. In this case, you can easily run the trace when needed.&lt;/p&gt;
&lt;h2 id=&quot;summary&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#summary&quot; aria-label=&quot;summary permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Summary&lt;/h2&gt;
&lt;p&gt;Using these basic steps you can resolve your Dynamics AX performance problems and make your users happy. All scripts related to this post are available on my &lt;a href=&quot;https://github.com/TrudAX/TRUDScripts/blob/master/Performance/AX%20Technical%20Audit.md&quot;&gt;GitHub&lt;/a&gt;. I also described some performance-related issues that were resolved using the provided approach - &lt;a href=&quot;https://denistrunin.com/performance-examplesAx2012/&quot;&gt;Examples of AX2012/ AX2009 performance problems&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update 10/10/2020&lt;/strong&gt; - If you want to know how to organize a performance optimization project, &lt;a href=&quot;https://denistrunin.com/performance-projmanage/&quot;&gt;check this post&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you need help you can contact me. Or if you see that some useful staff is missing, feel free to post a comment.&lt;/p&gt;
&lt;p&gt;There are some Microsoft blog posts about performance: &lt;a href=&quot;https://cloudblogs.microsoft.com/dynamics365/no-audience/2014/09/11/managing-general-performance-issues-in-microsoft-dynamics-ax/?source=axsupport&quot;&gt;Managing general performance issues in Microsoft Dynamics AX&lt;/a&gt;, &lt;a href=&quot;https://cloudblogs.microsoft.com/dynamics365/no-audience/2016/09/08/analysis-scripts-for-performance-analyzer-v2-0/?source=axsupport&quot;&gt;Analysis scripts for Performance Analyzer v2.0&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Also worth to check this great SQL Server resources collection - &lt;a href=&quot;https://github.com/ktaranov/sqlserver-kit&quot;&gt;SQL Server KIT&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[How to design a successful integration]]></title><description><![CDATA[There are many ways to implement integration between D365FO and external systems. In this document, I propose the actual checklist of what you need to consider to successfully design an integration solution]]></description><link>https://denistrunin.com/integration-checklist/</link><guid isPermaLink="false">https://denistrunin.com/integration-checklist/</guid><pubDate>Wed, 17 Apr 2019 22:12:03 GMT</pubDate><content:encoded>&lt;p&gt;There are many ways to implement integration between D365FO and external systems. To choose the correct approach you need to clearly understand integration requirements before doing actual programming/setup. In this document, I propose the actual checklist of what you need to consider to successfully design an integration solution. The checklist is based on Oracle guidelines and contains questions that you need to ask while designing integration and before choosing between different integration methods(&lt;a href=&quot;https://github.com/TrudAX/TRUDScripts/blob/master/Documents/Integration/Integration%20Data%20Flow%20Requirements.md&quot;&gt;https://github.com/TrudAX/TRUDScripts/blob/master/Documents/Integration/Integration%20Data%20Flow%20Requirements.md&lt;/a&gt;):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Defining the Integration Solution Topology&lt;/li&gt;
&lt;li&gt;Defining Data Flow Requirements&lt;/li&gt;
&lt;li&gt;Analysing the Data Flow properties&lt;/li&gt;
&lt;li&gt;Defining the Quality of Service&lt;/li&gt;
&lt;li&gt;Performance&lt;/li&gt;
&lt;li&gt;Availability and Reliability&lt;/li&gt;
&lt;li&gt;Security&lt;/li&gt;
&lt;li&gt;Scalability&lt;/li&gt;
&lt;li&gt;Logging and Nonrepudiation&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Every question in this document is important and can dramatically change the integration approach. For example, if you have an external system that needs to query D365FO for some information(like item prices) and it requires 24x7 availability, you can&apos;t use any direct calls(like OData, Webservices) to D365FO as it obviously will not be available 24x7(during new releases, hotfix installations..)&lt;/p&gt;
&lt;h2 id=&quot;keys-to-the-successful-integration&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#keys-to-the-successful-integration&quot; aria-label=&quot;keys to the successful integration permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Keys to the successful integration&lt;/h2&gt;
&lt;p&gt;Integration has never been easy. Here I try to describe the most problematic moments.&lt;/p&gt;
&lt;h3 id=&quot;performance&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#performance&quot; aria-label=&quot;performance permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Performance&lt;/h3&gt;
&lt;p&gt;You need to clearly define and test the amount of data that needs to be processed and the time interval when processing should be done.&lt;/p&gt;
&lt;p&gt;Even simple solutions can cause problems. For example, the client can ask you to develop a webservice that returns a list of vendors. It can be easily developed and tested without asking additional questions, but on production system you may see hundreds of calls per minute to this webservice that may completely stop the whole system and make your client unhappy. By asking a simple question from this checklist - &quot;Why do you need this webservice and how often do you plan to call it? and getting the answer - &quot;One call per document line&quot; you can fix the proposed design before it is implemented.&lt;/p&gt;
&lt;h3 id=&quot;transaction-support&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#transaction-support&quot; aria-label=&quot;transaction support permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Transaction support&lt;/h3&gt;
&lt;p&gt;When working with business documents transaction support is often required. For example, you import 10-line sales order from the external system, and 1 line can&apos;t be created due to some validation. In most cases you don&apos;t want to create a sales order with only 9 lines, the whole document should be rejected and often this behavior is implemented via SQL transaction support. This requirement may limit possible solutions as standard D365FO Data management module doesn&apos;t support transactions, you can&apos;t write several records in one transaction&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/52677eadd85b672ba94f3f02f9c9ee7c/cda19/EntityWrite.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 34.285714285714285%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAAA7EAAAOxAGVKw4bAAABQUlEQVR42oVQy0oDQRDcPzaJghLBRS9JLoIHvRnBT/APRIhec/aieDCbbGZ2MjvvmS17Nl41DUVV0013dReL5zleXx7w8f6E+eM9zi5vUE5vcZEx2aOc3eG0vMZoUOLo5ArD8RSj84wZjgmD8aTPh8RF1bQwxqHrgJgSXOxgtYZqJQyxUQpaK0jO8P22APv67Pui90ghIMWAGPwvAgqmLfK0ECOcp2LqEEkHKmbe68w0hPrysC5v/yOKldS9sD5CBXJnHXTvitzRMmMMlNKQOwnvHA5FUSvTO9TVGlvGwXhDXEPJBtZZ+OBomSVtetc5/jGIYp0H0lntcklOHFpjoYWG5wmhpRMVQdJLJOUuHHZY0ckd/WW32aBuFTgtYDXDerUF3zaQ0oO3DjX1MbFDvanBWANBWggBTlc1XPQ/TqnDDwBNCS0ZLP1YAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;EntityWrite&quot;
        title=&quot;&quot;
        src=&quot;/static/52677eadd85b672ba94f3f02f9c9ee7c/8c557/EntityWrite.png&quot;
        srcset=&quot;/static/52677eadd85b672ba94f3f02f9c9ee7c/4edbd/EntityWrite.png 175w,
/static/52677eadd85b672ba94f3f02f9c9ee7c/13ae7/EntityWrite.png 350w,
/static/52677eadd85b672ba94f3f02f9c9ee7c/8c557/EntityWrite.png 700w,
/static/52677eadd85b672ba94f3f02f9c9ee7c/cda19/EntityWrite.png 785w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;In this case, you either need to implement your own transaction system(via additional flags) or write more custom code that was initially planned&lt;/p&gt;
&lt;h3 id=&quot;logging-and-traceability&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#logging-and-traceability&quot; aria-label=&quot;logging and traceability permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Logging and traceability&lt;/h3&gt;
&lt;p&gt;Logging and traceability should be a base requirement. For export scenarios, it should be easy to identify what was exported and when this particular record was processed, for import scenarios - what the original incoming request, its processing status and created documents were. And vice verse - by the document you should be able to identify the original integration message.&lt;/p&gt;
&lt;h3 id=&quot;errors-handling&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#errors-handling&quot; aria-label=&quot;errors handling permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Errors handling&lt;/h3&gt;
&lt;p&gt;Errors are often divided into 2 categories - that can and that can&apos; be resolved by subsequent executions. For example, when you are reading data from the file, and its structure is not what you expect to see - you can mark this file with an error flag and move it to the Errors folder. If the file contains a vendor code that doesn&apos;t exist in the system, probably you can just show an error and then try to process this file again(a vendor may be created later).&lt;/p&gt;
&lt;p&gt;You should also think if there will not be any reaction from the system administrator to these errors. Growing numbers of old errors can stop new messages from processing, so you should implement some logic to mark such messages as skipped after some time(or a number of processing attempts). Import and processing stage separation(via the staging tables) is also a good idea.&lt;/p&gt;
&lt;h3 id=&quot;file-usage&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#file-usage&quot; aria-label=&quot;file usage permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;File usage&lt;/h3&gt;
&lt;p&gt;As D365FO is a cloud-based system often people ask: what about our existing file based integration that reads/writes files from the network share? And the answer is: if you want you can use the same approach in the cloud by replacing network storage to Azure file storage. From the user perspective it can look the same as a mapped drive in Windows. Libraries to work with the Azure storage are very similar to the File libraries(see the example &lt;a href=&quot;https://ievgensaxblog.wordpress.com/2017/07/16/d365fo-working-with-azure-file-storage/&quot;&gt;here&lt;/a&gt; and one of the options to store connection strings &lt;a href=&quot;https://www.agermark.com/2018/09/how-to-setup-azure-key-vault-with.html&quot;&gt;here&lt;/a&gt; )&lt;/p&gt;
&lt;h3 id=&quot;async-and-sync&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#async-and-sync&quot; aria-label=&quot;async and sync permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Async and sync&lt;/h3&gt;
&lt;p&gt;From my experience, it is better to try to avoid synchronous calls, especially when you don&apos;t control the external system. It&apos;s is not always possible, but if you can do this, better to implement some middleware storage where you can read/write messages. So if the 3-party app doesn&apos;t need real-time access, instead of providing ODATA or Webservice interfaces better to upload the data they required to SQL Azure database, File storage or somewhere else. It can solve a lot of problems - they can&apos;t slow down your system by querying a lot of data and you avoid complains like &quot;while making ODATA request we get a timeout error&quot;.&lt;/p&gt;
&lt;h3 id=&quot;reproduction-and-testing-support&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#reproduction-and-testing-support&quot; aria-label=&quot;reproduction and testing support permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Reproduction and testing support&lt;/h3&gt;
&lt;p&gt;It should be easy to reproduce/test single message processing. If your integration works with physical devices, you should think about a device emulator; if you are processing files from the specified folder(or processing data from the messages table), your solution should allow to select an individual file/message to process. This allows to quickly debug, test and solve potentials problems.&lt;/p&gt;
&lt;h2 id=&quot;summary&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#summary&quot; aria-label=&quot;summary permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Summary&lt;/h2&gt;
&lt;p&gt;I uploaded this checklist to &lt;a href=&quot;https://github.com/TrudAX/TRUDScripts/blob/master/Documents/Integration/Integration%20Data%20Flow%20Requirements.md&quot;&gt;GitHub&lt;/a&gt;. If you see that some  questions are missing, feel free to post a comment.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Create ledger journals in D365FO using X++]]></title><description><![CDATA[Create ledger journals using X++ is quite a common task, in this post I'll try to describe possible options how to perform it]]></description><link>https://denistrunin.com/xpptools-createledgerjournal/</link><guid isPermaLink="false">https://denistrunin.com/xpptools-createledgerjournal/</guid><pubDate>Tue, 16 Apr 2019 20:12:03 GMT</pubDate><content:encoded>&lt;p&gt;Creating LedgerJournalTrans using X++ is quite a common task, but sometimes I still see some mistakes(mostly related to fields initialization from account/offset account and voucher assignment). In this post, I&apos;ll try to describe possible options how to create ledger journals in D365FO.&lt;/p&gt;
&lt;h2 id=&quot;test-scenario&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#test-scenario&quot; aria-label=&quot;test scenario permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Test scenario&lt;/h2&gt;
&lt;p&gt;To test different methods, I wrote a Runnable class &lt;a href=&quot;https://github.com/TrudAX/XppTools/blob/master/DEVTutorial/DEVTutorial/AxClass/DEVTutorialCreateLedgerJournal.xml&quot;&gt;DEVTutorialCreateLedgerJournal&lt;/a&gt; that creates a new journal based on the data from the existing source journal using different methods. The dialog looks like this&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 522px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/3b454057f11bbce96f4f321366c00167/29492/CopyJournalDialog.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 48.57142857142858%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAA4UlEQVR42qVSTWuFMBDM//9V3sWj0EOh0IPQoibRpPlSp5kFH4Xnoe+9hSGzWRx3M6v6vkfbtui6Dk3TgDk5MQwDGMdx4L+h9n1HKUU+SikJzzkLWHs0lPcey7JgXdebAMWfRRX8gdYzrLVPdXQ5soyYMkKMrwtaH/H2/oHP4Qtmrd26hAc8uBcMqeB70tCLg48ZxgUxhmD327bd8TM/DSXOmip1XL6ftQZGawHzeZ7FLPJxHG9c1zpzmuicwzRNcmeMESiqkvAPjP2VeTkyBUMIiNUQnhT/u8jnOlyt09XdL0GIEFnjaZQYAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Dialog image&quot;
        title=&quot;&quot;
        src=&quot;/static/3b454057f11bbce96f4f321366c00167/29492/CopyJournalDialog.png&quot;
        srcset=&quot;/static/3b454057f11bbce96f4f321366c00167/4edbd/CopyJournalDialog.png 175w,
/static/3b454057f11bbce96f4f321366c00167/13ae7/CopyJournalDialog.png 350w,
/static/3b454057f11bbce96f4f321366c00167/29492/CopyJournalDialog.png 522w&quot;
        sizes=&quot;(max-width: 522px) 100vw, 522px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Let&apos;s discuss possible copy options(&lt;em&gt;Copy type&lt;/em&gt; parameter):&lt;/p&gt;
&lt;h2 id=&quot;ledgerjournalengine-class&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#ledgerjournalengine-class&quot; aria-label=&quot;ledgerjournalengine class permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;LedgerJournalEngine class&lt;/h2&gt;
&lt;p&gt;This method is using LedgerJournalEngine class - the same class that is used when the user creates a journal manually on the Journal lines form. This increases the chances that the resulting line will be the same as a manually created line.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;select&lt;/span&gt; ledgerJournalTransOrig
    order &lt;span class=&quot;token keyword&quot;&gt;by&lt;/span&gt; RecId
            &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ledgerJournalTransOrig&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;JournalNum &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; _ledgerJournalTableOrig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;JournalNum
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    numLines&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;ledgerJournalTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;RecId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;//Often journal name from parameters is specified here&lt;/span&gt;
        DEV&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;validateCursorField&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ledgerJournalName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fieldNum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LedgerJournalName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; JournalName&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        ledgerJournalTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;clear&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        ledgerJournalTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;initValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        ledgerJournalTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;JournalName &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ledgerJournalName&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;JournalName&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        ledgerJournalTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;initFromLedgerJournalName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        ledgerJournalTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;JournalNum &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; JournalTableData&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;newTable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ledgerJournalTable&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;nextJournalId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        ledgerJournalTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;strFmt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Copy of %1, Date %2&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _ledgerJournalTableOrig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;JournalNum&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token named-parameter punctuation&quot;&gt;DEV&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;systemdateget&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        ledgerJournalTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;insert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token function&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;strFmt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Journal %1 created&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ledgerJournalTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;JournalNum&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;        ledgerJournalEngine &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; LedgerJournalEngine&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;construct&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ledgerJournalTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;JournalType&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;        ledgerJournalEngine&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;newJournalActive&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ledgerJournalTable&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;clear&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;initValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    ledgerJournalEngine&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;initValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
    ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;JournalNum           &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;   ledgerJournalTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;JournalNum&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;TransDate            &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;   DEV&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;systemdateget&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;AccountType          &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;   ledgerJournalTransOrig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;AccountType&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;modifiedField&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fieldNum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LedgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; AccountType&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;LedgerDimension &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ledgerJournalTransOrig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;LedgerDimension&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;LedgerDimension&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Missing or invalid ledger dimension for journal process&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;modifiedField&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fieldNum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LedgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LedgerDimension&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    ledgerJournalEngine&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;accountModified&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LedgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
    ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;OffsetAccountType &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ledgerJournalTransOrig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;OffsetAccountType&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;modifiedField&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fieldNum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LedgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; OffsetAccountType&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;OffsetLedgerDimension &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ledgerJournalTransOrig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;OffsetLedgerDimension&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;modifiedField&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fieldNum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LedgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; OffsetLedgerDimension&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    ledgerJournalEngine&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;offsetAccountModified&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;//amounts&lt;/span&gt;
    LedgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;CurrencyCode         &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;   ledgerJournalTransOrig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;CurrencyCode&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ledgerJournalEngine&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;currencyModified&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LedgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    LedgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;AmountCurCredit      &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;   ledgerJournalTransOrig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;AmountCurCredit&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    LedgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;AmountCurDebit       &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;   ledgerJournalTransOrig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;AmountCurDebit&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;//additional fields&lt;/span&gt;
    LedgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Approver           &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; HcmWorker&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;userId2Worker&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;curuserid&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    LedgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Approved           &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; NoYes&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;Yes&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Txt                &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ledgerJournalTransOrig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Txt&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    LedgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;SkipBlockedForManualEntryCheck &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    DEV&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;validateWriteRecordCheck&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;insert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    ledgerJournalEngine&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When you modify Account/Offset account fields in this example you need to call two methods(on &lt;em&gt;ledgerJournalTrans&lt;/em&gt; and &lt;em&gt;ledgerJournalEngine&lt;/em&gt;). This ensures that the line will be properly initialized from the Account/Offset account field.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;modifiedField&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fieldNum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LedgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LedgerDimension&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  
ledgerJournalEngine&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;accountModified&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LedgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Voucher assignment here is processing in &lt;em&gt;ledgerJournalEngine.write().&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Also, an interesting flag here is LedgerJournalTrans.SkipBlockedForManualEntryCheck. It is useful when you don&apos;t want to allow users to create manually lines with the same accounts as in your procedure.&lt;/p&gt;
&lt;h3 id=&quot;ledgerjournaltrans-defaultrow-method&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#ledgerjournaltrans-defaultrow-method&quot; aria-label=&quot;ledgerjournaltrans defaultrow method permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;LedgerJournalTrans defaultRow() method&lt;/h3&gt;
&lt;p&gt;This is a new approach in D365FO and it uses a new &lt;em&gt;defaultRow()&lt;/em&gt; table method. Data entities also call this method during the import process. Its idea is that we don&apos;t control the sequence of different &lt;em&gt;modifiedField&lt;/em&gt; method calls, we just populate the fields that we know, all other logic happens in the &lt;em&gt;defaultRow()&lt;/em&gt; method.&lt;/p&gt;
&lt;p&gt;Code for journal creation in this case:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;select&lt;/span&gt; ledgerJournalTransOrig
    order &lt;span class=&quot;token keyword&quot;&gt;by&lt;/span&gt; RecId
    &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ledgerJournalTransOrig&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;JournalNum &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; _ledgerJournalTableOrig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;JournalNum
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    numLines&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;ledgerJournalTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;RecId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        ledgerJournalTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;clear&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        ledgerJournalTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;initValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        ledgerJournalTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;JournalName &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; _ledgerJournalTableOrig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;JournalName&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        ledgerJournalTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;initFromLedgerJournalName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        ledgerJournalTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;JournalNum &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; JournalTableData&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;newTable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ledgerJournalTable&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;nextJournalId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        ledgerJournalTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;strFmt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Copy of %1, Date %2&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _ledgerJournalTableOrig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;JournalNum&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token named-parameter punctuation&quot;&gt;DEV&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;systemdateget&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        ledgerJournalTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;insert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token function&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;strFmt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Journal %1 created&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ledgerJournalTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;JournalNum&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;clear&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;initValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;JournalNum             &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ledgerJournalTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;JournalNum&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;TransDate              &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; DEV&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;systemdateget&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;AccountType            &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ledgerJournalTransOrig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;AccountType&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;LedgerDimension        &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ledgerJournalTransOrig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;LedgerDimension&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;DefaultDimension       &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ledgerJournalTransOrig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;DefaultDimension&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;OffsetAccountType      &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ledgerJournalTransOrig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;OffsetAccountType&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;OffsetLedgerDimension  &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ledgerJournalTransOrig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;OffsetLedgerDimension&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;OffsetDefaultDimension &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ledgerJournalTransOrig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;OffsetDefaultDimension&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;CurrencyCode           &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;   ledgerJournalTransOrig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;CurrencyCode&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;AmountCurCredit        &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;   ledgerJournalTransOrig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;AmountCurCredit&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;AmountCurDebit         &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;   ledgerJournalTransOrig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;AmountCurDebit&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;//addition fields&lt;/span&gt;
    ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Approver           &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; HcmWorker&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;userId2Worker&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;curuserid&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Approved           &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; NoYes&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;Yes&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Txt                &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ledgerJournalTransOrig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Txt&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;SkipBlockedForManualEntryCheck &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;defaultRow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
    DEV&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;validateWriteRecordCheck&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ledgerJournalTrans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;insert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You can find an example of this approach in the &lt;strong&gt;MCRLedgerJournal&lt;/strong&gt; class (and the usage is &lt;a href=&quot;https://www.linkedin.com/pulse/simplest-way-create-general-journal-d365-using-code-udoye-samuel/&quot;&gt;here&lt;/a&gt;)&lt;/p&gt;
&lt;h3 id=&quot;data-entity&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#data-entity&quot; aria-label=&quot;data entity permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Data entity&lt;/h3&gt;
&lt;p&gt;We can also use a data entity for journal creation. Technically it produces the same result as the previous method because a data entity at the end will call a table defaultRow() method.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;select&lt;/span&gt; ledgerJournalTransOrig
    order &lt;span class=&quot;token keyword&quot;&gt;by&lt;/span&gt; RecId
    &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ledgerJournalTransOrig&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;JournalNum &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; _ledgerJournalTableOrig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;JournalNum
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    numLines&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;select&lt;/span&gt; dimensionCombinationEntity
        &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;dimensionCombinationEntity&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;RecId &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; ledgerJournalTransOrig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;LedgerDimension&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;select&lt;/span&gt; dimensionCombinationEntityOffset
        &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;dimensionCombinationEntityOffset&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;RecId &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; ledgerJournalTransOrig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;OffsetLedgerDimension&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    ledgerJournalEntity&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;initValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ledgerJournalEntity&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;JournalBatchNumber     &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; journalNum&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ledgerJournalEntity&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Description            &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;strFmt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Copy of %1, Date %2&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _ledgerJournalTableOrig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;JournalNum&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token named-parameter punctuation&quot;&gt;DEV&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;systemdateget&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ledgerJournalEntity&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;JournalName            &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; _ledgerJournalTableOrig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;JournalName&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ledgerJournalEntity&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;LineNumber&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;//if you have string and want to convert to ID - DimensionDefaultResolver::newResolver(_dimensionDisplayValue).resolve();&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;//AX &gt; General ledge &gt; Chart of accounts &gt; Dimensions &gt; Financial dimension configuration for integrating applications&lt;/span&gt;
    ledgerJournalEntity&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;AccountType                 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ledgerJournalTransOrig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;AccountType&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ledgerJournalEntity&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;AccountDisplayValue         &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; dimensionCombinationEntity&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;DisplayValue&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    ledgerJournalEntity&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;OffsetAccountType           &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ledgerJournalTransOrig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;OffsetAccountType&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ledgerJournalEntity&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;OffsetAccountDisplayValue   &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; dimensionCombinationEntityOffset&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;DisplayValue&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    ledgerJournalEntity&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;CreditAmount                &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ledgerJournalTransOrig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;AmountCurCredit&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ledgerJournalEntity&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;DebitAmount                 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ledgerJournalTransOrig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;AmountCurDebit&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ledgerJournalEntity&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;CurrencyCode                &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ledgerJournalTransOrig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;CurrencyCode&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ledgerJournalEntity&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;TEXT                        &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ledgerJournalTransOrig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Txt&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ledgerJournalEntity&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;TRANSDATE                   &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ledgerJournalTransOrig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;TransDate&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    ledgerJournalEntity&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;defaultRow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
    DEV&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;validateWriteRecordCheck&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ledgerJournalEntity&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    ledgerJournalEntity&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;insert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;

    journalNum &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ledgerJournalEntity&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;JournalBatchNumber&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As you see this method requires less code: we don&apos;t even need to write code for the journal header creation, it is all handled by the data entity insert() method. Dimensions can be also specified as strings. However there are some limitations: sometimes data entity doesn&apos;t contain all the table fields and it doesn&apos;t support all account types.&lt;/p&gt;
&lt;h2 id=&quot;performance-testing&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#performance-testing&quot; aria-label=&quot;performance testing permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Performance testing&lt;/h2&gt;
&lt;p&gt;Let&apos;s test the performance. First I created a test journal with the 1000 lines(**&lt;em&gt;createByCombination&lt;/em&gt; method) and then copied it using these 3 different methods. I got the following results:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&quot;left&quot;&gt;Method&lt;/th&gt;
&lt;th align=&quot;left&quot;&gt;Time to create 1000 lines(sec)&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;Using ledgerJournalEngine&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;30.54&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;Using DataEntity&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;33.09&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;Using Table defaultRow method&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;15.18&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;There are some differences between the copy speed in my example, but it is caused by a different logic for the dimension creation, so the result is that all methods are almost equal and quite fast. In a real-life scenario, you can expect an insert speed 10-30 lines per second.&lt;/p&gt;
&lt;h2 id=&quot;choosing-the-right-method-and-things-to-avoid&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#choosing-the-right-method-and-things-to-avoid&quot; aria-label=&quot;choosing the right method and things to avoid permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Choosing the right method and things to avoid&lt;/h2&gt;
&lt;p&gt;In general, you have 2 options - to create a journal similar to the manual user entry or create it similar to the import procedure(for the second scenario choice between entity and table mostly depends on what input data you have and whether the entity supports all the required fields). So the choice between these two should be made by answering the question: if the user wants to create the same journal manually, does he use manual entry or data import? Use &lt;a href=&quot;https://github.com/TrudAX/XppTools/blob/3d69455f4b8157bc28bfc9560e9f70c8bacd634a/DEVTutorial/DEVTutorial/AxClass/DEVTutorialCreateLedgerJournal.xml#L196&quot;&gt;createJournalUsingLedgerJournalEngine&lt;/a&gt; as default, as it is more flexible.&lt;/p&gt;
&lt;p&gt;Probably in D365FO it is better to avoid creation using &lt;em&gt;JournalTransData&lt;/em&gt; classes or when you simply populate &lt;em&gt;ledgerJournalTrans&lt;/em&gt; fields and call &lt;em&gt;insert()&lt;/em&gt;. This initially can work, but later users may complain - e.g. &lt;em&gt;&quot;Why when I create a journal manually and specify a vendor account the Due date field is calculated, but your procedure doesn&apos;t fill it&quot;.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;summary&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#summary&quot; aria-label=&quot;summary permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Summary&lt;/h2&gt;
&lt;p&gt;You can download this class using the following link &lt;a href=&quot;https://github.com/TrudAX/XppTools/blob/master/DEVTutorial/DEVTutorial/AxClass/DEVTutorialCreateLedgerJournal.xml&quot;&gt;https://github.com/TrudAX/XppTools/blob/master/DEVTutorial/DEVTutorial/AxClass/DEVTutorialCreateLedgerJournal.xml&lt;/a&gt;. The idea is that you can use this code as a template when you have a task to create(or post) a ledger journal using X++.
Comments are welcome.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Tool to filter in a query as a developer]]></title><description><![CDATA[X++ tool that adds a system field name in a standard query filter field lookup]]></description><link>https://denistrunin.com/xpptools-queryfieldsaotname/</link><guid isPermaLink="false">https://denistrunin.com/xpptools-queryfieldsaotname/</guid><pubDate>Thu, 07 Mar 2019 22:12:03 GMT</pubDate><content:encoded>&lt;p&gt;In the standard Advanced query filter dialog, when you select a field to filter, standard lookup displays only a field label. Sometimes, it is more convenient to filter by field AOT name(and not by the label).&lt;/p&gt;
&lt;p&gt;This tool adds a new column in the standard Field lookup dialog, so you can search the required field by label or by AOT name.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 614px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/ff347566d679d3769f21366fd618c7d6/e9131/DEVQueryFieldsAOTName.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 71.42857142857143%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACAElEQVR42p1TyW7bMBTU//feD+mlX5BDC7RwsyG1JVmWtVEySe0UqWX6RDWNe2maCCBIDonRm3lDJwxD7HY75HkOz/Pgui4e7u+x4u/5HKUU2rbFOI5YluVqbBeWtxLWdQ3GGIQQFpimCcaMOPMOj0eGIO/Q6vn/CZumQdd1tsK+7zET4TAMUHqEMhONGdP8hgqTXKAQFeZ53ghp1lrb+V0e6mlB2Y8QrQZvNKrebN4tL2Pbv7j5vP7b8w1zptFAq95K3jwcSbLCoNZqJ4uvFT8TzPNifV7vrPZc/cXizodPd/j4+Q4RkzgkEkdW4TFgePBT+FkNN+Y4RymynFtrOqWRXSrceimeTjmdC+zDAgGr0fYazle3wM19iFOUwAsTMNHAP6fwTjHSS4nVY1ZwxFmOsunQDwaVMoiPEZ5uvmD/7Qfc77dIfvoQexfOar4xGqrvoK0M6i7JXfejMegpAavksixt02wqKLtdmoDHEWRd0ZlAQ2eCHoYzku7lH+ldI7QS8ksBKTgkv0CWEipn4NEZQkqLcSlQBsetwuuO/TH/97pqFVLZw48vOCYcYSaR1hrszODuAxyiHEEqENOdiPbOa3kriTCmV3NYCaICUdFAUNPTU4aDG1IjOXwi5JS2LEheJ1RqsF6WJKmpKvJ5sLgmyaV7QM0yNOTn1DYwQYBfkXQ53yr9nw8AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;DEVQueryFieldsAOTName&quot;
        title=&quot;&quot;
        src=&quot;/static/ff347566d679d3769f21366fd618c7d6/e9131/DEVQueryFieldsAOTName.png&quot;
        srcset=&quot;/static/ff347566d679d3769f21366fd618c7d6/4edbd/DEVQueryFieldsAOTName.png 175w,
/static/ff347566d679d3769f21366fd618c7d6/13ae7/DEVQueryFieldsAOTName.png 350w,
/static/ff347566d679d3769f21366fd618c7d6/e9131/DEVQueryFieldsAOTName.png 614w&quot;
        sizes=&quot;(max-width: 614px) 100vw, 614px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;UPDATE - the same field was also added into the &quot;Personalize-Add columns&quot; dialog(thanks @wojzeh for the idea)&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/659ee67c6937f3170c4ab9415993729d/442cb/DEVQueryFieldsAOTNamePers.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 42.857142857142854%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABzklEQVR42o2SzY7aMBDHc0W8CWduPAbvsRVPwDNw4NiVEOICpSt1hZB4g3a1XVVtVcQCiYBsyJcT2yHkw8m/k2x7x9LIf4/HP8/Yo3U6HbTbbXS7Xbiui/1+D8MwsNvtcL1eceMo/s1/tOVyicVigdVqhSiKIARHJCXi+II8z1EUBZRStwN7vR7u7j6g3+/XwCxXSLIceVEiV0UNrOxmYLPZRKPRQKvVAuccmSoRRFeIOCP9HlcSvCzLSpFWZO9+JQXygEHxsKByoJj/qg2HQwwGA9zffwQLBTyZwmEcgYjBLylkomgt4QYSUVLA9gWcIIK8ZDB+/MZua+CoH3H2QjhP3wttPp9jNpvh8fELXD/E1uLQ3zysDQs704PNE+iWj+3RgSsJcmbYHGyc2QXbXxtsTi62hzNePQnn5xraeDzGaDTCdDpFGAS4UBkB8+E4dMiyYNvn2u+6Tl2y4JSJbUOlCXzqhJN5wtvxAJP2nW9foU0mE1TQKktGB0NOQJo9z0MYhkjTlHy8/rDqGYWQ8HwfeZLC03V6DgbGAiR03XWzgTadUcmf5vj88FCDhBAUwGpdtU01/vtqTfCqXxXtWS8vsNZrxKaJjC6Pn5/VX1j/kFWAWjNxAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;DEVQueryFieldsAOTNamePers&quot;
        title=&quot;&quot;
        src=&quot;/static/659ee67c6937f3170c4ab9415993729d/8c557/DEVQueryFieldsAOTNamePers.png&quot;
        srcset=&quot;/static/659ee67c6937f3170c4ab9415993729d/4edbd/DEVQueryFieldsAOTNamePers.png 175w,
/static/659ee67c6937f3170c4ab9415993729d/13ae7/DEVQueryFieldsAOTNamePers.png 350w,
/static/659ee67c6937f3170c4ab9415993729d/8c557/DEVQueryFieldsAOTNamePers.png 700w,
/static/659ee67c6937f3170c4ab9415993729d/442cb/DEVQueryFieldsAOTNamePers.png 752w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;summary&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#summary&quot; aria-label=&quot;summary permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Summary&lt;/h2&gt;
&lt;p&gt;You can download this tool using the following link &lt;a href=&quot;https://github.com/TrudAX/XppTools#-display-system-field-name-in-the-query-filter&quot;&gt;https://github.com/TrudAX/XppTools#-display-system-field-name-in-the-query-filter&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you have some ideas how to improve it, feel free to create a GitHub pull request or leave a comment.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Working with Financial dimensions in D365FO]]></title><description><![CDATA[Working with the financial dimensions framework has become much more difficult starting with the AX2012. This post describes the most common problems and how to resolve them]]></description><link>https://denistrunin.com/xpptools-devfindim/</link><guid isPermaLink="false">https://denistrunin.com/xpptools-devfindim/</guid><pubDate>Wed, 06 Mar 2019 22:12:03 GMT</pubDate><content:encoded>&lt;p&gt;Working with the financial dimensions framework has become much more difficult starting with the AX2012. This post describes the most common problems and how to resolve them.&lt;/p&gt;
&lt;h2 id=&quot;the-current-problems&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#the-current-problems&quot; aria-label=&quot;the current problems permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;The current problems&lt;/h2&gt;
&lt;p&gt;The current challenges that I saw on the projects while working with the financial dimensions framework were the following:&lt;/p&gt;
&lt;h3 id=&quot;misunderstanding-of-the-concept&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#misunderstanding-of-the-concept&quot; aria-label=&quot;misunderstanding of the concept permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Misunderstanding of the concept&lt;/h3&gt;
&lt;p&gt;There is no starting point if you want to learn Financial dimensions framework. The best I found is the original &lt;a href=&quot;http://download.microsoft.com/download/4/e/3/4e36b655-568e-4d4a-b161-152b28baaf30/implementing_the_account_and_financial_dimensions_framework_ax2012.pdf&quot;&gt;Implementing the Account and Financial Dimensions Framework for Microsoft Dynamics AX 2012 Applications&lt;/a&gt; whitepaper that explains the concept, but its content is quite outdated for D365FO. GitHub &lt;a href=&quot;https://github.com/MicrosoftDocs/dynamics-365-unified-operations-public/issues/236&quot;&gt;request&lt;/a&gt; to update this document was closed, standard D365FO &lt;a href=&quot;https://docs.microsoft.com/en-us/dynamics365/unified-operations//dev-itpro/financial/financial-dev-home-page&quot;&gt;Financials development home page&lt;/a&gt; contains some really specific information and no basic overview.&lt;/p&gt;
&lt;h3 id=&quot;reference-to-the-dimension&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#reference-to-the-dimension&quot; aria-label=&quot;reference to the dimension permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Reference to the dimension&lt;/h3&gt;
&lt;p&gt;Sometimes you need to reference just one dimension value(for example get or set &quot;Cost center&quot; value). You don&apos;t see many examples of this in the standard application, as in most cases dimension merging is using. In AX2009 it was quite easy - you had an enum and could use it to get or set the value. In the current version, you need somehow to reference a record in the &lt;em&gt;DimensionAttribute&lt;/em&gt; table and there is no &quot;recommended&quot; way of doing this. So, I have seen different implementations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Add &lt;em&gt;DimensionAttribute&lt;/em&gt; to parameters(as String or as RecId)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a new table with enum and reference to &lt;em&gt;DimensionAttribute&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Search &lt;em&gt;DimensionAttribute&lt;/em&gt; by backing table ID&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Search &lt;em&gt;DimensionAttribute&lt;/em&gt; by name defined as a Macro&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;... sometimes combinations of these options to access the same dimensions&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All this can create a real mess, some of these options require a setup, some aren&apos;t compatible with cross-references.&lt;/p&gt;
&lt;h3 id=&quot;problem-methods-for-working-with-dimensions&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#problem-methods-for-working-with-dimensions&quot; aria-label=&quot;problem methods for working with dimensions permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Problem: Methods for working with Dimensions&lt;/h3&gt;
&lt;p&gt;There are a lot of classes to manipulate dimensions, so it is often difficult to find the right one. Moreover, classes related to dimension were renamed in D365FO(comparing to AX2012). As a result, developers sometimes create a duplicate of the existing methods.&lt;/p&gt;
&lt;p&gt;For example, if you google &quot;assign a value to default dimension&quot; the first link will point to the 2-page method&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 699px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/ea337539e0dadf929ede47a118390251/3fe45/DimLongMethod.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 109.14285714285714%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAWCAYAAADAQbwGAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACsUlEQVR42n1VB5LjMAzL/195W5K4ybIs17jwAFr0eud2LzMYFUsUCELKLS8K+fy8K97e3+XP2zvaD/nA+PHM5PEAskyquhbfNFL7Rpz3R4s552oJbZR+GBS3uglSOC+VayQrKsBJXhK1PLNC59pulNiPEmIvTRyAHn20bSc+dNKPs0yvVXFbllXm1yLjhMl5lnXdTmzbLtu+i/2+er//buu6yv1+lzzPpUT68+t1fpymSfq+k67rpG1b9Hvp0Y+xlYixzqPfhqDfY4xkuIirnLDdwWbbVmDTgAyQQb+yKMVDswYaBmx2zkkN/WrV0On+CvDQVhlyIaPbqeM4anC2XMS5AYIro9Aqm4A92rZBmsD9nWaTUv5ENR+SPZ9glGNhVIY84I55nt6AYVVWUkCWHKzZFpApzwvNgtVmrBvTI0OezABMrUIafT/IOIzKpAFL6jaC5VcmEQeHb/pS8xurWeCUsixVqwLghw2ncSMLRTbUigeTpad+SUdKUmEv+9yrKbPCFNZO2ZNVyIgHUYIF62bYinjBCdZa36Ap0wohlZ5BX6i4LV4Wtou6wGDfFCmQOUMDduqtqGhTpXlI15nvonTpmyFAc2YzA3TDagGZXsD1I9Q+3RG4wdgKcATAGMGv6e77v3dHGda+PkV3ybA+mbY+W6fWsNT0KiKg4VtACk+vaeWwSa8h5pyrjpsA2BpW1Rib2Wno7Zqy3kNqR61Sgc6bwH4CM2BAgmNqN6mG03m7lCF9RA8xTfqMFvK1PxdxzRV7amm5K06GFLlRBse95Xhdjkfiapcrrlp+K4qJy4paKh5FsvRoHTKlXvToMBx9Y/RrQG4qK7zYePZ52Q0V5gg7rEKhWCBm8mPAa9lNC9Vt337Qb//SbvsPQ1aKViETGpwvjb7OyRb2HlraXP/bX8BfBCyk+jzTYswAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;DimLongMethod&quot;
        title=&quot;&quot;
        src=&quot;/static/ea337539e0dadf929ede47a118390251/3fe45/DimLongMethod.png&quot;
        srcset=&quot;/static/ea337539e0dadf929ede47a118390251/4edbd/DimLongMethod.png 175w,
/static/ea337539e0dadf929ede47a118390251/13ae7/DimLongMethod.png 350w,
/static/ea337539e0dadf929ede47a118390251/3fe45/DimLongMethod.png 699w&quot;
        sizes=&quot;(max-width: 699px) 100vw, 699px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Probably it can work but can cause difficulties with the support, performance and upgrades.&lt;/p&gt;
&lt;h2 id=&quot;proposed-solution---devdimensionhelper-class&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#proposed-solution---devdimensionhelper-class&quot; aria-label=&quot;proposed solution   devdimensionhelper class permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Proposed solution - DEVDimensionHelper class&lt;/h2&gt;
&lt;p&gt;To resolve the described issues I have created &lt;a href=&quot;https://github.com/TrudAX/XppTools/blob/master/DEVCommon/DEVCommon/AxClass/DEVDimensionHelper.xml&quot;&gt;DEVDimensionHelper&lt;/a&gt; class(you can rename it with your project prefix or use the default DEV). The idea is to collect all the necessary stuff in one place.&lt;/p&gt;
&lt;p&gt;In order to reference a dimension, you create a static method in this class with a default value&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Name&lt;/span&gt; BusinessUnit   &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &apos;BusinessUnit&apos;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;Name&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;BusinessUnit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;  
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; BusinessUnit&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In this case, you don&apos;t need to perform any setup and can use &quot;Find All References&quot;.&lt;/p&gt;
&lt;p&gt;Currently this class contains the following references:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create a new dimension&lt;/li&gt;
&lt;li&gt;Query filter by dimension&lt;/li&gt;
&lt;li&gt;Get Dimension value as string from the &lt;strong&gt;DefaultDimension&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Get Dimension value as string from the &lt;strong&gt;LedgerDimension&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Get a &lt;strong&gt;DefaultAccount&lt;/strong&gt; from the &lt;strong&gt;LedgerDimension&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Get a &lt;strong&gt;DefaultDimension&lt;/strong&gt; from the &lt;strong&gt;LedgerDimension&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Create a &lt;strong&gt;DefaultAccount&lt;/strong&gt; from the &lt;strong&gt;MainAccount&lt;/strong&gt;(String)&lt;/li&gt;
&lt;li&gt;Create a &lt;strong&gt;DefaultAccount&lt;/strong&gt; from the &lt;strong&gt;MainAccount&lt;/strong&gt;(RecId)&lt;/li&gt;
&lt;li&gt;Create a &lt;strong&gt;LedgerDimension&lt;/strong&gt; from the &lt;strong&gt;DefaultAccount&lt;/strong&gt; and &lt;strong&gt;DefaultDimension&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Create a &lt;strong&gt;DefaultDimension&lt;/strong&gt; from the Dim value(String)&lt;/li&gt;
&lt;li&gt;Merge &lt;strong&gt;DefaultDimension&lt;/strong&gt; with the &lt;strong&gt;DefaultDimension&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;SQL statement to get dimension(used for debug purposes)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/53303f00ab7b9f11ff339a77959d9b70/13e20/DEVDimensionHelperClass.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 90.28571428571429%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAIAAADUsmlHAAAACXBIWXMAAA7DAAAOwwHHb6hkAAACgUlEQVR42o1TyY7UMBTs72eRBjg0DfQgceAyjTjwBXDnwiahhpnpzuosdmw/707Cc3pADEKIUqlkR6lUvSRe7T/s9l/efHr/us/ffv38br3dbc5fPd7u1tuL9flufX6xeX7x7AVyh3y4eXnvwdO7Z0/unG3uP9quJDgG8XvuP16pfWFL5imflJ71QmNn5+dfmOZbWGlrrXODsRmX14x/6+lVkx/yA2ODMwaaVtbEgIrjFOMYR8SUOCVdaWN9CMKOlQwEpkzoY0cuL/ctbYK3Mj+K/Bi8m/+GlTLGhqiszmpBep0TUTQybyBvBaUTYzNlMyqjSYchKV3WXT+vhNLGRzDquiHIqh8oN5Trnqtu0AAjwARqQlUKidsRVS1XktmFaINuVMVMR3VnotJRqQC4mP+JFU/JQVqTDc1xKAvR1kObNVnRFkIIAAVaS+e4dcp7rbSUIIXAYbX3yQzW4ZskyhyFKCW0AC3nrRCUD1VZUkpdHP04hmmKITiEdfiO0ZNqY2/sQAUnfd8DCGul99L5wRiGWwzRWkGCBDDWpg++YDH7ZBZcNCShIKRsGmSOi7atuq6u66JrS8aKnnacY5eu6xhjqbZyYRqji7NxATH/N9CsMNkGU/CixG8MTQ2kkjWua0nAAVJYwS2XTuIfdst8qu2jq5OhbIA00KIWvKxEjQbt9ekRJhic87ZZp58Ek9FZi7pTPYYwzVrVUtVjJnKwXFhug/2z9pIcXTCNJEQSYSXehCGoLjiMOh2EE/FopNMxjb+Z8a5oceZ8yLF8JbBwlfMca2OgxIENqkRyIwYzSAc3Zvmz9oEdjuyItjJNWxWiyHhGNRWLGZUZZoNbTvXN5D8AoO33/zsTwpIAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;DEVDimensionHelperClass&quot;
        title=&quot;&quot;
        src=&quot;/static/53303f00ab7b9f11ff339a77959d9b70/8c557/DEVDimensionHelperClass.png&quot;
        srcset=&quot;/static/53303f00ab7b9f11ff339a77959d9b70/4edbd/DEVDimensionHelperClass.png 175w,
/static/53303f00ab7b9f11ff339a77959d9b70/13ae7/DEVDimensionHelperClass.png 350w,
/static/53303f00ab7b9f11ff339a77959d9b70/8c557/DEVDimensionHelperClass.png 700w,
/static/53303f00ab7b9f11ff339a77959d9b70/13e20/DEVDimensionHelperClass.png 741w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;As you see, there is no new code, all these it&apos;s just references(or small wrappers) to the standard classes. These methods will cover typical project requirements, if you need more, you can add them to this class.&lt;/p&gt;
&lt;p&gt;The idea is to use this class as a starting point for any dimension related question on the project(even before Googling something). You get some dimension related question, you check this class, if there is no answer in it, research how to do this task and update the class with the solution(either in form of new methods or just references to existing objects).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update 10/02/2020:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;To avoid always hardcode dimension names, I have made the following adjustment in the solution:&lt;/p&gt;
&lt;p&gt;Created a static constructor in &lt;strong&gt;DEVDimensionHelper&lt;/strong&gt; class that allows overriding the default dimension names(you need to uncomment this code or add your code)&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 668px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/8a5f8cfa2fb43d3dc9ee8add7cadf511/74866/StaticConstructor.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 22.285714285714285%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAYAAACOXx+WAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAwklEQVR42o2OXQ+CMAxF/f//zpAgfk38QJANHGwTus1c64wPvtnktmkfzunCTR5m9rBE0EZjtCN8DAjR8/SYI8E/eef8U4sYIrqHQtkfcNJHXMeK5xmi22PX7bBVW1RDhXqsQSwgFlCSfITxGX+B79Y/eqzlBlmdIb/lODBcdAKrNues0i6tZOgVjWnQ2hZ60lBOYZgGUCDMYUqiBLRk0hfLesngNUQvkDOsaIsP8F4y6IaLvqRPJYOkk+n2FnzjyOEF0sgw8Xi+LjMAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Static constructor&quot;
        title=&quot;&quot;
        src=&quot;/static/8a5f8cfa2fb43d3dc9ee8add7cadf511/74866/StaticConstructor.png&quot;
        srcset=&quot;/static/8a5f8cfa2fb43d3dc9ee8add7cadf511/4edbd/StaticConstructor.png 175w,
/static/8a5f8cfa2fb43d3dc9ee8add7cadf511/13ae7/StaticConstructor.png 350w,
/static/8a5f8cfa2fb43d3dc9ee8add7cadf511/74866/StaticConstructor.png 668w&quot;
        sizes=&quot;(max-width: 668px) 100vw, 668px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Created a simple table and a form(&lt;a href=&quot;https://github.com/TrudAX/XppTools/blob/master/DEVTutorial/DEVTutorial/AxForm/DEVDimNamesReference.xml&quot;&gt;DEVDimNamesReference&lt;/a&gt;) where you can setup dimension name references(this can be used for example in situations where you have CostCenter and CostCente dimensions)&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 559px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/1a3fc8fce6e0b47f4acdd108dd5d4e00/a65ce/DimSetupForm.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 37.14285714285714%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAAA7EAAAOxAGVKw4bAAABFUlEQVR42oWQUXOCMBCE+f//rg8VkLZEAomgCCQkoOJsN9TRl9Y+fLNJ5rJ3e9GhqeHdiKHvYMwAa3p0XUsdUO81dFXBjZZ3h3kK+JdEzhqYoaepXT8+YJMfHMb7PWiofUU0eYeqLJHEMT4/Mmy3KZIkRrzZ8LzlOYEQAmmaIM8FJzXr9H8RhbhHxi5EDrkLCJSygCx2KEtJLaCVWlVRzX+GEw2V0kiyHF9CIs1oWGnMnDxE93cmP65rCTv+LerTkIWlavAWS7xnCjs9oGktut7idOfYdpCS03I1+7phI+7T2gfBqKlrDqIYmd2PJwPdnrEnxl2xLDecLzdcrkEXnDqLQ+vZaGbtjAvfluWJZ5o+NO7O+Ab4ghKf9wDdkgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;DimSetupForm&quot;
        title=&quot;&quot;
        src=&quot;/static/1a3fc8fce6e0b47f4acdd108dd5d4e00/a65ce/DimSetupForm.png&quot;
        srcset=&quot;/static/1a3fc8fce6e0b47f4acdd108dd5d4e00/4edbd/DimSetupForm.png 175w,
/static/1a3fc8fce6e0b47f4acdd108dd5d4e00/13ae7/DimSetupForm.png 350w,
/static/1a3fc8fce6e0b47f4acdd108dd5d4e00/a65ce/DimSetupForm.png 559w&quot;
        sizes=&quot;(max-width: 559px) 100vw, 559px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;This form usage is optional, and even if it is used it requires zero setup - if the value in this form is not specified the default value from the class will be used.&lt;/p&gt;
&lt;h2 id=&quot;summary&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#summary&quot; aria-label=&quot;summary permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Summary&lt;/h2&gt;
&lt;p&gt;You can download this class using the following link &lt;a href=&quot;https://github.com/TrudAX/XppTools/blob/master/DEVCommon/DEVCommon/AxClass/DEVDimensionHelper.xml&quot;&gt;https://github.com/TrudAX/XppTools/blob/master/DEVCommon/DEVCommon/AxClass/DEVDimensionHelper.xml&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you know some other methods that can be added into this class feel free to create a GitHub pull request or leave a comment.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[30 additional methods to the Global class]]></title><description><![CDATA[Global class is a standard class that contains a lot of small static functions. This post describes additional functions that extend it.]]></description><link>https://denistrunin.com/xpptools-devglobal/</link><guid isPermaLink="false">https://denistrunin.com/xpptools-devglobal/</guid><pubDate>Wed, 27 Feb 2019 22:12:03 GMT</pubDate><content:encoded>&lt;p&gt;Global class is a standard class that contains a lot of small static functions. This post describes additional functions that extend it. To avoid using prefixes, all functions were added into the separate static class DEV. It exists in the &lt;a href=&quot;https://github.com/TrudAX/XppTools#devcommon-model&quot;&gt;DEVCommon&lt;/a&gt; model. As common practice, you can copy this class into your application as it is, or rename it according to your model name(e.g. ABC)&lt;/p&gt;
&lt;h2 id=&quot;dev-class-methods&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#dev-class-methods&quot; aria-label=&quot;dev class methods permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;DEV class methods&lt;/h2&gt;
&lt;h4 id=&quot;buf2buf&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#buf2buf&quot; aria-label=&quot;buf2buf permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;buf2Buf&lt;/h4&gt;
&lt;p&gt;Copies one cursor to another using field names(standard &lt;em&gt;buf2Buf&lt;/em&gt; uses IDs). So you can copy values between different tables&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;buf2Buf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Common&lt;/span&gt; _dest&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Common&lt;/span&gt; _source&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;container&lt;/span&gt; _fieldsToExclude &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;conNull&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;buf2BufMerge&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Common&lt;/span&gt; _dest&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Common&lt;/span&gt; _source&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id=&quot;canbeconverted-convertqty&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#canbeconverted-convertqty&quot; aria-label=&quot;canbeconverted convertqty permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;canBeConverted, convertQty&lt;/h4&gt;
&lt;p&gt;The same functions as &lt;em&gt;UnitofMeasureConverter::canBeConverted&lt;/em&gt; and &lt;em&gt;::convert&lt;/em&gt; but with the string parameters instead of RecIds&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; client server &lt;span class=&quot;token return-type class-name&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;canBeConverted&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;UnitOfMeasureSymbol&lt;/span&gt;     _fromUnitOfMeasure&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;UnitOfMeasureSymbol&lt;/span&gt;     _toUnitOfMeasure&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;ItemId&lt;/span&gt;                  _ItemId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id=&quot;qty&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#qty&quot; aria-label=&quot;qty permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;qty&lt;/h4&gt;
&lt;p&gt;Rounds the value according to unit settings&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;Qty&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;qty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Qty&lt;/span&gt;  _qty&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UnitOfMeasureSymbol&lt;/span&gt;  _unit&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id=&quot;cobject&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#cobject&quot; aria-label=&quot;cobject permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;cObject&lt;/h4&gt;
&lt;p&gt;Casts parameter to Object&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;Object&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;cObject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Object&lt;/span&gt;  _obj&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; _obj&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;   &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id=&quot;counttotalquick&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#counttotalquick&quot; aria-label=&quot;counttotalquick permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;countTotalQuick&lt;/h4&gt;
&lt;p&gt;Calculates the number of records in the query using Count(RecId). Standard &lt;em&gt;SysQuery::countTotal&lt;/em&gt; switches to the loop mode when the query contains more than 1 DataSource.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;Integer&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;countTotalQuick&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;QueryRun&lt;/span&gt; _queryRun&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id=&quot;copyranges&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#copyranges&quot; aria-label=&quot;copyranges permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;copyRanges&lt;/h4&gt;
&lt;p&gt;Copies DataSource ranges&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;copyRanges&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;QueryBuildDataSource&lt;/span&gt; _qbdsTarget&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;QueryBuildDataSource&lt;/span&gt; _qbdsSource&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id=&quot;datasourcerangesastext&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#datasourcerangesastext&quot; aria-label=&quot;datasourcerangesastext permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;datasourceRangesAsText&lt;/h4&gt;
&lt;p&gt;Gets a string, that contains all ranges values. Used in reports to display current filter values in the report header.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;Notes&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;datasourceRangesAsText&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;QueryBuildDataSource&lt;/span&gt; _sourceDS&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id=&quot;date2datetime-datetime2date&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#date2datetime-datetime2date&quot; aria-label=&quot;date2datetime datetime2date permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;date2DateTime, dateTime2Date&lt;/h4&gt;
&lt;p&gt;Converts date to DateTime using UserPreferredTimeZone&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;utcDateTime&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;date2DateTime&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;TransDate&lt;/span&gt; _date&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;boolean&lt;/span&gt; _isEndOfDay &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;date&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;dateTime2Date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;utcDateTime&lt;/span&gt; _dateTime&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id=&quot;systemdateget&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#systemdateget&quot; aria-label=&quot;systemdateget permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;systemdateget&lt;/h4&gt;
&lt;p&gt;Returns the current date. It is still unclear for me, why the original method was marked as obsolete&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;TransDate&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;systemdateget&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; DateTimeUtil&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getSystemDate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token named-parameter punctuation&quot;&gt;DateTimeUtil&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getUserPreferredTimeZone&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id=&quot;datestartwk-datestartyr&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#datestartwk-datestartyr&quot; aria-label=&quot;datestartwk datestartyr permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;dateStartWk, dateStartYr&lt;/h4&gt;
&lt;p&gt;Returns the start of the week, the start of the year&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;TransDate&lt;/span&gt;  &lt;span class=&quot;token function&quot;&gt;dateStartWk&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;TransDate&lt;/span&gt; _transDate&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;TransDate&lt;/span&gt;  &lt;span class=&quot;token function&quot;&gt;dateStartYr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;TransDate&lt;/span&gt; _transDate&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id=&quot;dsalloweditexceptfields&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#dsalloweditexceptfields&quot; aria-label=&quot;dsalloweditexceptfields permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;dsAllowEditExceptFields&lt;/h4&gt;
&lt;p&gt;Enable or disable all form DS fields, except specified&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;dsAllowEditExceptFields&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormDataSource&lt;/span&gt; _formDataSource&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;boolean&lt;/span&gt; _allowEdit&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;container&lt;/span&gt; _fieldListExclude&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;connull&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id=&quot;dsgetdisabledfields&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#dsgetdisabledfields&quot; aria-label=&quot;dsgetdisabledfields permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;dsGetDisabledFields&lt;/h4&gt;
&lt;p&gt;Get a list of the disabled fields. Used with the previous function when Datasource contains some code, that disables some fields, before dsAllowEditExceptFields call.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;container&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;dsGetDisabledFields&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormDataSource&lt;/span&gt; _formDataSource&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id=&quot;dsrefresh-dsresearch-dsexecutequery&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#dsrefresh-dsresearch-dsexecutequery&quot; aria-label=&quot;dsrefresh dsresearch dsexecutequery permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;dsRefresh, dsResearch, dsExecuteQuery&lt;/h4&gt;
&lt;p&gt;Performs datasource refresh/research/executeQuery&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;dsRefresh&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Common&lt;/span&gt;  _record&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;dsResearch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Common&lt;/span&gt; _record&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;NoYes&lt;/span&gt; _savePosition &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; NoYes&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;Yes&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;dsExecuteQuery&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Common&lt;/span&gt; _record&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;NoYes&lt;/span&gt; _savePosition &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; NoYes&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;Yes&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id=&quot;getformrunfromformargs&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#getformrunfromformargs&quot; aria-label=&quot;getformrunfromformargs permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;getFormRunFromFormArgs&lt;/h4&gt;
&lt;p&gt;Gets the calling form from the current form args&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;Object&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getFormRunFromFormArgs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormRun&lt;/span&gt;  _element&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IdentifierName&lt;/span&gt; _formName&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id=&quot;queryhasrecord&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#queryhasrecord&quot; aria-label=&quot;queryhasrecord permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;queryHasRecord&lt;/h4&gt;
&lt;p&gt;Checks, that the query has a record. The common usage scenario is when you need to create a custom lookup for the field. In this case, you create a query for this lookup, create the lookup based on this query and add a check into the validateWrite() method to check that the entered value(user can enter the value using the manual entry) exists in this query&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;queryHasRecord&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Query&lt;/span&gt;  _q&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id=&quot;isuserinrole&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#isuserinrole&quot; aria-label=&quot;isuserinrole permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;isUserInRole&lt;/h4&gt;
&lt;p&gt;Is the current user included into the role&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;isUserInRole&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Description&lt;/span&gt;  _roleName&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id=&quot;purchtableconfirm&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#purchtableconfirm&quot; aria-label=&quot;purchtableconfirm permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;purchTableConfirm&lt;/h4&gt;
&lt;p&gt;Confirms a purchase order&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt;  &lt;span class=&quot;token function&quot;&gt;purchTableConfirm&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;PurchTable&lt;/span&gt;  _purchTable&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id=&quot;runbuttonwithrecord&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#runbuttonwithrecord&quot; aria-label=&quot;runbuttonwithrecord permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;runButtonWithRecord&lt;/h4&gt;
&lt;p&gt;Executes menu item button with the specified record&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;runButtonWithRecord&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormFunctionButtonControl&lt;/span&gt; _button&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Common&lt;/span&gt; _record&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                                               &lt;span class=&quot;token class-name&quot;&gt;Object&lt;/span&gt; _obj &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id=&quot;validatecondition&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#validatecondition&quot; aria-label=&quot;validatecondition permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;validateCondition&lt;/h4&gt;
&lt;p&gt;Validates the specified condition&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;validateCondition&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;anytype&lt;/span&gt; _condition&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;str&lt;/span&gt; _message&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;boolean&lt;/span&gt; _isThrowError &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id=&quot;validatecursorisnotempty&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#validatecursorisnotempty&quot; aria-label=&quot;validatecursorisnotempty permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;validateCursorIsNotEmpty&lt;/h4&gt;
&lt;p&gt;Performs if (! A.RecId) {throw error(&quot;..&quot;)}&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;validateCursorIsNotEmpty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Common&lt;/span&gt;  _common&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;str&lt;/span&gt; _someText &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &apos;&apos;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id=&quot;validatecursorfield&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#validatecursorfield&quot; aria-label=&quot;validatecursorfield permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;validateCursorField&lt;/h4&gt;
&lt;p&gt;Checks that the field is not empty and generates a message&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;validateCursorField&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Common&lt;/span&gt; _table&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;fieldId&lt;/span&gt; _fieldId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;boolean&lt;/span&gt; _isThrow &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id=&quot;validatewriterecordcheck&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#validatewriterecordcheck&quot; aria-label=&quot;validatewriterecordcheck permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;validateWriteRecordCheck&lt;/h4&gt;
&lt;p&gt;Calls a validateWrite() method and generates an error if it fails&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;validateWriteRecordCheck&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Common&lt;/span&gt; _record&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id=&quot;mergeinventdim&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#mergeinventdim&quot; aria-label=&quot;mergeinventdim permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;mergeInventDim&lt;/h4&gt;
&lt;p&gt;Merges 2 inventDim values&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;InventDim&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;mergeInventDim&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;InventDimGroupSetup&lt;/span&gt;         _dimGroupSetup&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;InventDim&lt;/span&gt;                   _fromInventDim&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;InventDim&lt;/span&gt;                   _addedDim&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id=&quot;w&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#w&quot; aria-label=&quot;w permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;w&lt;/h4&gt;
&lt;p&gt;Displays the current value - info(StrFmt(&apos;%1&apos;,_i));, using mostly for debug purposes.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;w&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;anytype&lt;/span&gt; _i&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;str&lt;/span&gt; _addition &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &apos;&apos;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;summary&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#summary&quot; aria-label=&quot;summary permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Summary&lt;/h2&gt;
&lt;p&gt;You can download this class using the following link &lt;a href=&quot;https://github.com/TrudAX/XppTools/blob/master/DEVCommon/DEVCommon/AxClass/DEV.xml&quot;&gt;https://github.com/TrudAX/XppTools/blob/master/DEVCommon/DEVCommon/AxClass/DEV.xml&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you know some other helpful functions feel free to create a GitHub pull request or leave a comment.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Fields list form(if you like Table browser, you will love it)]]></title><description><![CDATA[Fields list form is an extended version of the standard Show all fields form with the additional features such as displaying all fields with the extended information, comparing and editing]]></description><link>https://denistrunin.com/xpptools-fieldslist/</link><guid isPermaLink="false">https://denistrunin.com/xpptools-fieldslist/</guid><pubDate>Wed, 13 Feb 2019 22:12:03 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://github.com/TrudAX/XppTools#-fields-list&quot;&gt;Fields list form&lt;/a&gt; is an extended version of the standard &lt;strong&gt;Show all fields&lt;/strong&gt; form with the additional features such as displaying all fields with the extended information, comparing and editing.&lt;/p&gt;
&lt;p&gt;Currently, you have the following options to directly view or edit D365FO data:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;SQL via &lt;strong&gt;SQL Management Studio&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Table browser&lt;/strong&gt; form&lt;/li&gt;
&lt;li&gt;Record info - &lt;strong&gt;Show all fields&lt;/strong&gt; form&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Typical problems when using these tools are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Table fields that have &lt;em&gt;Visible = false&lt;/em&gt; are not shown in D365 forms&lt;/li&gt;
&lt;li&gt;If the table has many columns, it is hard to find the required column&lt;/li&gt;
&lt;li&gt;D365 doesn&apos;t allow to change values for the columns that have &lt;em&gt;AllowEdit=false&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Fields list&lt;/strong&gt; form provides a convenient way to view current record data with the following options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Data is shown in the list view with Name and Label for each field(even with &lt;em&gt;Visible = false&lt;/em&gt;) that allows you to quickly find the field value&lt;/li&gt;
&lt;li&gt;Additional field information(like EDT name, Enum value, Enum name..) is displayed&lt;/li&gt;
&lt;li&gt;You can view data for the current record, even if it is not saved into the database&lt;/li&gt;
&lt;li&gt;You can compare records&lt;/li&gt;
&lt;li&gt;You can update or delete the current record with or without validation(it is not what you should use on test/prod data, but sometimes it can be useful during the development or debugging process)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;fields-list-form-usage&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#fields-list-form-usage&quot; aria-label=&quot;fields list form usage permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Fields list form usage&lt;/h2&gt;
&lt;p&gt;Open All sales orders form and go to the &lt;strong&gt;Options-Record info&lt;/strong&gt; and then press &lt;strong&gt;Fields list&lt;/strong&gt; button&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/2ab0aac9f0377f5ffb2203cea80a4eed/350de/FromRecordInfo.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 53.14285714285714%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACcUlEQVR42mWSS2tTURSFUxxYFQeCdCJqBR8D0Sr4dxxqFQedObX4QB2KbW5yk7Zp7vuZe5P0L/gHCg4stVJTyc2jSXpfeS/3PZh24IHF2YvD+dhn7ZOSZQkiz2GbW0OBW0c+vYYslwZPNZ9JI0M+/fULsrRvbeRROzqCH4Q47nbR833E/QE6nQ5arRaiKEZqfnEJF28u4cKNh5hbuIv56w+Yv7T4CJdvPcb5a/cxd/U2zi3cw5U7T7C3/xPj0QhBGCAKQ/gEHZFP1mQyQerp68949mYNy2/XSWksryY1h+er63hB/tUHHiuf8nj5PouVjzz+1JsICXRCoID2KIoYaDqdMmhqI8tBFbdhqhIsTYa4vclqx9SYSoYKTRHgWjqqjo1GwyM1/wPNVorLZCCIlKNEojyLRQGyokDTdei6AUVVIckKVFVjvl6vo015+f4Jer0egiBAv99nGo/HSPE8D0lKQEXIskwXVSgETOqZzryERqsN79iH1z7BYDBAHEcsw6RbliHHcQyYSNM0JlEUmU8gs7MZvNFso06wBkH9MKIsI4L2TweTyuVycF0HpmnS7sJxqDYM2LaNctmFZVkwDJ151y1RZ13sewEO2yEa3QiHjR7i4ZhQs6Hk89BMB4puo1Ktwi45lKkMt1whYJnlt1UoQNV08hXUa0f49f0HansHGMQxBsMh5Zc8PcaQasowh6LmoCBbUMwyRN3BpmhANlymgqgjX5AgqDadu/C8Jmo1j4bTxoSGkAwiye60wzx1aNkuDLOEnZ0qXHpykmOlUkGVOk5qQRBYjkkk3R4Ng+7Hoykm/77M7u8O3pV2IX87wF/hVL5CH0XHYgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Record information new button&quot;
        title=&quot;&quot;
        src=&quot;/static/2ab0aac9f0377f5ffb2203cea80a4eed/8c557/FromRecordInfo.png&quot;
        srcset=&quot;/static/2ab0aac9f0377f5ffb2203cea80a4eed/4edbd/FromRecordInfo.png 175w,
/static/2ab0aac9f0377f5ffb2203cea80a4eed/13ae7/FromRecordInfo.png 350w,
/static/2ab0aac9f0377f5ffb2203cea80a4eed/8c557/FromRecordInfo.png 700w,
/static/2ab0aac9f0377f5ffb2203cea80a4eed/350de/FromRecordInfo.png 998w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Fields list form will show the current data for the selected sales order&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/04304e0317a8925a9ca314e1a912650b/f941f/EnumView.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 88.57142857142857%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAYAAABb0P4QAAAACXBIWXMAAA7EAAAOxAGVKw4bAAADVklEQVR42o1TaW8URxAdKaBEAhwIArI2xoYvEQgJJMjPAQkQIOCnQBLARgn3r8D2ru1FFgb8DSzAXsfee3eOnmPn2FmPZ3b2paq9NgaBlJaeqru66nV1HcrbhQXMv8zj1cQLzM/M4NXsNOayWWSnc5iYnEQ2m8MknRlTtJ+YmkIul8P0bJ4wixz5zObzUvJZOXjoMIZHRnBkcAiHfx3E7h9/ws+/HMTwsVFkSDd0dAgjo6M4OnwMe/buww+7dmPvvgEcyWSQyQxiYGAAh4hj/4EDdL8Hytnr93Hm+hjO3xjH+ZvjOHn5LynP3XyA09fu4dyNMZy+eg+/3xoH25689CfZjuHUlbv47fJdHL9wBycu/iFx/MJtKE9eqxifKeJBvoS/X1ZIlum8in/mqnj61iDoePxak/IZ4ckbHc8XDKl7NK/iEcmHfclQmqqOwsoqVlbXsLS8ImW13oSqGdB0AZUgTBuGafVhQxebUnwDiqap+LC4iMX37/Dp40eUyyWsFJZRLK6hsLyEUrEEIQwYht7Hzr3+ld6AYpomGo0GyqUynFYLruvCcRy5d1oOLMuCbdto8Zn0vP98/xVIr7BDFEXwPJfgI04S9Ho9pGmKbjeRRJ7nIY5j8ArbIYJ2GynZdLvdbbA9L4VZWeG2+HULntuCT1EmREzM8H2PoiYdPRgQcSdsww98bGxs4FtLqakC7ysWKnUNdc2Cv54g6CQIN1K0owSVpo6aZpIuhk/QbR91g1LhdeAEkZS2H2E97kf4qdTE87k1FJsCNSuA5kZo2CEMP5YoNk3USW+FKcx2FyXDR6FuoVAVWFNdLFUM/NtsodXpfv5yksQwTQHTEvRlVyLp59KhIrQpZ5wWXlvye0sSxkTIpdd0HQ7la6sATCgM6kVVpR6jbwdteuh/ECaymtQKtkOO1jZhmnapKD4VxUMYhvKBaH1d6rgzvh8hEViWKRu4Qw69XrpNyH1nW7aUTMLtwRXmlOxsly8jpC9b9CVBeWTHkFpDEpKD42w2Mk9B1CfiVup0OggoUs7vF4RC0KyKfp7ISac8qpomJ8QUJpqslzaGlDJigkdk/HVu+p1Q+OVatSongg2CIJBkPMu1Wk1O0Kbel9WvVCqoN+oyyi0SHtetYP4DWJ/waGGkXDQAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;EnumView&quot;
        title=&quot;&quot;
        src=&quot;/static/04304e0317a8925a9ca314e1a912650b/8c557/EnumView.png&quot;
        srcset=&quot;/static/04304e0317a8925a9ca314e1a912650b/4edbd/EnumView.png 175w,
/static/04304e0317a8925a9ca314e1a912650b/13ae7/EnumView.png 350w,
/static/04304e0317a8925a9ca314e1a912650b/8c557/EnumView.png 700w,
/static/04304e0317a8925a9ca314e1a912650b/f941f/EnumView.png 736w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Another way to run this form is to Right click on the form field, press &lt;strong&gt;Form information&lt;/strong&gt; and then &lt;strong&gt;Field list&lt;/strong&gt; button. This action doesn&apos;t save the current form cursor, so you can view the uncommitted data.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 358px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/3b99a77cdfd220954d201a805da123a8/39185/FormInformationCall.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 132%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAaCAYAAAC3g3x9AAAACXBIWXMAAAsTAAALEwEAmpwYAAACiklEQVR42qVVy27aUBD1D/Qr+ild9we67Af0V7qossgm3XVfqeqiapqKBAmEUCQgjoN5g40xLhi/r1+ndy4xhVYoprnS0WDjOXfunJm5kmEYaDQaaLfb6Ha7qNVqqNfraLVaaDabqFarkGUZcRzjqZXnOSTP8wRRr9fDbDaDqqoC9KwoisBgMChFSEs63AHPXpwwR5ykCKIEts/gRzGyLPsHecndRIQsyeBFKYxNBCdMSjsfJYyiEJ7nwudwNhsEQYANt4QkSUqTCVHoh+f5O2dSnURyXVcQp2l6eoSktOM44oVpmuh0OmI3yl3ZRcHYtn2ocpH8U3JYfOv7vjiZdMy5IC6DgrDf70OiUKmgp9OpgKZpmEwmXKjoIIJji3JM31K+BSE5UA5pB7IEEqSsGEWuyZ+6SypeUqREUoBajTFWumzIh0gFIZUMhTsajcSxh8Oh6GFV7YnjpyTWKWVD0QScnfJAu8Qx+68u2RW2uXYwmOgYawv0xxq0hQXL9rBcuzBXjsDaDctHqFk2blsdtGVF2DulC/lB3T0ThvqylOqCMIwTPhRiuBwehxMwAZfw+Byw5IThEIaw12s+GGysflmIGXvetCEhSE3CeDwWlgp8xkH9Sf9HJTfZqUxThjCfzwUpWV3XxdAI+QlOugKogAunvzsk30f+9DWxFYWTWZaFNc8jFfmpE+foJbUfFS3VcFFRTFS7S1Tut/aGY+UxfqoMIUv59ZGLKyTkVwiLsz+E++MozbaUbz9UIb06x4s3n/Dy3WdIrz9yXOBLU4fJU1pXF7jujFDv6pAXDIvgWISPIV7dGXj/9R7nlyoufvZx9u0BZ997vJtMGNUahlc3GFxWhB39uMayLeM3mnHaeBEssH4AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;1549427927132&quot;
        title=&quot;&quot;
        src=&quot;/static/3b99a77cdfd220954d201a805da123a8/39185/FormInformationCall.png&quot;
        srcset=&quot;/static/3b99a77cdfd220954d201a805da123a8/4edbd/FormInformationCall.png 175w,
/static/3b99a77cdfd220954d201a805da123a8/13ae7/FormInformationCall.png 350w,
/static/3b99a77cdfd220954d201a805da123a8/39185/FormInformationCall.png 358w&quot;
        sizes=&quot;(max-width: 358px) 100vw, 358px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h3 id=&quot;edit-feature&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#edit-feature&quot; aria-label=&quot;edit feature permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Edit feature&lt;/h3&gt;
&lt;p&gt;You can edit a field value or delete the current record. To change a field value press the &lt;strong&gt;Change value&lt;/strong&gt; button.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 614px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/a93e05d683722181776918d4d332b5a4/e9131/ChangeValueDialog.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 51.42857142857144%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAuUlEQVR42q1RXQvDIBDz///BscH2sI8WK1adrbZqzabQ0gc3RrtAEI4zl8sRKSU455lKKTRNg2EYsAUxRhDnHMZxhDFmeUMI2ArS9z26rsuMXybPXNfWSCayQ+99dua9wx7MA0laUWuNe1XD2HJ2bduCUpr7rLULiysnd9MUcH3U4PJZbBJCgDGWRVNESSxFVBTEn0E+hbxb8Pfw3xed4sLNgvNXrh2OlcbhJnBhBlQ5nGuFUyXBuoAXg+QVwaiYWkEAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;1549428273252&quot;
        title=&quot;&quot;
        src=&quot;/static/a93e05d683722181776918d4d332b5a4/e9131/ChangeValueDialog.png&quot;
        srcset=&quot;/static/a93e05d683722181776918d4d332b5a4/4edbd/ChangeValueDialog.png 175w,
/static/a93e05d683722181776918d4d332b5a4/13ae7/ChangeValueDialog.png 350w,
/static/a93e05d683722181776918d4d332b5a4/e9131/ChangeValueDialog.png 614w&quot;
        sizes=&quot;(max-width: 614px) 100vw, 614px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;If you check &lt;strong&gt;Ignore update&lt;/strong&gt; parameter, an update will be performed using doUpdate() method. &lt;strong&gt;Delete&lt;/strong&gt; provides the same option. Do not use editing feature on test/prod data, you can easily corrupt the data.&lt;/p&gt;
&lt;h2 id=&quot;compare-feature&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#compare-feature&quot; aria-label=&quot;compare feature permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Compare feature&lt;/h2&gt;
&lt;p&gt;You can compare different records. For example, we can compare 2 sales order lines.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/3977a7b983644fe056d63540118ede5b/01ccc/SalesLines2.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 14.285714285714285%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAADCAYAAACTWi8uAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAiklEQVR42nVMWw6DMAzj/scEjW3QCvpIk7ZQL3RC+1oky484GVgEZ2s4zi/Om9vP/9srdd9U3zPExAiUkOsBFyIicdecC5JksCLEBCkVPlL3180Fr31SFs1KrSD9MywbYbYBG1VMb4vxZbHFAhsE1guMYzxW1/VsHIxn3WWse8Kk3UX5ytadMD4NPp6O6PGdYwp8AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;SalesLines2&quot;
        title=&quot;&quot;
        src=&quot;/static/3977a7b983644fe056d63540118ede5b/8c557/SalesLines2.png&quot;
        srcset=&quot;/static/3977a7b983644fe056d63540118ede5b/4edbd/SalesLines2.png 175w,
/static/3977a7b983644fe056d63540118ede5b/13ae7/SalesLines2.png 350w,
/static/3977a7b983644fe056d63540118ede5b/8c557/SalesLines2.png 700w,
/static/3977a7b983644fe056d63540118ede5b/e996b/SalesLines2.png 1050w,
/static/3977a7b983644fe056d63540118ede5b/01ccc/SalesLines2.png 1399w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Select the first line and press &lt;strong&gt;Options - Record info - Fields list&lt;/strong&gt; button. Then, expand the Compare group and Save the first line&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/a47892256a5e440e1e350d57a7273429/1628f/SaveSalesLine1.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 50.28571428571429%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABuElEQVR42o2RzU7bQBSFYRUqCmy6KZFKEBIgBGXHA/AibEKANQ8Q8dcdOxCIOLGZOHj8b+JEUd4H8S8KizjI2DnMnUqIglqwdHTvjGe+OWembzj3E8O5OWS+T+Hrj1kMjc1iZHwemdEpDGSnMSjmvmRn0P9tApMLi7i8ukYcx+h0OlJpmuL115cv7iNf3ENh4wCFrUOs7pSwsl3C2i8FazsKlreOkN88wlLxAOu7DL/vH5A8xUiSBKlQr9f7G6gqJVSEdHYMpqngJzoci8PiBizTgGObQjQ+QTMMcHZxh9uHR5CvOOkhfQsslytQFAWMVaHrOrRjDZqmyV6v1VAuqaioVaiqCsuycH11J6LGEvQkgO8ccs5BosUk27Zl5aYJ13Hg6jU43IQt+rBeRxRFcuNb0AvQ8zw0m024orIqkxsbjQYMg0v4aRjKA2hdq9X6PNDzXNRERMd1UBdOuPnHdRAEMoFhGOKgEN1u92MgOaJKQC7ihcKVKSJT7/uB/E+HtNvt/wJp7lVkF4Z4WRrTZnJHUN/3pcgpAaOPHJIruiuKRK9Llcb0yoyxFzDNE/hfdxg9xjg/v8Ezov+JUsJC2G4AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;SaveSalesLine1&quot;
        title=&quot;&quot;
        src=&quot;/static/a47892256a5e440e1e350d57a7273429/8c557/SaveSalesLine1.png&quot;
        srcset=&quot;/static/a47892256a5e440e1e350d57a7273429/4edbd/SaveSalesLine1.png 175w,
/static/a47892256a5e440e1e350d57a7273429/13ae7/SaveSalesLine1.png 350w,
/static/a47892256a5e440e1e350d57a7273429/8c557/SaveSalesLine1.png 700w,
/static/a47892256a5e440e1e350d57a7273429/e996b/SaveSalesLine1.png 1050w,
/static/a47892256a5e440e1e350d57a7273429/1628f/SaveSalesLine1.png 1232w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Close this form, return to Sales order and select the second line. Run &lt;strong&gt;Fields list&lt;/strong&gt; form again. Then you can compare previously saved Line1 and the Current record(sort by the &lt;strong&gt;Different&lt;/strong&gt; column to see all differences)&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/a745365bb28c330b84140528d782dd9f/75609/CompareLine2.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 43.99999999999999%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB6UlEQVR42n2RWW/TUBCF/TsRD0gU1B8EPBAoVA1pQ6m7PPDQQkvbbIUWnCZxFtuxk3i5S+zYrpAQBA7jWyTEC5Y+nZm5M8dzdbV7Tz5gpVTD6vMGHpQaWF1rktYVK8TDZxQT95/WcPfxGe48Ov0vmmVZMAwDrjeB67qwbYfUA+McjHGlnAuCQwpB8H+RAkL8RQsDH45t0zBTRFGEIAhuDaSE+DMQcQmfzRGJWGlIGvC5ihmdczIv0Bi7NUjTFDdZiq95hjln4FQrNE8XuCGkTOBHEvEiJ/MY8yQDp1pAtXSxQJbECi0ng4yMlj++w6MGM5Sw5xksYkiDvUCo3IlzDEIBSyRwkpxy6qF+VZMpbDov0Dwy8HyG5fIXDnsuXtY72DN9HIwY9N4Umx/70LszHAwjVC+H2Ol4Kt4n9O4EW1cj7PUD7A9ChXZsjPFpMEP+7SdOzSnetj2ckNl7Oiw46no4dwRasxQnAx9nowgNL0ZrukDN4Tjuz1AfSzQniYKunCNJEgC0oTlG6dzAi/o1yvTnrbaD9WYHG7Tlq88jUhNl2vI1bV5QvXax3uqhYjjYNmeqphWPEdLLFt+7voe1Bhlc9LBN19mhhjKZbFyY2PxioXI5QOVqCJ2uqNP2bzoT1Vttj7FLeVH/DclXc8e2JOlhAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;CompareLine2&quot;
        title=&quot;&quot;
        src=&quot;/static/a745365bb28c330b84140528d782dd9f/8c557/CompareLine2.png&quot;
        srcset=&quot;/static/a745365bb28c330b84140528d782dd9f/4edbd/CompareLine2.png 175w,
/static/a745365bb28c330b84140528d782dd9f/13ae7/CompareLine2.png 350w,
/static/a745365bb28c330b84140528d782dd9f/8c557/CompareLine2.png 700w,
/static/a745365bb28c330b84140528d782dd9f/75609/CompareLine2.png 994w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;summary&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#summary&quot; aria-label=&quot;summary permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Summary&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Fields list&lt;/strong&gt; tool in some cases can simplify and increase the development speed. You can download it using the following link - &lt;a href=&quot;https://github.com/TrudAX/XppTools#installation&quot;&gt;https://github.com/TrudAX/XppTools#installation&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Feel free to post any comments(better as a GitHub issue) or ideas, what else can be improved.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Blocking in D365FO(and why you shouldn't always follow MS recommendations)]]></title><description><![CDATA[Understanding blocking is a key component of resolving performance issues. You can have fast CPU, a lot of memory, but if you face SQL blocking problem all these will not be fully utilized]]></description><link>https://denistrunin.com/understanding-sql-blocking/</link><guid isPermaLink="false">https://denistrunin.com/understanding-sql-blocking/</guid><pubDate>Wed, 30 Jan 2019 20:12:03 GMT</pubDate><content:encoded>&lt;p&gt;Understanding blocking is a key component of resolving performance issues. You can have fast CPU, a lot of memory, but if you face SQL blocking problem, all these will not be fully utilized. Moreover, some tips from the Performance webcasts can actually lead to blocking. In this post, I am going to describe the most common reasons for blocking and how to avoid them.&lt;/p&gt;
&lt;h2 id=&quot;history&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#history&quot; aria-label=&quot;history permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;History&lt;/h2&gt;
&lt;p&gt;SQL Server engine doesn&apos;t support &quot;true&quot; row-level blocking, and this was a big problem in the days of Axapta 3.0. But starting from AX 4.0 and SQL Server 2005 the situation has changed. SQL Server 2005 introduced  &lt;em&gt;Read Committed Snapshot Isolation&lt;/em&gt; feature, and in AX 4.0 &quot;Occ enabled&quot; table property was added. Both these components significantly reduced the chance of blocking.&lt;/p&gt;
&lt;p&gt;For more information check this article&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://cloudblogs.microsoft.com/dynamics365/no-audience/2009/07/08/about-locking-and-blocking-in-dynamics-ax-and-how-to-prevent-it/&quot;&gt;https://cloudblogs.microsoft.com/dynamics365/no-audience/2009/07/08/about-locking-and-blocking-in-dynamics-ax-and-how-to-prevent-it/&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;test-example&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#test-example&quot; aria-label=&quot;test example permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Test example&lt;/h2&gt;
&lt;p&gt;Let&apos;s test the common blocking scenario. We will use the following table &lt;strong&gt;DEVBlockingTestTable&lt;/strong&gt; , that has 4 fields, Field1 is a unique Alternate Key, Field2 is included into a non-unique index.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 250px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/74eb946ea28b52c4c5bd22988e08583a/63868/TestTableAOT.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 128.57142857142856%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAaCAYAAAC3g3x9AAAACXBIWXMAAAsTAAALEwEAmpwYAAADeUlEQVR42q1VS4/bVBj1T6Gq2LNCqsSGJUiwKD+oUpG6YIOARSW6YAXi0SI27VTlJTEDmSSTaR52/H7bydiJnaTJxBnb8eG7NyQaJDQkiCsd+XXv8ffd833nCqvVCk+efA9TV9Hv99GsNRCEPlRZ5RC7PfR6ImSRQM+u7cL3XWiyjna7A5XWdNpthIMIbAhXV1cYDodwHQeGbsBQdZiGicAPMAhCXFwMEccjjOIIEb/GSNIxxqOEv58kKdIkwWw23xDOZjMw2LYNx7IxCEO0zpoYjRM+oaoqHDKE64tY+s1GA47tQFUU2gYDRVHuiHe49sy/8ed/IFwul2gQoe/7lL4OmyIuy/V/jzDLMtTrdfieB13VoFCURVn+D4TuhlDX9F3KBxFuR5at0Kg34DkukWnoS32srvLDCNfr9S7CNE15hKyMWOkYunl4yjHVU7bKIfUVnJ214HkBxF6fq6woGlqtNlKqMfbLoqzANLoJwmp5CYZpEiEOXUzjIUJLRmApyLMZqnxBm7y/0sLjziW+eznHV40Ej3718cPvFh4+1/H5Tw6OtBy/2MCRDjwjPCW8UEv8qBZ4rq3xQtveV/w7g/D6ZwDDW18Adx7luPdtD+9+mePuY+D9ryvc/QZ44yFw6+MKr30KvPlRivfum3jnQxdvPwjxwT2Z3k1wi77d/qSCoCcVDIKZAua4wHRZ4qgm47euh+Ouj5+bOl7aM1hTgM9NN7DSNV3B127egWNXNusy52pntJ+eY2EcDRD5DmxNQXa5vNbXN/e2sJ3C2o21XpusaDgYQhIldM/bpLSK+SLb/HTbxzfgb4XNapINSZIoSoqOTELs9TBO9ncegbUbIxoMBjzKxas590V2zyJVKcIoinlb7kXIuiPPc4jkyLVaDT75om06ME0TtmGRS2vckVXq7XL97/XIDZa59mg0osUydFmBpMjQNAMhme36UIOdTqc85frpKZqE0HPR7fS4F7qui5jSnaSTvV2HE+Y02aHykOt/IAgCtM+7MAyDDqsAUk+i9A0sV/lfwuxByKw/iiI6mHxoJIJGoshdEYqqwCKyTkdEPIr3UpoTFkVBizoU2TkJYlDt6fAdJoyFCX1fzBfki6v9Ut6KMry4gEKieK6DZr3FiUUq7sns1UGnHy8bFuHJyQlOjo9hklM3Ts+4H+q0j7sTbk+V/wQ0J6izdOv7MAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;1548397937555&quot;
        title=&quot;&quot;
        src=&quot;/static/74eb946ea28b52c4c5bd22988e08583a/63868/TestTableAOT.png&quot;
        srcset=&quot;/static/74eb946ea28b52c4c5bd22988e08583a/4edbd/TestTableAOT.png 175w,
/static/74eb946ea28b52c4c5bd22988e08583a/63868/TestTableAOT.png 250w&quot;
        sizes=&quot;(max-width: 250px) 100vw, 250px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;We create a form DEVBlockingTest with a set of actions. Initial data will be the following&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 626px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/923faf45ff43bf14f0337dd95f3b94b2/af590/TestTable.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 96%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAACXBIWXMAAAsTAAALEwEAmpwYAAACiElEQVR42p1TyW7bMBBVDOeW3ho0duMk/dUC/ZmiZ8uGE+cLeui1h8ISvCrRvlCiKL/OjKUETbMUJfCgN+RwOMuTNRgOcXF5ieFwgOHHId6dnKB/fIyzswFGowsMzj7gfHSOq6tLwiecnr5Hv9+HZVno9Xo4OjoS9NqvZds25re3uL6+FrA9Ho8xn89hTyaY0d5sNhPOZ5PJFFPiN/MbjO2x2LZ9OJtOp7CSJEEcx4iiCHmeC3hPKYUsy1DQt+NJmiBLM/FRpRK/lGw5I55lOazlconFYiFYrVbYbDaCdft1HFfO1us1NgTXdbBwHPJdY7fbYbvdCjpuBUGAMAzppVRe5tf4WxQFfDpjhJQ9V+B5nviGIdkEDvIUDwG5bA7C6IIeyqCyi0PJYdsWbgEnwHefwuJg7MS9qGsDrbVkw4GbppGLDOZlWUpm7GOMwX6//wsWO9d1LRd4GVOLsyxyqGuN1hD7gaPjfy7L86kfuYKhgOxS6RplpYXzI6qkbMhoWpjmkT8b8Mu37/j89Qd8P4WzzfBrGWK13OHe8+Ft7/Bz4cGlfXebwt0kcO8KOIHGMqSHnolqeUGMJM6hqW8N6UjHpMEgQhUlBBqUH8BQfwVJCkN95Fqa/QslpzQ9U1aoaco0PgqaoaEhMWdo2t/TgMDgfa3x2rJYDqpSCHOSRF0gKVMCyUVnglgxzwUp2ZWpXg+YU5l5mcNL7xDrBIEKBVEVC/zikYdlBGXU2xkWZYH71JcMIhULkioVhEX0wGPKXJny7YCapUI/O0kTNemQ0ewbgiEJlS0/YP/CMB6HQsJmIbO40WqvEzkLWb8xhGczrCnDqjo0uyHlMv47YJdhd/Fphl3m/xrwN4gQgVZZZZn5AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;1548397644658&quot;
        title=&quot;&quot;
        src=&quot;/static/923faf45ff43bf14f0337dd95f3b94b2/af590/TestTable.png&quot;
        srcset=&quot;/static/923faf45ff43bf14f0337dd95f3b94b2/4edbd/TestTable.png 175w,
/static/923faf45ff43bf14f0337dd95f3b94b2/13ae7/TestTable.png 350w,
/static/923faf45ff43bf14f0337dd95f3b94b2/af590/TestTable.png 626w&quot;
        sizes=&quot;(max-width: 626px) 100vw, 626px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;We need to run 2 sessions(for OneBox VMs using the following link
&lt;a href=&quot;https://usnconeboxax1aos.cloud.onebox.dynamics.com/?f=DEVBlockingTest&quot;&gt;https://usnconeboxax1aos.cloud.onebox.dynamics.com/?f=DEVBlockingTest&lt;/a&gt; ) to test whether we have blocking or not. The first session will update the rows marked in red, second session - marked in green.&lt;/p&gt;
&lt;h3 id=&quot;test-1---select-forupdate&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#test-1---select-forupdate&quot; aria-label=&quot;test 1   select forupdate permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Test 1 - select forupdate&lt;/h3&gt;
&lt;p&gt;The first test is using &lt;strong&gt;select forupdate&lt;/strong&gt; statement&lt;/p&gt;
&lt;p&gt;For the first session enter Row number 1 = &quot;1&quot; and Row number 2 = &quot;0&quot; and press &quot;select forupdate&quot; button. For the second session enter &quot;1&quot; and &quot;1&quot; and press the same button&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;ttsbegin&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;select&lt;/span&gt; forupdate blockingTableLocal
    &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;blockingTableLocal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Field2 &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; updateRow1 &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;
          blockingTableLocal&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Field3 &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; updateRow2
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    blockingTableLocal&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Field4 &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;u1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    blockingTableLocal&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
Box&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;okCancel&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Select forupdate has been done&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token named-parameter punctuation&quot;&gt;DialogButton&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;Ok&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
ttsabort&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Results:&lt;/strong&gt; both sessions will show an OK message. Actually, it doesn&apos;t matter, what fields or conditions we are using in the &lt;strong&gt;forupdate&lt;/strong&gt; statement, sessions will not block each other in any case. Even in the worst case scenario, when 2 sessions will update the same row, blocking doesn&apos;t happen, instead, the &lt;strong&gt;UpdateConflict&lt;/strong&gt; exception will be generated(this is the drawback of &quot;Occ enabled&quot; property, it doesn&apos;t fit for tables where concurrent updates are normal, like InventSum)&lt;/p&gt;
&lt;h3 id=&quot;common-mistakes&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#common-mistakes&quot; aria-label=&quot;common mistakes permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Common mistakes&lt;/h3&gt;
&lt;p&gt;Blocking is sometimes not taken into account when discussing performance best practices. One of the recent examples can be found in the &lt;strong&gt;&quot;Performance Patterns and Anti-patterns&quot;&lt;/strong&gt; webcast, that can be found at this link: &lt;a href=&quot;https://infopedia.eventbuilder.com/index?landingpageid=92tzhl&quot;&gt;https://infopedia.eventbuilder.com/index?landingpageid=92tzhl&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/a4a59ef9a627b7274d46a56a1b6345fb/79e48/InfopediaMain.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 43.42857142857143%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAAsTAAALEwEAmpwYAAABvklEQVR42k2S3YvUMBTF5/8H0QcXYUEQBH3wL1DWD0RlZMEXX1zdddqZ2S3ttE3StPlokh7vzRa1cDhpSU9+995snPMYpwmntiO1qJsGzemU1fc9hJDouh4tr6WCsQ6TsdCTyT6SJmMg1YBqEtiEMCOmBSEm+BDRDR699uQue0uuJg/jAgal0NKhQgowiKL3iWCefTrgwevfeHxRYAMs8HNCLSwa6aBtyBpX8TqmRLsWGCLRWtP+GcuyINH3RDDfjxqfr3tsb4gwxpjpmIDFVEIzpYMYiZR8MDOsj0Qk0XddJpsplMOttXi5vcPZuxLnH/YrYUholEWriNCEHKBXqWnOB/Lzl9D7TBxCyJQ/Ko3LncS3UnEPqaT/CO9753CicO4fU7o5gg+WUqKlYUki5aBhJXz+5RYP3+xw9rZYSybCgUg0Nb8RhsJsdpagcB4WP0IINHQLJJdMw+SBeOfwYnuLRzmwXAkXwNE/ltSbiN4mdOyGDvI0jABw0XyN6romUkVlzxjHtYdfq389TEvC2Anc3ZSoiyOKnyUO13vsf907a3dVoD1WUJKH0qOjq8N9ZDoezqvLCk/el3j68YA/RpGqFW3vn7wAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;1548400337887&quot;
        title=&quot;&quot;
        src=&quot;/static/a4a59ef9a627b7274d46a56a1b6345fb/8c557/InfopediaMain.png&quot;
        srcset=&quot;/static/a4a59ef9a627b7274d46a56a1b6345fb/4edbd/InfopediaMain.png 175w,
/static/a4a59ef9a627b7274d46a56a1b6345fb/13ae7/InfopediaMain.png 350w,
/static/a4a59ef9a627b7274d46a56a1b6345fb/8c557/InfopediaMain.png 700w,
/static/a4a59ef9a627b7274d46a56a1b6345fb/79e48/InfopediaMain.png 865w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;In this webcast, you can find the following advice(on the 17th minute)&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/33dc80f7a6ef372479c41a0d00c2675e/350de/InfopediaAdvice.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 45.714285714285715%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAAsTAAALEwEAmpwYAAAByElEQVR42m1SS4+bMBjk//+WSrtSu9qo1SYlm/CyjcEYbAgBQrtRe+klx7CdfrZKTz2M/Jjx9xoH96HDYjV+dQa6PaG2FrnI0TQGbdtCaw3j9sbC1gZWGyhZQCmF2+2G9/ffWO4L7oRlWRD8LCWun5/xtnvBj80nXL9sMIwXDOcRQz/gTJjHGXrq8VQe8Sj32GqG6Tyh/8uv6E9nBEZVyPavEFGMnCCiCJwLMMYh8wKC515o2w574qIsRZxlYBknXU4r+6czjUUwDhOkKJCl3F/WVQNLhG1aarP1otOpxzzNqKQCTzjyTKAqKs+vOvemtR0FHCdkVYlUFzhUuUdpDFitkGiJota+wsv8DVyX/s5pmCa+LsANdUhaRW868iDoxwGb/RYfaXZf0wihSJByTkMnMyxVSNn77oyJAm7jAx6fnxA6HUvACwkhKGmpyLwaDRkWuFYklwi3IaJDBBZn2L3skLvZdT0sBTzR+vb9CpYwPHx4wH4X0j5DfIiRxCmqsiJoNPQLgokcdY8UZTlSwEKW/uzKdzNxe98yJa51Q7rKf6mOkjjeJXPwetfyZbqAM4HD65H+n/QmuCBOvAb0plDLa7Ur9z/8AW5Tcq0gVy8uAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;1548400892774&quot;
        title=&quot;&quot;
        src=&quot;/static/33dc80f7a6ef372479c41a0d00c2675e/8c557/InfopediaAdvice.png&quot;
        srcset=&quot;/static/33dc80f7a6ef372479c41a0d00c2675e/4edbd/InfopediaAdvice.png 175w,
/static/33dc80f7a6ef372479c41a0d00c2675e/13ae7/InfopediaAdvice.png 350w,
/static/33dc80f7a6ef372479c41a0d00c2675e/8c557/InfopediaAdvice.png 700w,
/static/33dc80f7a6ef372479c41a0d00c2675e/350de/InfopediaAdvice.png 998w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;What happens if we use this advice and switch to set-based command?&lt;/p&gt;
&lt;h3 id=&quot;test-2---update_recordset&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#test-2---update_recordset&quot; aria-label=&quot;test 2   update_recordset permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Test 2 - update_recordset&lt;/h3&gt;
&lt;p&gt;let&apos;s test this. The same example, 2 sessions, updating a different set of records, but using the &lt;strong&gt;update_recordset&lt;/strong&gt; statement:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;ttsbegin&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

update_recordset blockingTableLocal
    &lt;span class=&quot;token class-name&quot;&gt;setting&lt;/span&gt; Field4 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;u1&quot;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;blockingTableLocal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Field2 &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; updateRow1
     &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;   blockingTableLocal&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Field3 &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; updateRow2&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

Box&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;okCancel&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;strFmt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;update_recordset has been done. Rows: %1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; blockingTableLocal&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;RowCount&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token named-parameter punctuation&quot;&gt;DialogButton&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;Ok&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

ttsabort&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When we run the second session, we will see &quot;Please wait..&quot; message. So we just switched our system to &quot;single user mode&quot; using the best practice advice.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 685px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/cec40dbe1b2e316921a2423630e9c256/8ce22/TestTableBlocking.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 37.14285714285714%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAAAsTAAALEwEAmpwYAAABBUlEQVR42pWQ224DIQxE9/+/MlJVwFwN7CXpbjK13adIeSnS0Q5jmDVeiAJqrUg5I6WE4ANCIORS4L23b+sT3AdqY1TuppU+Joaw7nc5M0QPLM453G43Q3UI4Q3nPFIb8sMKFyI8JSPEDMrF4LmbF2PEol2llFGkE2Z+gyJZKMVknZJcUGptyPKiGJO9iogszAJLkTAp9s44jh3HvmHfVoO5YVtVb2itYvRu9Tm7hXxi0dkVHkLHlFmMuSEVxnY8bB9Lwypa56S+ervsX6/XR5Ygs/mqBzw/QOOEE+3qHWFe+BZPa6p9/4HXukDzlMv4uJbWGq7rwvP5NEP1df1p9c7zxH/WL/43F6gbFphpAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;1548401791918&quot;
        title=&quot;&quot;
        src=&quot;/static/cec40dbe1b2e316921a2423630e9c256/8ce22/TestTableBlocking.png&quot;
        srcset=&quot;/static/cec40dbe1b2e316921a2423630e9c256/4edbd/TestTableBlocking.png 175w,
/static/cec40dbe1b2e316921a2423630e9c256/13ae7/TestTableBlocking.png 350w,
/static/cec40dbe1b2e316921a2423630e9c256/8ce22/TestTableBlocking.png 685w&quot;
        sizes=&quot;(max-width: 685px) 100vw, 685px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h3 id=&quot;ways-to-resolve-this-blocking&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#ways-to-resolve-this-blocking&quot; aria-label=&quot;ways to resolve this blocking permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Ways to resolve this blocking&lt;/h3&gt;
&lt;p&gt;The best advice based on practical experience - try to avoid set-based operation where possible(this is exactly the opposite of what is recommended in this Microsoft webcast). On the next slide, they show the time of these operations. Update 1000 records one by one takes 300ms versus 6ms in the &lt;strong&gt;update_recordset&lt;/strong&gt; case.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/e61d93d7b69e85353fab0c1bbbedf18b/1c3a5/InfopediaResult.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 33.142857142857146%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAAAsTAAALEwEAmpwYAAABkklEQVR42j2RbW/aUAyF8/9/zrqq/VC0MloqjZYATUiam/cLhLLAgCQksMEzN9Vm6ciSz/GxZRvYY87TCUopHBVgTx0mkwm+7+O6LpZltZx681Cuh2s7ONaUkTlina/5iMvlwr8w8n6PtfnC7GVA+v0byjTxxDhQPspTeIIkSnBCRd8e0p0MeLCGLZckKctsSbbI/sMIOneET32SXpfVfYdMtprNl+hUM9Nz0mRGGqdYgce9mN2OHulaskAqdTFM4qTldaLbwYYbxMR6gV6u2JQV1aGhKCoOkuv6SFkePs2lIfYjMp2Rv+fsdnuq6tDyH7qmObV9RhxG1MUO/hz5XTc0lZjutxwPJeeTmJb7dnos0+da00j9ItpTLUZlIdpf0lNIe82h2GLYSvPoV/T8ho79ytXA5Nrc8OU543qU8/V5gRekpFGEHf0UXc1DeKbjJNyMI24mO66GK26tgrvXtWwo0x0vwo/mrLc7tBx2ttwwf9+wzHcsJIdh/PkYR/H0Y8TYkmfJqSxXCYIWjkp48xP+ApMM/QHUc+jwAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;1548401557126&quot;
        title=&quot;&quot;
        src=&quot;/static/e61d93d7b69e85353fab0c1bbbedf18b/8c557/InfopediaResult.png&quot;
        srcset=&quot;/static/e61d93d7b69e85353fab0c1bbbedf18b/4edbd/InfopediaResult.png 175w,
/static/e61d93d7b69e85353fab0c1bbbedf18b/13ae7/InfopediaResult.png 350w,
/static/e61d93d7b69e85353fab0c1bbbedf18b/8c557/InfopediaResult.png 700w,
/static/e61d93d7b69e85353fab0c1bbbedf18b/1c3a5/InfopediaResult.png 981w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;But in any case it is fast. Time to post a typical AX document with 1000 lines can be from 1 to 10 minutes. It will not be noticeable for the user either you add 6ms or 300ms to this time. But it will be very noticeable if the sessions block each other.&lt;/p&gt;
&lt;p&gt;Another option is to create an index, that includes all fields used in the WHERE clause. You can test it using the following command.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;sql&quot;&gt;&lt;pre class=&quot;language-sql&quot;&gt;&lt;code class=&quot;language-sql&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;CREATE&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;NONCLUSTERED&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;INDEX&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;I_TEST1&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;ON&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;dbo&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;DEVBLOCKINGTESTTABLE&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;PARTITION&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;ASC&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;DATAAREAID&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;ASC&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;FIELD2&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;ASC&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;FIELD3&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;ASC&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;ON&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;PRIMARY&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;  &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Field3 may be added as a normal or &quot;include&quot; index field. This will resolve our blocking issue in test 2. But when someone tries to update the same table using a different set of fields(for example Field2 and Field4) we&apos;ll get blocking again.&lt;/p&gt;
&lt;p&gt;Does adding an index always remove blocking? No. Sometimes you need to remove existing index in order solve it. One of the most common cases - blocking of InventSumDelta table in AX2012 - &lt;a href=&quot;https://axology.wordpress.com/2013/12/19/locking-on-the-inventsumdelta-table-additional-tweaks/&quot;&gt;https://axology.wordpress.com/2013/12/19/locking-on-the-inventsumdelta-table-additional-tweaks/&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Locking on the InventSumDelta table – additional tweaks  - We tried
changing the column sequence on the two tables to have Partition and
DataAreaId in the beginning, but nothing happened &lt;strong&gt;until we disabled the&lt;/strong&gt;
&lt;strong&gt;ItemId index too&lt;/strong&gt;. That had an instant effect and practically removed the
deadlock issues immediately.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;summary&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#summary&quot; aria-label=&quot;summary permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Summary&lt;/h2&gt;
&lt;p&gt;Following some performance tips(even if they are given by Microsoft experts) without knowing the drawbacks can sometimes slow down your system.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Try to avoid any &lt;strong&gt;update_recordset&lt;/strong&gt; and &lt;strong&gt;delete_from&lt;/strong&gt; usage by default(especially in document posting operations - e.g. Sales-Purch orders, Journals..) if you don&apos;t get any measurable performance boost(less than 1%). For example, if you want to update/delete less than 1000 rows in a transaction that can last more than a minute, better to use &lt;strong&gt;select forupdate&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Use set based operations only when you are 100% sure that it will not cause blocking and you really need to reduce the operation time&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If you still want to use &lt;strong&gt;update_recordset&lt;/strong&gt;, check that all fields, used in WHERE condition, are covered by the existing indexes&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I put objects used in this article to GitHub (form &lt;strong&gt;DEVBlockingTest&lt;/strong&gt;, table &lt;strong&gt;DEVBlockingTestTable&lt;/strong&gt; - &lt;a href=&quot;https://github.com/TrudAX/XppTools/tree/master/DEVTutorial&quot;&gt;https://github.com/TrudAX/XppTools/tree/master/DEVTutorial&lt;/a&gt;). Feel free to experiment with it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update 16/08/2021&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Check this video from Brent Ozar &lt;a href=&quot;https://youtu.be/EqfAPZGKifA&quot;&gt;Blocking and Locking: How to Find and Fight Concurrency Problems&lt;/a&gt; that explains the fundamentals of locking in detail&lt;/p&gt;</content:encoded></item><item><title><![CDATA[RunBase template class builder]]></title><description><![CDATA['RunBase class builder' Add-in parameters description and usage scenarious]]></description><link>https://denistrunin.com/runbasebuilder-util/</link><guid isPermaLink="false">https://denistrunin.com/runbasebuilder-util/</guid><pubDate>Tue, 08 Jan 2019 22:12:03 GMT</pubDate><content:encoded>&lt;p&gt;This topic describes &quot;RunBase class builder&quot; Add-in, its parameters and usage. The purpose of this Add-in is to generate code template for a class that extends RunBaseBatch based on typical usage scenarios. Use the following &lt;a href=&quot;https://github.com/TrudAX/TRUDUtilsD365/releases&quot;&gt;link&lt;/a&gt; to download it.&lt;/p&gt;
&lt;h2 id=&quot;main-screen&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#main-screen&quot; aria-label=&quot;main screen permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Main screen&lt;/h2&gt;
&lt;p&gt;Add-in can be run from the &lt;strong&gt;Dynamics 365&lt;/strong&gt; - &lt;strong&gt;Addins&lt;/strong&gt; - &lt;strong&gt;RunBase class builder&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;You can specify values for each parameter, preview the changes(using the Refresh button) and if you are fine with it, automatically generate the class and the related menu item.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 700px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/270e4d30b426012f81bd09052d37e277/748b0/ToolMainScreen.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 50.28571428571429%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB80lEQVR42nWSbW/aMBSF8/9/wbTvk7ZVlaZJ20rbQTfIgFKKgNIBgUDjJIWQhBDyQhLI6bV5Wfthlo5sy9bjc8+15C8d2Asbi/kccRxjt9siTTbIshR5vkNO+yxNEUURTMfHzA2wDlKh1cqH67oIghDbTQRl5kO6kRsoluu4Ksn4XW2i1uyIdalyi2qjjXqrh6HKwDQNrZ6Cbn8MRbEwGMzAmA7TNLHy1wLYmcwhnf2o4OxCxnmhivPLKj59r5z08VsZny9qaPQm8L0lbHtBjmwYJsNmE+M4dvl+vhvokNqPCh6GU3JhoNMboK+o0M05LMeDZjxjNNFgOy6BHAKZFM8Cuq6TK19A8jw/AR+ZA6l0N0ThTxfvP3xFoViGTqXxLI+X+ciyDI5tYzajhyhry7JOZ68d9o0lZXg/wpfrOt4RUKbMojBAGIYCelRA+2C9hqqqMMhdmmb7B5EfgPk/YKmp4FdrjMvaX3SHT1hTKbxrHMQ7y+cwoM5S8AHNySYRjl+PNw458OZewfXtACPdOpT65j6SJBFwxjTKzyDHgSh7QXnyR7iBXRrvM/xJGRablGOtD0X7P5BLIyBjTICYWOviH1ocvFqip9mQal0VdZLcHmP09IyYnPDMwoO4M8/zRDM4bDqdCnccxM+4wjDCNtn/wxcEMObtfimP6AAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;1546917739841&quot;
        title=&quot;&quot;
        src=&quot;/static/270e4d30b426012f81bd09052d37e277/8c557/ToolMainScreen.png&quot;
        srcset=&quot;/static/270e4d30b426012f81bd09052d37e277/4edbd/ToolMainScreen.png 175w,
/static/270e4d30b426012f81bd09052d37e277/13ae7/ToolMainScreen.png 350w,
/static/270e4d30b426012f81bd09052d37e277/8c557/ToolMainScreen.png 700w,
/static/270e4d30b426012f81bd09052d37e277/748b0/ToolMainScreen.png 868w&quot;
        sizes=&quot;(max-width: 700px) 100vw, 700px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;As a result, the following class will be generated&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 583px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/91a8cc0b3aeaf28fe09c84cc13bbdce1/9fc4b/ParmsWithQuery.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 89.14285714285714%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAYAAABb0P4QAAAACXBIWXMAAAsTAAALEwEAmpwYAAABhUlEQVR42qVUa2+DMBDL//+Jk/ZlK+VZoEBeEPDOWSNVVdeW7qRTSAiOz+egmqbB6XTCNE1xbNsWWmtkWQbvPZ7Fuq4wxsg3Frr7gBqGAcuyxJznOSaBON+2DXsirJsAjiOqqgKZlmWJoigiO873AgICqI2LbLxzCCFEkFugtHbv3XXpDGWMxfl8jtoZa/FuJDLKCTNPUUVLLeUvbIS8xBUTbv4VXkeNH4VysnHuOrhLBgGdpdtBup6CDiAgtWU1jwGlzE00XOXkNK7CcrtocqvTs0YpltH3HdquBS1UCzvKsDeSzRQ955YNowtv2OQOQwIO4vK8auMp/wZ0AthLM7LDIQq+3tFuN0Nqxk6O0mErTeL8XWBFEALQFinZKK6lu/1Kpv2K95h3uK5r5HmO4/EYR5ZPQ6cfx7PUmhVOUCyVZafkSSybz3+xWSQDgdJzEP9Kck296rlkKO0Dvk4Wn8WArHNodcChmfBdj5j8xYd7ws4rysEj7zSaccZgA6reSFqYecMP+LCHuwnhxK0AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;1546919626624&quot;
        title=&quot;&quot;
        src=&quot;/static/91a8cc0b3aeaf28fe09c84cc13bbdce1/9fc4b/ParmsWithQuery.png&quot;
        srcset=&quot;/static/91a8cc0b3aeaf28fe09c84cc13bbdce1/4edbd/ParmsWithQuery.png 175w,
/static/91a8cc0b3aeaf28fe09c84cc13bbdce1/13ae7/ParmsWithQuery.png 350w,
/static/91a8cc0b3aeaf28fe09c84cc13bbdce1/9fc4b/ParmsWithQuery.png 583w&quot;
        sizes=&quot;(max-width: 583px) 100vw, 583px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Let&apos;s describe the Add-in parameters&lt;/p&gt;
&lt;h3 id=&quot;-class-name&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#-class-name&quot; aria-label=&quot; class name permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;-Class name&lt;/h3&gt;
&lt;p&gt;The name of the resulting class.&lt;/p&gt;
&lt;h3 id=&quot;-description&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#-description&quot; aria-label=&quot; description permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;-Description&lt;/h3&gt;
&lt;p&gt;The value that will be returned from the static description() method.&lt;/p&gt;
&lt;h3 id=&quot;-parameters&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#-parameters&quot; aria-label=&quot; parameters permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;-Parameters..&lt;/h3&gt;
&lt;p&gt;You can specify several parameters that will be displayed in the user dialog, one line per parameter. To describe the parameter the following information should be provided(values are separated by a | delimiter):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;EDT&lt;/strong&gt; - Extended data type name for the dialog field. For mandatory fields add * at the end&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Variable name&lt;/strong&gt; - class variable for this EDT. Can be empty, in this case, it will be generated from the EDT name&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Label&lt;/strong&gt; - you can override EDT label for the field on the dialog form. If the Label is empty, EDT label will be used&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Help text&lt;/strong&gt;- you can override EDT help text for the field on the dialog form. If it is empty, EDT help text will be used&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following code is generated for each parameter:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;//ClassDeclaration&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;CustAccount&lt;/span&gt;  custAccount&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;DialogField&lt;/span&gt;  dlgCustAccount&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token preprocessor property&quot;&gt;#localmacro.CurrentList&lt;/span&gt;
    custAccount
&lt;span class=&quot;token preprocessor property&quot;&gt;#endmacro&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//dialog&lt;/span&gt;
dlgCustAccount     &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; dialog&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addFieldValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;extendedtypestr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;CustAccount&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; custAccount&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//getFromDialog&lt;/span&gt;
custAccount      &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; dlgCustAccount&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//parm method&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;CustAccount&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;parmCustAccount&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;CustAccount&lt;/span&gt; _custAccount &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; custAccount&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token range operator&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;-query-table&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#-query-table&quot; aria-label=&quot; query table permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;-Query table&lt;/h3&gt;
&lt;p&gt;If you want to display a query in the dialog, you need to specify the main table for this query. In this case, the following code will be added:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;//ClassDeclaration&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;QueryRun&lt;/span&gt;       queryRun&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//initQuery() sample code for query init&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;Query&lt;/span&gt;                   query &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;Query&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;QueryBuildDataSource&lt;/span&gt;    qbds &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; query&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addDataSource&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;tablenum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;CustTable&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;QueryBuildRange&lt;/span&gt;         qBR&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
qBR &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; SysQuery&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findOrCreateRange&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;qbds&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fieldnum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;CustTable&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; RecId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
qBR&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token named-parameter punctuation&quot;&gt;RangeStatus&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;HIDDEN&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
queryRun &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;QueryRun&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;query&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//pack() unpack() support for this queryRun&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//run() - sample code&lt;/span&gt;
qBDS &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; queryRun&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;dataSourceTable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;tableNum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;CustTable&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        SysQuery&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findOrCreateRange&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;qBDS&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fieldnum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;CustTable&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; RecId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;queryValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;progressInit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token named-parameter punctuation&quot;&gt;RunBase&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getDescription&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;classIdGet&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                  &lt;span class=&quot;token named-parameter punctuation&quot;&gt;SysQuery&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;countTotal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;queryRun&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                  &lt;span class=&quot;token preprocessor property&quot;&gt;#AviSearch);&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;queryRun&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    custTable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; queryRun&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;tablenum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;CustTable&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    processedCounter&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    progress&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;incCount&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;-external-table-name&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#-external-table-name&quot; aria-label=&quot; external table name permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;-External table name&lt;/h3&gt;
&lt;p&gt;Table name of the caller record should be specified. This covers a scenario when class is calling from a Menu item button on a form. Often, in this case, we need to save the caller record, to check for the caller record or to update the existing query based on the caller record.&lt;/p&gt;
&lt;p&gt;The following code will be generated (&lt;strong&gt;External table name&lt;/strong&gt; = CustTable)&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;//ClassDeclaration&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;CustTable&lt;/span&gt;    callerCustTable&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//main&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;_args&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;dataset&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;tablenum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;CustTable&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token named-parameter punctuation&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;missingRecord&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;funcname&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
runObject&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parmCallerCustTable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;_args&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;_args &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; _args&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;TableId &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;tablenum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;CustTable&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    qbds &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; runObject&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;queryRun&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;dataSourceTable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;tablenum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;CustTable&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    qbds&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;clearRanges&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    qbds&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addRange&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fieldnum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;CustTable&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; RecId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;queryValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;runObject&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parmCallerCustTable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;RecId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;//runObject.parmIsDisableUnpackQuery(true);&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;-add-file-upload&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#-add-file-upload&quot; aria-label=&quot; add file upload permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;-Add file upload&lt;/h3&gt;
&lt;p&gt;You need to specify &apos;y&apos; symbol to generate code that allows a user to select a file from the local PC. It will add a fileUploadResult variable, a necessary code to handle this file and a sample code that displays uploaded text file content.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 570px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/81440071b679c014da9f47f86446a68b/432e7/FileUpload.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 71.42857142857143%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAAsTAAALEwEAmpwYAAABHUlEQVR42p1Uy26DMBDk//+shyoSTRSphxKJNiUJzwAGA/Z0xyot3MArjYwNjGe8uw601iiKAk3ToKoqN5ZlibZtsTeMMQjGcUSe544kTVOHJEncJj4RTNOErusc+OwbVGetRTAMg7NKhbS/fOlFOInlSsg4sVwUgGSOcIGNGwQkKp5PlHXtxvo3GTSvhWOQcdxzht3jgeJyQR5Fq/EWfeLt9YzDS4j4PYaW7zYRKsloEoZIjkfcTifUQthEH2jjGOr76tBev9Dd7xsty5kZsWv7XjxqWKUwSskYzn3KxkipMMtz/f3FnJglNhGKQpZLL4qyLFuT+ShkpyixSZCYredT4P91KD9T3Qzfjll1CtXxMqglOTO4vicogpfDD50oTV4sjiEmAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;1546932149579&quot;
        title=&quot;&quot;
        src=&quot;/static/81440071b679c014da9f47f86446a68b/432e7/FileUpload.png&quot;
        srcset=&quot;/static/81440071b679c014da9f47f86446a68b/4edbd/FileUpload.png 175w,
/static/81440071b679c014da9f47f86446a68b/13ae7/FileUpload.png 350w,
/static/81440071b679c014da9f47f86446a68b/432e7/FileUpload.png 570w&quot;
        sizes=&quot;(max-width: 570px) 100vw, 570px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;//run()&lt;/span&gt;
memoryStreamFile &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; fileUploadResult&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;openResult&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;AsciiStreamIo&lt;/span&gt; asciiIo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; AsciiStreamIo&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;constructForRead&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;memoryStreamFile&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
asciiIo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;inRecordDelimiter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token char&quot;&gt;&apos;\n&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;asciiIo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; IO_Status&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;Ok&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;container&lt;/span&gt; c &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; asciiIo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;conLen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;c&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;strFmt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;File data:%1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;conPeek&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;c&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Comparing to AX2012(where you can simply define a variable with the FileNameOpen type) adding file upload button requires more efforts in D365FO, as Dialog doesn&apos;t include new file control. I even created an idea to improve this &lt;a href=&quot;https://experience.dynamics.com/ideas/idea/?ideaid=ac0834aa-216c-e711-80c0-00155d7cd0b4&quot;&gt;https://experience.dynamics.com/ideas/idea/?ideaid=ac0834aa-216c-e711-80c0-00155d7cd0b4&lt;/a&gt;, but its status is still New.&lt;/p&gt;
&lt;h3 id=&quot;-create-menu-item&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#-create-menu-item&quot; aria-label=&quot; create menu item permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;-Create menu item&lt;/h3&gt;
&lt;p&gt;Specify &apos;y&apos; symbol to create an Action menu item, linked to the created class.&lt;/p&gt;
&lt;h2 id=&quot;summary&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#summary&quot; aria-label=&quot;summary permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Summary&lt;/h2&gt;
&lt;p&gt;This utility covers some common patterns of RunBase usage, so you can focus on business logic developing rather than typing standard code. If you find that something is missing or can be improved don&apos;t hesitate to leave a comment.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[How to setup Financial reporting on D365FO local One box VM]]></title><description><![CDATA[Using Financial reporting (aka Management Reporter in Ax2012) on local DEV D365FO one box requires some addition settings, that are not yet documented. This post describes the problem and a possible solution.]]></description><link>https://denistrunin.com/financial-reporting-local-onebox/</link><guid isPermaLink="false">https://denistrunin.com/financial-reporting-local-onebox/</guid><pubDate>Sat, 22 Dec 2018 22:12:03 GMT</pubDate><content:encoded>&lt;p&gt;Using Financial reporting (aka Management Reporter in Ax2012) on local DEV D365FO one box requires some addition settings, that are not yet documented. This post describes the problem and possible solution.&lt;/p&gt;
&lt;h2 id=&quot;problem-description&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#problem-description&quot; aria-label=&quot;problem description permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Let&apos;s start with the standard 8.1PU20 VM One box.&lt;/p&gt;
&lt;p&gt;Download and install it, rename and execute AdminUserProvisioning tool.&lt;/p&gt;
&lt;p&gt;Then open &lt;em&gt;General ledger - Inquiries and reports - Financial reports&lt;/em&gt; and press New in this form&lt;/p&gt;
&lt;p&gt;Go to the Tools - Reset Data Mart and press OK.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 549px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/fc69de14e0cc506d76db9cb394fbf967/928ea/MRResetScreen.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 92%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAYAAABb0P4QAAAACXBIWXMAAAsTAAALEwEAmpwYAAADR0lEQVR42p1U227bRhDll/c16EPeky8oUCRRFNm1YilQI6t2g7hpLNmyREqiKN6W94tEiqQpncwu3QAJgj5kgcHsdXb2zDkrzRQNts3IbDiOC4cxeK4L13GQpgmSOBYWhYHw2zRFWRYoij3KgvuCxiWqqsR+v4ek6R6YbcGxTbheLAJbzIFh2jAsu7nM2sBmLhmDZnrwox22ux2SLfc5WSb6ZVVBar3qoNVq4+Skgz/O3mKxbg67foSsKJHtC+yrB+RFhR31M/K8n+UFdnkzjimYH8VwwwTSaaeFfreN1+03OO2eYyYrkGczWKaJwPcRhiGCIKAnh4ijSBjvhwSBML7G5+MIluvRk7UNcKQs8hxFVeNeXuDq6m98/vcGHgVsNscwDAPL5QrKYiH6fJ6b73tQlAUsy8JaNyGp6hpNO6KqD4iSFD9qx+PxG/u+1fUDmB9AWmva44EDyocaYZyK4D869H+N71c1nQKuv89wi59pPOBqTQHH4xtEgQXbXMHUVQQE+M+0w6GGbruQ+i+eY9F9gnHrF8y6v8LSZDCHuEZ4+AFVMwpFUbjxiseC6MnXMS9MkiSIqMrrjQHpt987GLzr4YzoM7oY4v5+Cnl6izT0kCcBkdqCqqrQCGuXFLRaqbRnhgVV2/M8cMhmszl03YBGJr1ud/BuMMDbXg/9fh8vRnM8uwrw7NLH02EAI8xQEqUSqj7P5KGuRXYBvaAiwh9o7JJkNyQI5oVE7LM2ev1zUsophhcX+HS3wOizglvNhxbVVPmDwCjPMuKa3dCGF+FwpLn869qSMtZtB9J5v4fBnwN0u10M/7rEhoiuq0t4zILPTBo3T+VqYaRlgWHSfBr/qcgnAfDPhLnEw5POGwyHQ3z4QOq4mWA8ucP4Zkw43WM+nxM+M1KCAoUkyb0sy2JtOp0Sbvo30vS4ll++fIXRaITh+/e4GF3ijgCfjMeYTG4J+KWQFKPb+WEuMR7s+uNH/HN9LYrF17kUufY3pgWJOYxK/5h+GItKrVZLsZlnxCFI6Q/ktt1uyVLsyGfZTvT5p5DwNTLDYpA4HhxoTkz+DzpeIATPcfM8X1AjjhoeRo/eCyJMVjY+yQYU3cGaLt9s6NtzfXwB0D05s53icYkAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;1545399001281&quot;
        title=&quot;&quot;
        src=&quot;/static/fc69de14e0cc506d76db9cb394fbf967/928ea/MRResetScreen.png&quot;
        srcset=&quot;/static/fc69de14e0cc506d76db9cb394fbf967/4edbd/MRResetScreen.png 175w,
/static/fc69de14e0cc506d76db9cb394fbf967/13ae7/MRResetScreen.png 350w,
/static/fc69de14e0cc506d76db9cb394fbf967/928ea/MRResetScreen.png 549w&quot;
        sizes=&quot;(max-width: 549px) 100vw, 549px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;You will get the error &quot;There was a problem communicating with the server&quot;&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 308px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/e86ea7ded1e448eee6e897cf91ac5de1/3a5b9/clip_image002.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 40%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAIABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAEF/8QAFQEBAQAAAAAAAAAAAAAAAAAAAAH/2gAMAwEAAhADEAAAAdygCf/EABYQAQEBAAAAAAAAAAAAAAAAAAARAf/aAAgBAQABBQJVx//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABQQAQAAAAAAAAAAAAAAAAAAABD/2gAIAQEABj8Cf//EABkQAAIDAQAAAAAAAAAAAAAAAAABETFBkf/aAAgBAQABPyGqjg4ahM1M/9oADAMBAAIAAwAAABCAP//EABURAQEAAAAAAAAAAAAAAAAAAAAR/9oACAEDAQE/EFf/xAAVEQEBAAAAAAAAAAAAAAAAAAAAEf/aAAgBAgEBPxBH/8QAGBABAQEBAQAAAAAAAAAAAAAAAREAcWH/2gAIAQEAAT8QAVi9ZBUjjhxfRN//2Q==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;img&quot;
        title=&quot;&quot;
        src=&quot;/static/e86ea7ded1e448eee6e897cf91ac5de1/3a5b9/clip_image002.jpg&quot;
        srcset=&quot;/static/e86ea7ded1e448eee6e897cf91ac5de1/e52aa/clip_image002.jpg 175w,
/static/e86ea7ded1e448eee6e897cf91ac5de1/3a5b9/clip_image002.jpg 308w&quot;
        sizes=&quot;(max-width: 308px) 100vw, 308px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;and weird text in the Event log, like this&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;exceptionMessage {&quot;Class&quot;:16,&quot;Number&quot;:8169,&quot;State&quot;:2,&quot;Message&quot;:&quot;Conversion failed when converting from a character string to uniqueidentifier.&quot;,&quot;ErrorCode&quot;:-&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;There is a standard topic about Data Mart reset on the docs site, but it works only if you have a proper connection properties&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/dynamics365/unified-operations/dev-itpro/analytics/reset-financial-reporting-datamart-after-restore?toc=/fin-and-ops/toc.json&quot;&gt;https://docs.microsoft.com/en-us/dynamics365/unified-operations/dev-itpro/analytics/reset-financial-reporting-datamart-after-restore?toc=/fin-and-ops/toc.json&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If your search the same topic for AX2012, you will find several posts, that describe full reset(like this one - Management Reporter: Rebuilding your Data Mart
&lt;a href=&quot;https://community.dynamics.com/365/financeandoperations/b/dynamicsaxbi/archive/2016/02/01/management-reporter-rebuilding-your-data-mart&quot;&gt;https://community.dynamics.com/365/financeandoperations/b/dynamicsaxbi/archive/2016/02/01/management-reporter-rebuilding-your-data-mart&lt;/a&gt; )&lt;/p&gt;
&lt;p&gt;But the problem is that in D365FO we don&apos;t have MR Configuration Console, instead, PowerShell should be used.&lt;/p&gt;
&lt;h2 id=&quot;solution&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#solution&quot; aria-label=&quot;solution permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Solution&lt;/h2&gt;
&lt;p&gt;Let&apos;s recreate a Data Mart using the standard PowerShell scripts&lt;/p&gt;
&lt;p&gt;Open PowerShell ISE as administrator&lt;/p&gt;
&lt;p&gt;As a first step, let&apos;s back up our existing ManagementReporter database&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;powershell&quot;&gt;&lt;pre class=&quot;language-powershell&quot;&gt;&lt;code class=&quot;language-powershell&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$FileNameLocal&lt;/span&gt; = &lt;span class=&quot;token string&quot;&gt;&quot;C:\backup\ManagementReporter.bak&quot;&lt;/span&gt;
&lt;span class=&quot;token variable&quot;&gt;$FileDirName&lt;/span&gt; = &lt;span class=&quot;token function&quot;&gt;Split-Path&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$FileNameLocal&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;New-Item&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;ItemType Directory &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;Path &lt;span class=&quot;token variable&quot;&gt;$FileDirName&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;Force
&lt;span class=&quot;token function&quot;&gt;Backup-SqlDatabase&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;ServerInstance localhost &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;Database &lt;span class=&quot;token string&quot;&gt;&quot;ManagementReporter&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;BackupFile &lt;span class=&quot;token variable&quot;&gt;$FileNameLocal&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;CompressionOption On&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then import the standard MRDeploy library and check it&apos;s default settings&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;powershell&quot;&gt;&lt;pre class=&quot;language-powershell&quot;&gt;&lt;code class=&quot;language-powershell&quot;&gt;cd C:\FinancialReporting\Server\MRDeploy
&lt;span class=&quot;token function&quot;&gt;Import-Module&lt;/span&gt; –Name C:\FinancialReporting\Server\MRDeploy\MRDeploy&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;psm1 &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;Verbose
&lt;span class=&quot;token function&quot;&gt;Get-MRDefaultValues&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The current problem is that many pre-configured parameters contain irrelevant to local One box values(like DB name is AXDBRAIN instead of AxDB, some users credentials are empty)&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 521px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/eec6b74d462e5ed7446683c8b27d67e4/bb9c5/MRPsCommands.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 73.71428571428572%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAAAsTAAALEwEAmpwYAAACpklEQVR42qVT/UtTYRi9qdt0aYqaSjq/trk5p/Nr23VT1IzK3PS6zS1dVtacmin57Uzqh8jE/yAQxD8sKBAiCCHot4rTeV+nmagEXThc7vtxnvOc51zlx6+f+PrlOz59OMTBx0N8PviG/3kU7d0+ht/uIbTN95tdaFt7CGy+R2BrH8HXuwhO7yA4uY1AGoPJy6HoXQ+R4XyArOZH0LmIlsfQNY7D4EkgsyGOrOoQ9HUx6K0xZNVEoJQGoJSlUXoOTGoSlR1JFJCkgOTyImGsH0OFN4mqzmmYfFMwsmiGJSpxxZyG+BbnbfdPoHQMp+ALp+DqX4Tr3hIq/FPQceMqCzjvLKCmawb1t+ZRLoqyi+K2CZR4nqLUnUBx64QspJhHJLmA4hlchWdoDW2BZVh6Z3FDnUROw5gk9Ghr8AwSQ6uouzmHCl8SJW6SkbDMm0BJ+xPkNp4hdAdWSbYCL0mddxeQJypWhyWhP7wBVVtHK5Xb++ZQREWZbFWpCsszEjXhMwqHjhS0DCzBy8sdxLWmcWQ74vLbyz2VtrQFV2DtfQ5Lz6y0wEQLclk0nzZk0+9jUkUQqWzN3jePJiq0szW9bZRtx9E6sAxzzzPYqE74aeOe8/YLri+hXE1wIFHo7aPIZApOFApFnZEUmtlWZecUckQ1tpJHlb5QSnon1o1UrNSeas0yIlVJpNfkuk8SbqCdLRUyg6KqOGQQseHExXTzmU+hRDH/uXgRFL8mYrN+NOk0qSAUBAaRK2F8bQQZp4y/nJBt+ULrcNN8EYvrMgrjEj2xV/R1EUXir7GN/ZvC7ugmukZews28lZNQpj2tUMfhGPk21UehOjRYbMP0K3b0t1xEKCZ87GFt9ywKmTXpoWMUZf4ZWFviiDj6UV2nwWiN/DWA8wh/A/fhKQiewGQfAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;1545399953847&quot;
        title=&quot;&quot;
        src=&quot;/static/eec6b74d462e5ed7446683c8b27d67e4/bb9c5/MRPsCommands.png&quot;
        srcset=&quot;/static/eec6b74d462e5ed7446683c8b27d67e4/4edbd/MRPsCommands.png 175w,
/static/eec6b74d462e5ed7446683c8b27d67e4/13ae7/MRPsCommands.png 350w,
/static/eec6b74d462e5ed7446683c8b27d67e4/bb9c5/MRPsCommands.png 521w&quot;
        sizes=&quot;(max-width: 521px) 100vw, 521px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;I could not find any documentation that describes the correct configuration for One box, so just specified one value for all user accounts.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;powershell&quot;&gt;&lt;pre class=&quot;language-powershell&quot;&gt;&lt;code class=&quot;language-powershell&quot;&gt;&lt;span class=&quot;token function&quot;&gt;Set-MRDefaultValues&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;SettingName AXDatabaseName &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;SettingValue AxDB
&lt;span class=&quot;token function&quot;&gt;Set-MRDefaultValues&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;SettingName AosUserName &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;SettingValue AOSUser
&lt;span class=&quot;token function&quot;&gt;Set-MRDefaultValues&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;SettingName AosUserName &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;SettingValue AOSWebSite@123
&lt;span class=&quot;token function&quot;&gt;Set-MRDefaultValues&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;SettingName AosWebsiteName &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;SettingValue AOSService
&lt;span class=&quot;token function&quot;&gt;Set-MRDefaultValues&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;SettingName MRSqlUserName &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;SettingValue AOSUser
&lt;span class=&quot;token function&quot;&gt;Set-MRDefaultValues&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;SettingName MRSqlUserPassword &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;SettingValue AOSWebSite@123
&lt;span class=&quot;token function&quot;&gt;Set-MRDefaultValues&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;SettingName MRSqlRuntimeUserName &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;SettingValue AOSUser
&lt;span class=&quot;token function&quot;&gt;Set-MRDefaultValues&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;SettingName MRSqlRuntimeUserPassword &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;SettingValue AOSWebSite@123
&lt;span class=&quot;token function&quot;&gt;Set-MRDefaultValues&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;SettingName DDMSqlUserName &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;SettingValue AOSUser
&lt;span class=&quot;token function&quot;&gt;Set-MRDefaultValues&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;SettingName DDMSqlUserPassword &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;SettingValue AOSWebSite@123
&lt;span class=&quot;token function&quot;&gt;Set-MRDefaultValues&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;SettingName DDMSqlRuntimeUserName &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;SettingValue AOSUser
&lt;span class=&quot;token function&quot;&gt;Set-MRDefaultValues&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;SettingName DDMSqlRuntimeUserPassword &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;SettingValue AOSWebSite@123
&lt;span class=&quot;token function&quot;&gt;Set-MRDefaultValues&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;SettingName AXSqlUserName &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;SettingValue AOSUser
&lt;span class=&quot;token function&quot;&gt;Set-MRDefaultValues&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;SettingName AXSqlUserPassword &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;SettingValue AOSWebSite@123
&lt;span class=&quot;token function&quot;&gt;Set-MRDefaultValues&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;SettingName AXSqlRuntimeUserName &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;SettingValue AOSUser
&lt;span class=&quot;token function&quot;&gt;Set-MRDefaultValues&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;SettingName AXSqlRuntimeUserPassword &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;SettingValue AOSWebSite@123&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The main script can then be run. It will delete the existing ManagementReporter database and performs a new DB initialization.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;powershell&quot;&gt;&lt;pre class=&quot;language-powershell&quot;&gt;&lt;code class=&quot;language-powershell&quot;&gt;&lt;span class=&quot;token function&quot;&gt;New-MRSetup&lt;/span&gt;  &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;IntegrateDDM&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;After that, you can run the Reset command without errors. If you check Integration status you will see &quot;Integration complete&quot;&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 374px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/365d96ae57e16cbd8141d0ffca04e224/52dba/IntegrationComplete.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 62.28571428571429%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAAsTAAALEwEAmpwYAAACMElEQVR42n2Ty47TMBSG866IBUIskOAleApWaGDYswO2LKCdtrk6ceLEuSejNulM7/05x4KhgwSRjuw4x7+/3+fEyrVGFEWQMkYYhiiKAk3TmOi6zsTf81hK2iNR1zX6vkdVVbRf0ljDYrHAD+A4DkJK4k01fei7HufzGafTCcfj0cw5dKbh2A58zzcC+/0OcRybNaUUrCxNoXVuyMqixP39Pf736CwzG0vK7+jQ3W6HVKUkqqDSDJbv+7iZzeC6HuazBTwaPTq9aVpj53A4PBJkN/PZHM7CJuEMm80GC5pPfkzg0zcrJdWyLFGVFVGWaNvWiK3XdyaZLV8+7IJtM2Hf3+Kw36PIc2RErmm0fp/IZPbCoeQcq+US539YDsgR5/uehzTV5lDbEE6JUMCS5D2MU0RJhlAq6KLGchhxIDJmO5HyJaOmrkgSZe6yaTsqyh7sktcyIrfefhV48c7D6w8eXl0HeHnl4Rm9P30v8fyjwpOrBG8+V7+Iz4jCiNz4CIWgq6qw3W7N3c3nC2q7CJaIYngihiskkWYm7EBi6ghMbYGZG6G5HR4IkziBCIQRZCKuMgsFtMaVtpIkpkaNwe2jCHscR9ytR6zHAcNqhdPxcZU5hyk5v6ECsiAfEpIgjxZXR6Xqz93QyD2pTeU0llSgYRgegivKfZckCXKaN9SLAd09OxRMaDrfcQk5ML8fE66IjOl4zoKXwWtt22AymcKlv8tJSny5ifHpm4fvssFP9iN0I+VyaskAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;1545401515609&quot;
        title=&quot;&quot;
        src=&quot;/static/365d96ae57e16cbd8141d0ffca04e224/52dba/IntegrationComplete.png&quot;
        srcset=&quot;/static/365d96ae57e16cbd8141d0ffca04e224/4edbd/IntegrationComplete.png 175w,
/static/365d96ae57e16cbd8141d0ffca04e224/13ae7/IntegrationComplete.png 350w,
/static/365d96ae57e16cbd8141d0ffca04e224/52dba/IntegrationComplete.png 374w&quot;
        sizes=&quot;(max-width: 374px) 100vw, 374px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;summary&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#summary&quot; aria-label=&quot;summary permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Summary&lt;/h2&gt;
&lt;p&gt;I posted the whole script to GitHub - &lt;a href=&quot;https://github.com/TrudAX/TRUDScripts/tree/master/FinancialReporting&quot;&gt;https://github.com/TrudAX/TRUDScripts/tree/master/FinancialReporting&lt;/a&gt; It has been tested for the 8.1 version. If you find any issues or have ideas how to improve it, Pull requests are always welcome. Hope Microsoft will fix this in the new version, as right now it looks like a missing documentation step.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Do we really need index hints? (forceLiterals vs forcePlaceholders)]]></title><description><![CDATA[Index hint is a new feature announced in D365FO PU23. When do we need it and what is the performance overhead of others alternatives.]]></description><link>https://denistrunin.com/forceliterals-forcePlaceholders/</link><guid isPermaLink="false">https://denistrunin.com/forceliterals-forcePlaceholders/</guid><pubDate>Mon, 10 Dec 2018 22:12:03 GMT</pubDate><content:encoded>&lt;p&gt;The idea to write this post came after a discussion of the new PU23 feature “Enabling index hints in X++ again”&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/dynamics365/unified-operations/fin-and-ops/get-started/whats-new-platform-update-23#enabling-index-hints-in-x-again&quot;&gt;https://docs.microsoft.com/en-us/dynamics365/unified-operations/fin-and-ops/get-started/whats-new-platform-update-23#enabling-index-hints-in-x-again&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;And the main question during the discussion was – Do we really need “index hint” for the modern SQL Server?&lt;/p&gt;
&lt;p&gt;First, let&apos;s discuss the basic methods of SQL query generation.
In D365FO we have 2 ways of executing a SQL statement&lt;/p&gt;
&lt;h3 id=&quot;forceplaceholders&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#forceplaceholders&quot; aria-label=&quot;forceplaceholders permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;strong&gt;ForcePlaceholders&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;This is the default query execution mode. In this case, every SQL Statement that you write in X++, is processed in 2 steps – first &lt;strong&gt;sp_prepare&lt;/strong&gt; command executed with placeholders instead of actual values and as a result of this &lt;strong&gt;sp_prepare&lt;/strong&gt; command, we get a cached plan. Then &lt;strong&gt;sp_cursorexecute&lt;/strong&gt; is called, that executes the query using this plan and the actual values. For one SQL statement with the different values, the plan is calculated only once.&lt;/p&gt;
&lt;p&gt;How does SQL server determine what plan to generate in &lt;strong&gt;sp_prepare&lt;/strong&gt; if the statement is new (for some values one plan may be more efficient than for others)? For new unknown plans it uses a “parameters sniffing” feature. If it gets &lt;strong&gt;sp_prepare&lt;/strong&gt; command for a new statement, it doesn’t try to calculate it immediately, instead, it waits for the first call of &lt;strong&gt;sp_cursorexecute&lt;/strong&gt; and uses the first passed values to calculate the plan.&lt;/p&gt;
&lt;h3 id=&quot;forceliterals&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#forceliterals&quot; aria-label=&quot;forceliterals permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;strong&gt;ForceLiterals&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;In this case, your current SQL statement (with the actual values) is sent to SQL Server and executed as it is. The drawback of this is that for every set of values you will need to parse this statement and compile a new SQL plan.&lt;/p&gt;
&lt;h3 id=&quot;parameters-sniffing&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#parameters-sniffing&quot; aria-label=&quot;parameters sniffing permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;strong&gt;Parameters sniffing&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Parameters sniffing quite often becomes a reason for performance problems. For example, you have a warehouse where most of the items have one batch ID, but there are some Items and Batches with general names (like “No batch”, “Empty”). In this situation, when you query item by batch your actual plan depends on the first query values. If your query contains “general” batch values, SQL Server creates a plan that starts execution with the ItemId, as a “general batch value” is not selective in this case. But for most of your items, it will be wrong and gives huge overhead, as in most cases Batch is a unique value.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How to resolve a Parameters sniffing issue&lt;/strong&gt;:&lt;/p&gt;
&lt;p&gt;There is no universal way to resolve Parameters sniffing issue(refer to the excellent BrentOzar post that describes this &lt;a href=&quot;https://www.brentozar.com/archive/2013/06/the-elephant-and-the-mouse-or-parameter-sniffing-in-sql-server/&quot;&gt;https://www.brentozar.com/archive/2013/06/the-elephant-and-the-mouse-or-parameter-sniffing-in-sql-server/&lt;/a&gt; ), but there are several ways to deal with it in D365FO&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create new indexes – you can create new indexes, to help SQL server always choose the best plan. This often works only if you have conditions to one table only&lt;/li&gt;
&lt;li&gt;Use the &lt;strong&gt;sp_create_plan_guide&lt;/strong&gt; command to force the actual plan – using this option creates a big admin overhead as you need to maintain these created plans. If you add a new field to the AX table you will need to change all the plan guides in which this table is used&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;forceLiterals&lt;/strong&gt; hint –you send actual values to the SQL Server and it chooses the best plan for these values. The overhead is that the plan will need to be compiled every time&lt;/li&gt;
&lt;li&gt;Use index hint (new feature in PU23) – it is the same as &lt;strong&gt;sp_create_plan_guide&lt;/strong&gt; but with no admin overhead&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;overhead-of-forceliterals-usage&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#overhead-of-forceliterals-usage&quot; aria-label=&quot;overhead of forceliterals usage permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Overhead of forceLiterals usage&lt;/h2&gt;
&lt;p&gt;Let’s check, what is the overhead of &lt;strong&gt;forceLiterals&lt;/strong&gt; usage(I have tested this on medium size AX2012 DB and on D365 8.1 demo, time proportions were the same in both cases)&lt;/p&gt;
&lt;p&gt;For the test let’s use the following job. It calculates actual item quantity for the warehouse.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;dev_testForceLiterals&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Args&lt;/span&gt; _args&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;InventTable&lt;/span&gt;         inventTable&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;InventDim&lt;/span&gt;           inventDim&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;InventSum&lt;/span&gt;           inventSum&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;InventLocation&lt;/span&gt;      inventLocation&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;/span&gt;                 curCount&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; maxCount &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;System&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Diagnostics&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Stopwatch&lt;/span&gt; stopwatch &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;System&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Diagnostics&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Stopwatch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;real&lt;/span&gt;                         timeMs&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        stopwatch&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Start&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;select&lt;/span&gt; inventTable
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;select&lt;/span&gt; inventLocation
            &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;token comment&quot;&gt;//select forcePlaceholders  //case 1&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;select&lt;/span&gt; forceLiterals        &lt;span class=&quot;token comment&quot;&gt;//case 2&lt;/span&gt;
                    &lt;span class=&quot;token function&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;AvailPhysical&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; inventSum
                &lt;span class=&quot;token keyword&quot;&gt;group&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;by&lt;/span&gt; ItemId
                &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;inventSum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ItemId &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; inventTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ItemId &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;
                      inventSum&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Closed &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;
            exists &lt;span class=&quot;token keyword&quot;&gt;join&lt;/span&gt; inventDim
                &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;inventDim&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;inventDimId      &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; inventSum&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;InventDimId &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;
                      inventDim&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;InventLocationId &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; inventLocation&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;InventLocationId &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;
                      inventDim&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;InventSiteId     &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt;   inventLocation&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;InventSiteId&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

                curCount&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;curCount &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; maxCount&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;curCount &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; maxCount&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        stopwatch&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Stop&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        timeMs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; stopwatch&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get_ElapsedMilliseconds&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;strFmt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Time for %1 lines: %2 sec&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; curCount&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; timeMs &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Before each run we will clear SQL plan cache using the following command (note that this command only clears plan cache, not the data cache, all used tables are still located in the memory)&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;sql&quot;&gt;&lt;pre class=&quot;language-sql&quot;&gt;&lt;code class=&quot;language-sql&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;DBCC&lt;/span&gt; FREEPROCCACHE
GO&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To calculate memory consumption after each run we will use the following statement&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;sql&quot;&gt;&lt;pre class=&quot;language-sql&quot;&gt;&lt;code class=&quot;language-sql&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;SELECT&lt;/span&gt; objtype &lt;span class=&quot;token keyword&quot;&gt;AS&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;CacheType&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; count_big&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;AS&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Total Plans&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cast&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;size_in_bytes &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;decimal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;18&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1024&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1024&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;AS&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Total MBs&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;avg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;usecounts&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;AS&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Avg &lt;span class=&quot;token keyword&quot;&gt;Use&lt;/span&gt; Count&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cast&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;CASE&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;WHEN&lt;/span&gt; usecounts &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;THEN&lt;/span&gt; size_in_bytes &lt;span class=&quot;token keyword&quot;&gt;ELSE&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;END&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;decimal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;18&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1024&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1024&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;AS&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Total MBs &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;USE&lt;/span&gt; Count &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;CASE&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;WHEN&lt;/span&gt; usecounts &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;THEN&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;ELSE&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;END&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;AS&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Total Plans &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;USE&lt;/span&gt; Count &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;FROM&lt;/span&gt; sys&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;dm_exec_cached_plans
&lt;span class=&quot;token keyword&quot;&gt;GROUP&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;BY&lt;/span&gt; objtype
&lt;span class=&quot;token keyword&quot;&gt;ORDER&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;BY&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Total MBs &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;USE&lt;/span&gt; Count &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;DESC&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;forceplaceholders-results&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#forceplaceholders-results&quot; aria-label=&quot;forceplaceholders results permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;strong&gt;forcePlaceholders results&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;For the first and for the second executions, time was the same&lt;/p&gt;
&lt;p&gt;First run: 8,51 sec&lt;/p&gt;
&lt;p&gt;Second run: 8,51 sec&lt;/p&gt;
&lt;p&gt;Memory consumption:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 589px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/597344789078096b35888c33e0ba9c7f/b1665/Memory1.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 25.71428571428572%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAYAAABFA8wzAAAACXBIWXMAAAsTAAALEwEAmpwYAAABGUlEQVR42k2P60rDQBSE+/7v4g8fQNA/IsXWaluhWtomzea2uZnLbpJN87kJCA4Mey7D7JlFWZYIzyMIInw/5OK4SJnw/rGda8cyjGKCMGK3++R6FbM2STJbe4R2LoRPHCd0XceiKAoSGVH9FGitGIYB0/e4zpnKfqZUw4RWa3zvSm93E4wxtG3Lf4zjyCLLcx5XB54PkvU5Zx927IXi/umN12PKPmg55rA6pdw9LNkKzTGDnWjYuDXfKRzkyFcyoo01TNOUkyPw4wJZ1JR6IK80y/U7F1/a3qAMBDLnZb0hLTVWQmY1RdPS2IPrbpw53KxhXddk1lQpG9f09uybjdVxdS9UVTn3E5Sqce1s2k2YXmP6v7Azp8i/uml6U7oV5V8AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;1544426361493&quot;
        title=&quot;&quot;
        src=&quot;/static/597344789078096b35888c33e0ba9c7f/b1665/Memory1.png&quot;
        srcset=&quot;/static/597344789078096b35888c33e0ba9c7f/4edbd/Memory1.png 175w,
/static/597344789078096b35888c33e0ba9c7f/13ae7/Memory1.png 350w,
/static/597344789078096b35888c33e0ba9c7f/b1665/Memory1.png 589w&quot;
        sizes=&quot;(max-width: 589px) 100vw, 589px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h3 id=&quot;forceliterals-results&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#forceliterals-results&quot; aria-label=&quot;forceliterals results permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;strong&gt;forceLiterals results&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;First run: 66,57 sec&lt;/p&gt;
&lt;p&gt;Second run: 9,60 sec&lt;/p&gt;
&lt;p&gt;Memory consumption:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 557px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/94625a0848f0b7b00e040d48e1e12da0/30d00/Memory2.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 25.71428571428572%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAYAAABFA8wzAAAACXBIWXMAAAsTAAALEwEAmpwYAAAA+0lEQVR42lWPyW6DMBRF+f8P6rqLLrrpgqQSCVNIbQaXQRgMZjDc2lZA6pUsebg679gRvUAcx0jTDEWRIwxDkLzE24eL96870owhz3LUTWN7l8sVlFKUZQXGCgRBaPdHx+m6Dr+MQU4T+r7HMAyQs8Kn68P1f9DyDvu+wyTPMhBCzvM4jrZvctw5LW8RR7GdwjmHEIN5hfd9tQbzNEOtypbjKMLtdseRXst0WsJk2zYLdbgGMm04Sol1WbDopZRCpIfUdXOeTSgleCQJXjKYJollXU9DCxRCgBKKtuW6MGGeNUCXPM9DWVUY9ZfWl+HzmcAPgxMopQEu/4B/KXV8/SqS1aQAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;1544426462937&quot;
        title=&quot;&quot;
        src=&quot;/static/94625a0848f0b7b00e040d48e1e12da0/30d00/Memory2.png&quot;
        srcset=&quot;/static/94625a0848f0b7b00e040d48e1e12da0/4edbd/Memory2.png 175w,
/static/94625a0848f0b7b00e040d48e1e12da0/13ae7/Memory2.png 350w,
/static/94625a0848f0b7b00e040d48e1e12da0/30d00/Memory2.png 557w&quot;
        sizes=&quot;(max-width: 557px) 100vw, 557px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;During the execution there was almost 100% utilization for 1 CPU core&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 289px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/7d9aec4697bce5c5a9ceeaec4e86a5dd/c969a/CPU2.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 66.28571428571429%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAAAsTAAALEwEAmpwYAAACV0lEQVR42k1TW5LaMBD0PVM53B4hOQT5SLYq2QrLsgEHDBjbsi3kl+QXnR4BtXG5pfFopuclB0qlWCwW+L16w+Ppe4tMKaRZBl1q5HmOc3KG1hppmhIZMu5ZrlAUBZIk9bbjOCKozAXH4xFRFMFZi945XHSJzeYP4vh0d0igVAZjDMqyQEmdpk1OQl2WUJlCGIboug5B60akZY1UV0jKCrHSUJcaJ+ry2sJeATtd0QnGK+p+xsVNXv7AjIT+dpiYIQntMIM6DHQS8EWsLap9jOGcwiY57HaHIcmQNz0S42g3ewI7Tugpt+Ro+jthy4j9eDNwxED5VHYwA9DuI9RfvsJJb3lWtCSsnCfp/iOsLHmEsCGZZOhIcmVmopzmK7PoIe2YSFQ8PcH9ePaybgcoZim2Exd7z0z8PaEh8zZr8JbUvpSfkfb4dTDYFy1O7Yz1+x7pp884rEJsmfbrucKeFRx1h5fY4Jn267SGsQOCghF3RYczycQovlhf0ooBtnmLgyao+/vtO5brCC9Z64MfLp23P7DXsbEIGVzaF9T95KckYKUYuMgupFIKRY+K5xI0oqOULI8MZhR7yr5kmbIsGQ0E0hPfSxrEJDSMKA4C3fCyMxOpQGwdr4JkLkFvU55uhA2d9nnnr8mJWLOcgg6H0kLaIZOUqxSxLTvV+gwleyl3K9++lxY1hyuTDnQ3YnWu8U6i5clgFVcer0RIh1A12Nz7FnJ425TfqsOS56KXXossHJJcMM8z79eAcWK/WPLEXXRS9szvxy7/qdjIuciic/xNBQ87ef4B3MPh6TuTpK4AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;1544426512418&quot;
        title=&quot;&quot;
        src=&quot;/static/7d9aec4697bce5c5a9ceeaec4e86a5dd/c969a/CPU2.png&quot;
        srcset=&quot;/static/7d9aec4697bce5c5a9ceeaec4e86a5dd/4edbd/CPU2.png 175w,
/static/7d9aec4697bce5c5a9ceeaec4e86a5dd/c969a/CPU2.png 289w&quot;
        sizes=&quot;(max-width: 289px) 100vw, 289px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;If we present these values on a graph:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 624px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/5fb0a0701abfe77b7fa1d69228b86a11/39c09/Compare1.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 47.42857142857142%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAAsTAAALEwEAmpwYAAABHElEQVR42pVSwUoDMRDN9+iH9QtU1IqFUgRPogjFUxHR2lsvQhGkePDQm3rSg5f2VuoebN1skpnnJLtppdCuBiYvMwkv816inHOIQURYNbgMOV8pP9ksg5GCm0zAx0fgeg1UOwAfVteHP7O7Db5o5sTCEQiNMTlhksCen8KenYDb1+Dbm3lQkdPvvNMGXV2C73sLQt+qTlNokWzHY2BnC9yog6VWaPmfZO9dpjVY8HP6hb1eF62nPsTQ3FOp+zWXYSQ01iIVQgiOZlNsDB5QeXsOm4558Six0xJUWshm6Tc4MxhKh5uPd6i8DlYSll2gvCxHLniVyGvvv7+gNfoImyS1v3YWv5xaujYEFf75wy6ieLWM4cuJVUFNkf8A+XGoa/Be8u0AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;1544426563576&quot;
        title=&quot;&quot;
        src=&quot;/static/5fb0a0701abfe77b7fa1d69228b86a11/39c09/Compare1.png&quot;
        srcset=&quot;/static/5fb0a0701abfe77b7fa1d69228b86a11/4edbd/Compare1.png 175w,
/static/5fb0a0701abfe77b7fa1d69228b86a11/13ae7/Compare1.png 350w,
/static/5fb0a0701abfe77b7fa1d69228b86a11/39c09/Compare1.png 624w&quot;
        sizes=&quot;(max-width: 624px) 100vw, 624px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Memory consumption is about 100KB per saved plan. So in forceLiterals case, it requires a 500MB memory per 5k SQL statements. This is a large amount of memory just for the plan cache.&lt;/p&gt;
&lt;h2 id=&quot;summary&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#summary&quot; aria-label=&quot;summary permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Summary&lt;/h2&gt;
&lt;p&gt;Plan compilation is still a complex task, that consumes a lot of CPU. This 1-minute difference between the first run of &lt;strong&gt;forceLiterals&lt;/strong&gt; and &lt;strong&gt;forcePlaceholders&lt;/strong&gt; is utilizing one CPU core for 100%. For the &lt;strong&gt;forceLiterals&lt;/strong&gt; case, time to build a plan is 6 times longer than the time to fetch the actual data. Also, notice a difference between the second run of &lt;strong&gt;forceLiterals&lt;/strong&gt; and &lt;strong&gt;forcePlaceholders&lt;/strong&gt;. It is about a second – this time is a time server spends doing lexical parsing of SQL statement.&lt;/p&gt;
&lt;p&gt;For single SQL statements (or statement that executes once per document header) &lt;strong&gt;forceLiterals&lt;/strong&gt; can provide some benefit, but if we have a large number of users who are working with different items and different dimensions &lt;strong&gt;forceLiterals&lt;/strong&gt; usage for the frequent SQL requests can affect overall SQL server performance (both for memory consumption and CPU), so we need to avoid &lt;strong&gt;forceLiterals&lt;/strong&gt; usage on a &quot;per line&quot; level. And the new “index hint” feature can help us in this.&lt;/p&gt;</content:encoded></item></channel></rss>