July 31, 2023

SQL server log database size shrink

 1. Log in to SQL server wit Admin rights 

2. Use the below SQL commands in sequence

Note: Replace DBName with your log DB Name. EX(AXDB_Log)

  • Set the Database recovery mode to simple

            ALTER DATABASE DBName

            SET RECOVERY SIMPLE;

            GO

  • Shrink the DB

            DBCC SHRINKFILE (DBName, 1);

            GO

  • Set the database recover mode back to full

            ALTER DATABASE DBName

            SET RECOVERY FULL;

July 19, 2023

Certificate issues in D365FO Cloud hosted environment

 The problem with certificates is that they have an expiry date.

Since all Dynamics environments are deployed using LCS and the Cert used is owned by Microsoft we have limited ability to fix the issue on our own. This is why Microsoft built functionality into LCS to help us with this. To fix the issue, just look up the environment in LCS, click Maintain and select Rotate Secrets

The Cert you need to fix is the SSL Certificate

Simply click Rotate SSL Cert and wait for the process to finish. 

July 18, 2023

SQL Query to get Security roles, duties and privileges in D365FO

  • All security roles 

            Select Name as SecurityRoleName FROM SecurityRole;

  • All security roles to duties
    SELECT SECURITYROLE.Name as SecurityRole, SECURITYDUTY.NAME as Duty FROM SECURITYOBJECTCHILDREREFERENCES JOIN SECURITYROLE ON SECURITYOBJECTCHILDREREFERENCES.IDENTIFIER = SECURITYROLE.AOTNAME JOIN SECURITYDUTY ON SECURITYOBJECTCHILDREREFERENCES.CHILDIDENTIFIER = SECURITYDUTY.IDENTIFIER     WHERE SECURITYOBJECTCHILDREREFERENCES.OBJECTTYPE = 0 AND SECURITYOBJECTCHILDREREFERENCES.CHILDOBJECTTYPE = 1

order by SECURITYROLE.Name asc;

  • All security roles with privileges 
    SELECT SECURITYROLE.Name as SecurityRole, SECURITYPRIVILEGE.NAME as Privileges FROM SECURITYOBJECTCHILDREREFERENCES JOIN SECURITYROLE ON SECURITYOBJECTCHILDREREFERENCES.IDENTIFIER = SECURITYROLE.AOTNAME JOIN SECURITYPRIVILEGE
        ON SECURITYOBJECTCHILDREREFERENCES.CHILDIDENTIFIER = SECURITYPRIVILEGE.IDENTIFIER WHERE SECURITYOBJECTCHILDREREFERENCES.OBJECTTYPE = 0 AND SECURITYOBJECTCHILDREREFERENCES.CHILDOBJECTTYPE = 2 order by SECURITYROLE.Name asc;

 

  • All role-duty combination with privilege 
SELECT SECURITYROLE.Name as SecurityRole, SECURITYROLE.AOTNAME as RoleSystemName,     SECURITYDUTY.NAME AS Duty, SECURITYDUTY.IDENTIFIER as DutySystemName,     SECURITYPRIVILEGE.NAME as Privilege, SECURITYPRIVILEGE.IDENTIFIER as PrivilegeSystemName FROM SECURITYOBJECTCHILDREREFERENCES JOIN SECURITYROLE ON SECURITYOBJECTCHILDREREFERENCES.IDENTIFIER = SECURITYROLE.AOTNAME JOIN SECURITYDUTY ON SECURITYOBJECTCHILDREREFERENCES.CHILDIDENTIFIER = SECURITYDUTY.IDENTIFIER JOIN SECURITYOBJECTCHILDREREFERENCES Table1 on Table1.IDENTIFIER = SECURITYDUTY.IDENTIFIER JOIN SECURITYPRIVILEGE on Table1.CHILDIDENTIFIER = SECURITYPRIVILEGE.IDENTIFIER WHERE SECURITYOBJECTCHILDREREFERENCES.OBJECTTYPE = 0 AND SECURITYOBJECTCHILDREREFERENCES.CHILDOBJECTTYPE = 1 AND Table1.OBJECTTYPE = 1 AND Table1.CHILDOBJECTTYPE = 2 order by SECURITYROLE.Name asc;

July 06, 2023

Synchronize the table from Visual studio Project - D365 FO

From Visual studio project node, we can perform database synchronization either on a required table (or) on few tables bases on our requirement.

This could be very useful during on-premises environments package deployments because can drastically reduce the downtime.

In fact you can only synchronize the tables that you have actually modified rather than perform an entire synchronization

To perform a single table db sync simply Right click on project >>synchronize table. 

June 29, 2023

Move AOT elements between models

In order to move the objects from one model to another model, we opt to copy -paste from original model`s physical folder to destination model`s folder. This is feasible when we have limited objects. but if the object count is more, this approach is tedious.

So here is another way to move the objects from one model to another.
  1. Open the project which has all the objects.
  2. In the same solution, create another project and set its model to the new one .
  3. Drag and drop the objects from the above project to the new one .
  4. Sync and Rebuild.
  5. Now the objects are ready in new model .
This way our job becomes easy and we can be sure the objects are not missed because there are chances of missing the objects when they are moved across physical locations.

June 28, 2023

Database restore from bacpac file - D365 FO

 We may have to restore the database in D365 environment in order to get the latest data and configurations in the system. To get the latest dat we should have a backup file of the database taken from other environment. 

The back up files can of two types

  • .bak 
  • .bacpac

Restoring a ".bak" file in to SQL server involves the direct process to get the latest data base. But if the file type is of ".bacpac" then it is not the same way as a ".bak" file.

Restoring a ".bacpac" file needs a different approach than the regular database back up file Below are the steps to be followed to restore the bacpac file in to SQL Server.

1. Open command prompt with Admin rights

2. Use the below command to navigate to the folder 

  • Cd C:\Program Files (x86)\Microsoft SQL Server\140\DAC\bin

      Note : If 140 or 150 not available then install update for dac framework. Install DAC

3. Execute the below command

  • SqlPackage.exe /a:import /sf:Your file path /tsn:localhost /tdn:AXDB_New /p:CommandTimeout=1800
  • File path example : C:\Temp\YourbacpacName.bacpac

4. Login to SQL Server with Admin user

5. Select the newly created DB (AXDB_New) in previous steps and execute the following SQL command in it.

6. Rename AXDB to AXDB_Old.

7. Rename AXDB_New to AXDB.


SQL Script to be executed

CREATE USER axdeployuser FROM LOGIN axdeployuser

EXEC sp_addrolemember 'db_owner', 'axdeployuser'


CREATE USER axdbadmin FROM LOGIN axdbadmin

EXEC sp_addrolemember 'db_owner', 'axdbadmin'


CREATE USER axmrruntimeuser FROM LOGIN axmrruntimeuser

EXEC sp_addrolemember 'db_datareader', 'axmrruntimeuser'

EXEC sp_addrolemember 'db_datawriter', 'axmrruntimeuser'


CREATE USER axretaildatasyncuser FROM LOGIN axretaildatasyncuser

EXEC sp_addrolemember 'DataSyncUsersRole', 'axretaildatasyncuser'


CREATE USER axretailruntimeuser FROM LOGIN axretailruntimeuser

EXEC sp_addrolemember 'UsersRole', 'axretailruntimeuser'

EXEC sp_addrolemember 'ReportUsersRole', 'axretailruntimeuser'


CREATE USER axdeployextuser FROM LOGIN axdeployextuser

EXEC sp_addrolemember 'DeployExtensibilityRole', 'axdeployextuser'


CREATE USER [NT AUTHORITY\NETWORK SERVICE] FROM LOGIN [NT AUTHORITY\NETWORK SERVICE]

EXEC sp_addrolemember 'db_owner', 'NT AUTHORITY\NETWORK SERVICE'


UPDATE T1

SET T1.storageproviderid = 0

    , T1.accessinformation = ''

    , T1.modifiedby = 'Admin'

    , T1.modifieddatetime = getdate()

FROM docuvalue T1

WHERE T1.storageproviderid = 1 --Azure storage


DROP PROCEDURE IF EXISTS SP_ConfigureTablesForChangeTracking

DROP PROCEDURE IF EXISTS SP_ConfigureTablesForChangeTracking_V2

GO

-- Begin Refresh Retail FullText Catalogs

DECLARE @RFTXNAME NVARCHAR(MAX);

DECLARE @RFTXSQL NVARCHAR(MAX);

DECLARE retail_ftx CURSOR FOR

SELECT OBJECT_SCHEMA_NAME(object_id) + '.' + OBJECT_NAME(object_id) fullname FROM SYS.FULLTEXT_INDEXES

    WHERE FULLTEXT_CATALOG_ID = (SELECT TOP 1 FULLTEXT_CATALOG_ID FROM SYS.FULLTEXT_CATALOGS WHERE NAME = 'COMMERCEFULLTEXTCATALOG');

OPEN retail_ftx;

FETCH NEXT FROM retail_ftx INTO @RFTXNAME;


BEGIN TRY

    WHILE @@FETCH_STATUS = 0 

    BEGIN 

        PRINT 'Refreshing Full Text Index ' + @RFTXNAME;

        EXEC SP_FULLTEXT_TABLE @RFTXNAME, 'activate';

        SET @RFTXSQL = 'ALTER FULLTEXT INDEX ON ' + @RFTXNAME + ' START FULL POPULATION';

        EXEC SP_EXECUTESQL @RFTXSQL;

        FETCH NEXT FROM retail_ftx INTO @RFTXNAME;

    END

END TRY

BEGIN CATCH

    PRINT error_message()

END CATCH


CLOSE retail_ftx; 

DEALLOCATE retail_ftx; 

June 23, 2023

CrossCompany and changeCompany using x++

 CrossCompany:

    Required company filter:

    MyTable 	myTable; 
    container 	conCompanies = ['cmp1', 'cmp2', 'cmp3'];

    while select crossCompany : conCompanies * from myTable
    {
	// code
    }

    All company filter:

    MyTable 	myTable; 

    while select crossCompany * from myTable
    {
        // code
    }

    Applying On Dynamic queries:

    Query 			query = new Query();
    QueryRun 			queryRun;
    QueryBuildDataSource 	qBDS;

    qBDS = query.addDataSource(TableNum(CustTable));
	
    // Way-1 (we can add required company)
    query.allowCrossCompany(true);
    query.addCompanyRange('cmp1');
    query.addCompanyRange('cmp2');

    // Way-2 (It will loop all company)
    queryRun = new QueryRun(query);
    queryRun.allowCrossCompany(true);

Change Company:

    MyTable 	myTable; 
    changeCompany('cmp1') { while select myTable { // code } }