Skip to content

Instantly share code, notes, and snippets.

@tshego3
Last active May 13, 2025 21:38
Show Gist options
  • Save tshego3/269527599851636eb0d3aae27bfa63b7 to your computer and use it in GitHub Desktop.
Save tshego3/269527599851636eb0d3aae27bfa63b7 to your computer and use it in GitHub Desktop.
D365 F&O Development Processes

D365 F&O Development Processes

Tips & Tricks

VM shutdown

  • To minimize the chance of your database going into an inconsistent state, please ensure you shut down your VM from within the VM first before shutting down your computer. This only applies to scenarios where the VM is hosted on your computer.

Useful Links

  • Azure https://portal.azure.com/
  • Postman https://www.postman.co/
  • For viewing LCS https://sa.lcs.dynamics.com/
  • For getting Public IP with Cloudflare https://speed.cloudflare.com/ OR https://radar.cloudflare.com/ip
  • For getting Public IP with CMD OR PowerShell nslookup myip.opendns.com. resolver1.opendns.com
  • For viewing a table use https://{d365ffo-url}/?cmp={company}&mi=SysTableBrowser&tableName=placeholder
  • For editing a table use https://{d365ffo-url}/?cmp={company}&mi=DEVSysTableBrowser&TableName=placeholder
  • For executing a runnable class & SysOperation use https://{d365ffo-url}/?cmp={company}&mi=SysClassRunner&cls=placeholder
  • For viewing system errors use https://{d365ffo-url}/?cmp={company}&mi=DEVCSXppCallStackTable
  • For executing a sql statement use https://{d365ffo-url}/?cmp={company}&mi=DEVSQLQueryExecute

Setup default model in VS

C:/Users/%USERNAME%/Documents/Visual Studio Dynamics 365/DynamicsDevConfig.xml/<DefaultModelForNewProjects>{ModelPrefix}</DefaultModelForNewProjects>

Debug UAT database

https://learn.microsoft.com/en-us/dynamics365/fin-ops-core/dev-itpro/database/dbmovement-scenario-debugdiag

Install Powershell D365 tools

Install-Module -Name d365fo.tools

Various Commands

  • Run Db sync on one module

    • Run Powershell command Invoke-D365DbSyncModule -Module {ModelPrefix} OR Invoke-D365DbSync
  • RDP session getting disconnected continuously or hanging

    • Login from another server - e.g., remote into the AX dev server and then remote into your D365 server from there
  • Server continuously restarting/Windows license expired

    • Run CMD command slmgr /rearm
  • Getting a error on a DLL while doing a get latest; run the script:

     NET STOP "MR2012ProcessService"
     NET STOP "DynamicsAxBatch"
     NET STOP "Microsoft.Dynamics.AX.Framework.Tools.DMF.SSISHelperService.exe"
     NET STOP "W3SVC"
     PAUSE
     NET START "MR2012ProcessService"
     NET START "DynamicsAxBatch"
     NET START "Microsoft.Dynamics.AX.Framework.Tools.DMF.SSISHelperService.exe"
     NET START "W3SVC"
     PAUSE
  • Apply the platform update package to your development environment:

    • Install the deployable package
       # Rerun Step ID 1:
       AXUpdateInstaller.exe execute -runbookid=OneBoxDev -rerunstep=1
      
       # Set step complete, for Step ID 1:
       AXUpdateInstaller.exe execute -runbookid=OneBoxDev -setstepcomplete=1
Various Documentation
  • General Information

    • {company}/Sales and marketing/Common/Contacts/All contacts
    • {company}/Sales ledger/Common/Customers/All customers
    • {company}/Purchase ledger/Vendors/All vendors
    • {company}/Strategic asset management/Common/Contract planning/<Contract per specific status == Active>/Registration/Serial Number
    • {company}/System administration/Area page/Periodic/Services and Application Integration Framework/History/{Select a <Port name>}/Document logs/{Select <Process step>}/{Select <View XML>}
    • {company}/System administration/Area page/Periodic/Services and Application Integration Framework/Exceptions/{Select a <Exception message>}
    • {company}/System administration/Area page/Setup/Services and Application Integration Framework/{Select <Inbound ports> or <Outbound ports}/{Select a <Port name>}
    • {company}/System administration/Area page/Setup/System/Azure integration
    • {company}/Organisation administration/Area page/Setup/Document management/Output document parameters
    • Batch Jobs: {company}/System administration/Area page/Enquires/Batch Jobs/<Job description>
    • Customer Transactions: {company}/Sales ledger/Common/Customers/All customers/[Lookup & Select customer]/[Click Transactions on the ribbon]
    • Add Customer Relation To User: {company}/System administration/Common/Users/Users then click on Relations under the Set Up button group and add the customer relation to the user and make it active.
    • View Document Type Library Details:
      • {company}/Organisation administration/Area page/Setup/Document management/Document types/Output document parameter/<Right-Click Category Id>/<Click View details>
      • {company}/ECM/Setup/ECM Parameters/SharePoint site collections
  • Use F12 to get Table and Field information

  • Dynamics AX Case Service Status OR Service Process Status Reset/Modification {company}/Case management/Area page/Setup/Case Update/Case admin update/{On the Overview tab, search for a case by Case ID and pick the detected case}/{Select the service on the Service Details tab, then click "Update Service Status" to update the service. To edit the status of a service process, go to the Process subtab and pick the process, then click the "Edit Process" button; if the modified service process is "Not started," ensure that the preceding process is "In progress". Alternatively, the process action parameters can be modified by selecting the "Update from setup" button, which will utilize the most recent list version of the process action parameters.}

  • Changing the URI of an AIF portal that has been disabled: Navigate to the AifPort table on path: AOT/Data Dictionary/Tables/AifPort/{Select the port name}/{Deselect the enabled field}, then change the URI of the inbound port using the drop-down on path: {company}/System administration/Area page/Setup/Services and Application Integration Framework/{Select the <Inbound port>/{Select the port name}. Sometimes the deployment/activation of the ports hangs, so confirming the files are deployed on the path, C:\Program Files\Microsoft Dynamics AX\60\AifWebServicesTest, and restarting the AOS can be sufficient.

  • To run a batch job in D365:

    • Navigate to System administration > Enquiries > Batch jobs.
    • Select the job.
    • Set the Scheduled start date/time to when you want the job to begin.
    • Under Recurrence, set it to run once and specify the end date as the same day.
    • Under Change status, if the job status is Ended, you may need to create a new execution by setting its status to Waiting so that it re-enters the queue for execution.
  • To modify the WCF/AIF-Port configuration for a port, navigate to:

    • Azure Function app time-out duration System Administration > Setup > Services and Application Integration Framework > Inbound Ports. Choose the port you wish to edit, ensuring it is deactivated first. Next, click on Configure, proceed to Bindings, and adjust the timeout values as needed.
Database Documentation
-- Index Hint
SELECT DPT.RecId ,DPT.PartyNumber ,CP.RecId ,CP.ContactPersonId ,CP.ContactForPARTY ,LEA.RecId ,LEA.[Locator] ,* 
FROM DirPartyTable AS DPT WITH(INDEX(I_2303RECID,I_2303PARTYNUMBERIDX))
LEFT OUTER JOIN LogisticsElectronicAddress AS LEA ON LEA.RecId = DPT.PrimaryContactEmail
LEFT OUTER JOIN ContactPerson AS CP ON CP.Party = DPT.RecId
WHERE LEA.[Locator] = N'Email' AND DPT.PartyNumber = N'0';

-- Paginate Results in T-SQL 
SELECT * FROM CASEDETAILBASE ORDER BY RECID OFFSET 1000 ROWS FETCH NEXT 1000 ROWS ONLY;
	
-- Find a Table Name by TABLEID (REFTABLEID) in Dynamics AX
SELECT [NAME] FROM SQLDICTIONARY WHERE TABLEID = <TABLEID> AND FIELDID = 0;

-- Iterate through a list and split it using a comma as the separator
DECLARE @CURRENTPOSITION NVARCHAR(MAX);
DECLARE @LISTTABLE TABLE (
    COLUMN1 NVARCHAR(MAX),
    COLUMN2 NVARCHAR(MAX),
    COLUMN3 NVARCHAR(MAX)
);
DECLARE LISTCURSOR CURSOR FOR
WITH [LIST] AS
(
	SELECT VALUE
	FROM STRING_SPLIT(N'INDEX1,INDEX2,INDEX3,INDEX4,INDEX5', N',')
)
SELECT [VALUE]
FROM [LIST];
OPEN LISTCURSOR;
FETCH NEXT FROM LISTCURSOR INTO @CURRENTPOSITION;
WHILE @@FETCH_STATUS = 0
	BEGIN
		BEGIN TRY
			INSERT INTO @LISTTABLE VALUES (@CURRENTPOSITION, N'COLUMN2', N'COLUMN3');
			-- INSERT INTO @LISTTABLE SELECT COLUMN1, COLUMN2, COLUMN3 FROM TABLE WHERE COLUMN1 = @CURRENTPOSITION AND COLUMN2 = N'1000';
			FETCH NEXT FROM LISTCURSOR INTO @CURRENTPOSITION;
		END TRY
		BEGIN CATCH
			PRINT CONCAT(N'ERROR NUMBER: ', ERROR_NUMBER(), N' ', N'CURRENT POSITION: ', @CURRENTPOSITION);
		END CATCH
	END;
CLOSE LISTCURSOR;
DEALLOCATE LISTCURSOR;
SELECT * FROM @LISTTABLE;
Caesar Encryption Tutorial
Tutorial X++
private static str str2Caesar(str _source, int64 _shift = 1)
{ 
    int maxChar = 65535;
    int minChar = 0;

    System.String _str   = _source;
    System.Char[] buffer = _str.ToCharArray();

    for (int i = 0; i < buffer.Length; i++)
    {
	int shifted = System.Convert::ToInt32(buffer.GetValue(i)) + _shift;

	if (shifted > maxChar)
	{
	    shifted -= maxChar;
	}
	else if (shifted < minChar)
	{
	    shifted += maxChar;
	}

	buffer.SetValue(System.Convert::ToChar(shifted), i);
    }

    str ret = new System.String(buffer);

    return ret;
}	
Tutorial C#
private static string StringToCaesar(string source, Int16 shift = -1)
{
    var maxChar = Convert.ToInt32(char.MaxValue);
    var minChar = Convert.ToInt32(char.MinValue);

    var buffer = source.ToCharArray();

    for (var i = 0; i < buffer.Length; i++)
    {
	var shifted = Convert.ToInt32(buffer[i]) + shift;

	if (shifted > maxChar)
	{
	    shifted -= maxChar;
	}
	else if (shifted < minChar)
	{
	    shifted += maxChar;
	}

	buffer[i] = Convert.ToChar(shifted);
    }

    return new string(buffer);
}
D365FO – AX – X++ Various Documentation
  • To resolve the error, during Team Explorer - Get and Map: The path C:\AOSService\PackagesLocalDirectory is already mapped in workspace [WorkSpaceName]\[E-Mail_Address]

    • Delete the contents of this folder: C:\Users\%UserName%\AppData\Local\Microsoft\Team Foundation\8.0\Cache
    • OR C:\Users\%UserName%\AppData\Local\Microsoft\VisualStudio\16.xxx
    • OR 17.xxx\ComponentModelCache
  • To edit a checked-out object by another developer using AOT, open table "DEVToolsLockTable" and add a "x" at the end of the checked-out object name, restart client, complete changes, then when checking in, make sure to remove the "x" and on Deployment AOS, remove changes you did not make, as per deployment code version control standards.

  • X++ and C# syntax differences

    • X++: System.Net.WebRequest httpRequest = System.Net.WebRequest::Create(fileUri);
    • C#: System.Net.WebRequest httpRequest = System.Net.WebRequest.Create(fileUri);
  • Delete the sub-folders found under your TFS profile here: %localappdata%\Microsoft\Team Foundation\3.0\Cache

  • All AX Tables: {company}/System administration/Area page/<Data export/import>/<Definitions groups>

  • AX Lookup MultiSelect Dialog: AOT/Classes/tutorial_LookupMultiSelectDialog

  • Switch off the CIL:

<Any Workspace>/Tools/Options/Development/<Execute business operations in CIL:>/<uncheck the checkbox>
  • Clear AX usage data:
<Any Workspace>/Tools/Options/Development/<click Usage data on the action plane>/<click All usage data on the pop-up-form>/<select all records and delete>
  • Add .NET Class Library Path:
C:\Program Files\Microsoft Dynamics AX\60\Server\MicrosoftDynamicsAX\bin 
C:\Program Files (x86)\Microsoft Dynamics AX\60\Client\Bin
  • Another configuration is needed, the Table Name parameter needs to be filled in, so we don't have to create the record. This is the default way for the Portal, on {company}/Case management/Area page/Setup/Services/Service table/[Seleceted service]/Service details/Table name/[Populate table name]. The prerequisites are that the field CaseServiceRecId must exist on the table as intended, and then the initValue is executed to pre-populate any values it can.

  • DevOps find SQL file-filters:

file:{Name} ext:sql path:$/RepoName/Trunk/Development/Metadata/Model/Model/AxResource/ResourceContent/Data/
  • AX 2012 Error: Could not load type 'Dynamics.Ax.Application.ClassName' from assembly 'Dynamics.Ax.Application, Version=0.0.0000.000, Culture=neutral, PublicKeyToken=null'.:
    • To resolve the error, attempt to compile the ClassName and execute an Incremental CIL.
Faulted: System.OperationCanceledException: AIF service group not activated.  Service group: <ServiceGroupName>.  Error: Could not load type 'Dynamics.Ax.Application.<ClassName>' from assembly 'Dynamics.Ax.Application, Version=0.0.0000.000, Culture=neutral, PublicKeyToken=null'. ---> System.TypeLoadException: Could not load type 'Dynamics.Ax.Application.<ClassName>' from assembly 'Dynamics.Ax.Application, Version=0.0.0000.000, Culture=neutral, PublicKeyToken=null'.
D365FO – AX – X++ – Get All AOT Resources

https://pedrotornich.com/a/2019/09/26/use-d365fo-metadata-api-in-net/ https://stackoverflow.com/questions/45598166/how-to-get-aot-objects-tables-for-example-belongs-to-a-model-in-ax7 || https://stackoverflow.com/a/45712653

// C#
	
// Required references:
// C:\AOSService\webroot\bin\Microsoft.Dynamics.ApplicationPlatform.Environment.dll
// C:\AOSService\webroot\bin\Microsoft.Dynamics.AX.Metadata.dll
// C:\AOSService\webroot\bin\Microsoft.Dynamics.AX.Metadata.Core.dll
// C:\AOSService\webroot\bin\Microsoft.Dynamics.AX.Metadata.Storage.dll
	
using Microsoft.Dynamics.AX.Metadata.Storage;
using Microsoft.Dynamics.AX.Metadata.Storage.Runtime;
using System;
using System.Diagnostics;

namespace ConsoleApp
{
    public class Program
    {
        public static void Main(string[] args)
        {
            try
            {
                var environment = Microsoft.Dynamics.ApplicationPlatform.Environment.EnvironmentFactory.GetApplicationEnvironment();
                var runtimeConfiguration = new RuntimeProviderConfiguration(environment.Aos.PackageDirectory);
                var metadataProvider = new MetadataProviderFactory().CreateRuntimeProviderWithExtensions(runtimeConfiguration);
                var aotResources = metadataProvider.Resources.ListObjectsForModel("ModelPrefix");
                foreach (var resource in aotResources)
                {
                    Debug.WriteLine(string.Concat("Resource Name: ", resource));
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
        }
    }
}
// X++ - AX2012
	
static void getAllAOTResources(Args _args)
{
    #AOT
    TreeNode                treeNode;
    TreeNode                resourcesNode;
    TreeNodeIterator        iterator;

    // resourcesNode        = TreeNode::findNode(@"\Resources");
    resourcesNode           = TreeNode::findNode(#ResourcesPath);
    iterator                = resourcesNode.AOTiterator();

    while (iterator.next())
    {
        treeNode = iterator.next();
        info(treeNode.AOTname());
    }
}

// X++ - D365
	
public final class GetAllAOTResources
{
    public static void main(Args _args)
    {
        var environment                 = Microsoft.Dynamics.ApplicationPlatform.Environment.EnvironmentFactory::GetApplicationEnvironment();
        var runtimeConfiguration        = new Microsoft.Dynamics.AX.Metadata.Storage.Runtime.RuntimeProviderConfiguration(environment.get_Aos().get_PackageDirectory());
        var metadataProviderFactory     = new Microsoft.Dynamics.AX.Metadata.Storage.MetadataProviderFactory();
        var metadataProvider            = metadataProviderFactory.CreateRuntimeProvider(runtimeConfiguration);
        var aotResources                = metadataProvider.Resources.ListObjectsForModel("ModelPrefix");

        System.Collections.IEnumerator enumerator = aotResources.GetEnumerator();
        while (enumerator.MoveNext()) 
        { 
            str resourceName = enumerator.Current;

            if (strStartsWith(resourceName, "potentialStart") || strStartsWith(resourceName, "potentialStart") || strStartsWith(resourceName, "potentialStart"))
            {
                ResourceNode        resourceNode        = SysResource::getResourceNode(resourceName);

                if(resourceNode && strEndsWith(resourceNode.filename(), "potentialEnd"))
                {
                    BinData         binData             = new BinData();
                    container       resourceNodeData    = SysResource::getResourceNodeData(resourceNode);

                    binData.setData(resourceNodeData);
                    str result = binData.getStrData();
                    info(result);
                }
            }
        }
    }
}
D365FO – AX – X++ – JSON Construct Tutorial
static void jsonConstructTutorial(Args _args)
{
    System.IO.StringWriter                              strWriter;
    Newtonsoft.Json.JsonTextWriter                      jsonWriter;
    System.Exception                                    exception;
    str                                                 jsonBody;
    Map                                                 jsonBodyMap;
    MapEnumerator                                       jsonBodyEnumer;
    str                                                 jsonBodyMapName;
    str                                                 jsonBodyMapValue;

    // JSON Array Deconstruct Tutorial - Begin
    int                                                 i, arrayLength;
    str                                                 txtName, txtModel;
    Newtonsoft.Json.Linq.JObject                        jObject;
    Newtonsoft.Json.Linq.JToken                         sName, sModel;
    // JSON Array Deconstruct Tutorial - End

    // JSON Array Deconstruct Tutorial - Begin
    str jsString = '[{"Name": "BMW", "Model": "325IS"}, {"Name": "VW", "Model": "City Golf"}]';
    Newtonsoft.Json.Linq.JArray jArry = Newtonsoft.Json.Linq.JArray::Parse(jsString);
    // JSON Array Deconstruct Tutorial - End

    // JSON Deconstruct Tutorial - Begin
    str jsonString = '{"Name": "Jack Moose", "Age": 30, "Cars": [{"Name": "BMW", "Model": "325IS"}, {"Name": "VW", "Model": "City Golf"}]}';
    Newtonsoft.Json.Linq.JObject jObjct = Newtonsoft.Json.Linq.JObject::Parse(jsonString);
    Newtonsoft.Json.Linq.JToken jToken = jObjct.get_Item('Cars');
    Newtonsoft.Json.Linq.JArray jArray = jToken as Newtonsoft.Json.Linq.JArray;
    Newtonsoft.Json.Linq.JObject subObjct = jArray.get_First();
    Newtonsoft.Json.Linq.JToken subName = subObjct.get_Item('Name');
    Newtonsoft.Json.Linq.JToken subModel = subObjct.get_Item('Model');
    info(subModel.ToString());
    // JSON Deconstruct Tutorial - End

    // JSON Array Deconstruct Tutorial - Begin
    // Loop through each item in the array and log the "Name" and "Model" elements
    arrayLength = jArry.get_Count();
    for (i = 0; i < arrayLength; i++)
    {
        jObject = jArray.get_Item(i);
        sName = jObject.get_Item('Name');
        sModel = jObject.get_Item('Model');
        txtName = sName.ToString();
        txtModel = sModel.ToString();
        info(strFmt("Name: %1 Model: %2", txtName, txtModel));
    }
    // JSON Array Deconstruct Tutorial - End

    // JSON Construct Tutorial
    try
    {
        strWriter       = new System.IO.StringWriter();
        jsonWriter      = new Newtonsoft.Json.JsonTextWriter(strWriter);
        jsonBody        = strMax();

        jsonBodyMap = new Map(Types::String, Types::String);
        jsonBodyMap.insert("ScopeEmail", "email");
        jsonBodyMap.insert("ScopeOpenId", "openid");
        jsonBodyMap.insert("ScopeOfflineAccess", "offline_access");
        jsonBodyMap.insert("ScopeImap", "https://outlook.office.com/IMAP.AccessAsUser.All");
        jsonBodyMap.insert("ScopeSmtp", "https://outlook.office.com/SMTP.Send");
        jsonBodyMap.insert("SmtpHost", "smtp.office365.com");
        jsonBodyMap.insert("SmtpPort", "587");
        jsonBodyMap.insert("ImapHost", "outlook.office365.com");
        jsonBodyMap.insert("ImapPort", "993");
        jsonBodyMap.insert("TenantId", "D6BBC893-4199-43C4-BA1B-3F67FEA3E75A");
        jsonBodyMap.insert("AppId", "77ca9202-414b-47fb-a1ba-5d5a48207962");
        jsonBodyMap.insert("AppSecret", "Fbr8Q~hGlRn8SJWGuvDc6EnfcsJfUP2VpP2nCcuW");
        jsonBodyMap.insert("Username", "[email protected]");
        jsonBodyMap.insert("Password", "Password1");

        jsonWriter.WriteStartObject();

            jsonBodyEnumer = jsonBodyMap.getEnumerator();
            while (jsonBodyEnumer.moveNext())
            {
                jsonBodyMapName = jsonBodyEnumer.currentKey();
                jsonBodyMapValue = jsonBodyEnumer.currentValue();

                jsonWriter.WritePropertyName(jsonBodyMapName);
                jsonWriter.WriteValue(jsonBodyMapValue);
            }

            jsonWriter.WritePropertyName("Email");
            jsonWriter.WriteStartObject();
                jsonWriter.WritePropertyName("To");
                jsonWriter.WriteValue("[email protected]");
                jsonWriter.WritePropertyName("Subject");
                jsonWriter.WriteValue("Test Email");
                jsonWriter.WritePropertyName("Body");
                jsonWriter.WriteValue("Hello world!");
            jsonWriter.WriteEndObject();

        jsonWriter.WriteEndObject();
        jsonBody = strWriter.ToString();
        info(jsonBody);
    }
    catch
    {
        error("@EXD32721");
        exception = ClrInterop::getLastException();
        if (exception != null)
        {
            exception = exception.get_InnerException();
            if (exception != null)
            {
                error("\n" +  clr2XppStr(exception.ToString()));
            }
        }
    }
}
D365FO – AX – X++ – Tutorial: reread, research
[ExtensionOf(formcontrolstr(LogisticsPostalAddress, RefreshForm))]
final class LogisticsPostalAddress_RefreshForm_FC_Extension
{
    void clicked()
    {
	// https://d365ffo.com/2021/04/02/d365ffo-ax-x-tutorial-refresh-reread-research-executequery-which-one-to-use/comment-page-1/
			
        FormRun                         formRun;
        FormControl                     formControl;
	// FormDataObject               formDataObject;
        FormDataSource                  formDataSource;

        next clicked();

	// formControl                  = this.formRun().design().controlName("FormControlName") as FormControl;
	// formControl                  = this.formRun().design().controlName(formControlStr(FormName, FormControlName)) as FormControl;
        formControl                     = any2Object(this) as FormControl;
	// formDataObject               = any2Object(this) as FormDataObject;
        formRun                         = formControl.formRun().args().caller();
	// formRun                      = formDataObject.datasource().formRun();
        formDataSource                  = formRun.dataSource();

        formDataSource.reread();
        formDataSource.research();
	// formRun.doRefresh();
	// element.redraw();
	// element.reload();
    }
}
D365FO – AX – X++ – Check Interactive Session (Client)
static void checkInteractiveClientJob(Args _args)
{
    if (Global::hasGUI() == true)
    // if (xGlobal::clientKind() == ClientType::Client) // For AX 2012
    {
        info("This code is running on an interactive client.");
    }
    else
    {
        info("This code is not running on an interactive client.");
    }
}
D365FO – AX – X++ – Cross Company and Change Company Select
// https://learn.microsoft.com/en-us/dynamics365/fin-ops-core/dev-itpro/dev-ref/xpp-session-run-time-functions
static void crossCompanyCaseDetailExampleJob(Args _args)
{
    CaseDetailBase caseDetailBase;

    while select crossCompany * from caseDetailBase
        where caseDetailBase.CaseId == 'CASE123'
    {
        if (caseDetailBase)
        {
            changeCompany(caseDetailBase.dataAreaId)
	    // changeCompany(curExt()) 
            {
                select generateOnly firstOnly * from caseDetailBase
                    where caseDetailBase.CaseId == 'CASE123';

                info(strFmt("Case ID: %1, Company: %2", caseDetailBase.CaseId, caseDetailBase.dataAreaId));
                info(caseDetailBase.getSQLStatement());
            }
        }
    }
}
D365FO – AX – X++ – .NET API browser Dynamics.AX.Application SQL Statement class

https://learn.microsoft.com/en-us/dotnet/api/dynamics.ax.application.statement?view=dyn-finops-dotnet#remarks

static void example() 
{ 
    Connection Con; 
    Statement Stmt; 
    ResultSet R; 
    SqlStatementExecutePermission perm; 
    str sql = 'SELECT VALUE FROM SQLSYSTEMVARIABLES'; 
    Con = new Connection(); 
    Stmt = Con.createStatement(); 
    perm = new SqlStatementExecutePermission(sql); 
    perm.assert();

    // SELECT
    R = Stmt.executeQuery(sql);
    // R = stmt.executeQueryWithParameters(sql, null);
    while ( R.next() ) 
    { 
        print R.getString(1); 
    }

    // DELETE, INSERT or UPDATE
    // Stmt.executeUpdate(sql);
    // stmt.executeUpdateWithParameters(sql, null);
	
    CodeAccessPermission::revertAssert();
}
D365FO – AX – X++ – Update a OneBox DevTest environment to connect to the UAT database
<add key="DataAccess.Database" value="<example_axdb_fromAzure>" />
<add key="DataAccess.DbServer" value="<example_axdb_server.database.windows.net>" />
<add key="DataAccess.SqlPwd" value="<axdbadmin_password_from_LCS>" />
<add key="DataAccess.SqlUser" value="axdbadmin" />
<add key="DataAccess.AxAdminSqlPwd" value="<axdbadmin_password_from_LCS>" />
<add key="DataAccess.AxAdminSqlUser" value="axdbadmin" />
CMD - Execute SQL File
for %%G in (*.sql) do sqlcmd /S <server> /d <database> -E -i"%%G"
pause

for %%G in (*.sql) do sqlcmd /S <server> /d <database> -U <username> -P <password> -i"%%G"
pause
Placeholder
Placeholder
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment