Showing posts with label D365FO. Show all posts
Showing posts with label D365FO. Show all posts

Virtual Fields Vs Computed Fields


 


Virtual Field:

A virtual field in D365FO is a field that doesn't have a direct representation in the database. It's a field that you can define in a table as if it were a regular data field, but its value is computed on-the-fly based on certain calculations or business logic whenever it is queried. Virtual fields are often used to display derived or computed information without storing it in the database.


Advantages of Virtual Fields:


  • No need to store redundant data in the database.
  • Useful for displaying calculated values without performing calculations every time.

Computed Field:

A computed field in D365FO is similar to a virtual field in that its value is calculated based on certain rules or business logic. However, computed fields are typically defined in the Application Object Tree (AOT) and are often used within forms or reports to display dynamic information based on specific calculations.


Advantages of Computed Fields:

  • Provides dynamic and real-time calculations.
  • Can be used for various display purposes within forms and reports.

In summary, both virtual fields and computed fields are used to display calculated or derived information in Dynamics 365 Finance and Operations. Virtual fields are defined in tables and calculated on-the-fly during queries, while computed fields are often used within forms and reports to display dynamic calculations based on business logic. The choice between them depends on where and how you want to display the calculated information.



Support Faryal's Cusine


Chain of Command VS Event Handlers

 

Differences & Advantages



Chain of Command (COC):

Chain of Command is an extension framework in D365FO that allows developers to customize and extend standard application logic without modifying the original code. It enables you to add new business logic, validations, and modifications to existing methods in base classes. COC works by creating an extension class for the base class you want to modify and then overriding or adding methods within this extension class. COC supports before, after, and around method events.


Advantages of COC:

  • Non-intrusive: Original code remains untouched.
  • Supports method extensions.
  • Facilitates the coexistence of multiple extensions.
Example
class BusinessLogic1 { str doSomething(int arg) { // ... } }


[ExtensionOf(classStr(BusinessLogic1))] final class BusinessLogic1_Extension { str doSomething(int arg) { // Part 1 var s = next doSomething(arg + 4); // Part 2 return s; } }

BusinessLogic1 object = new BusinessLogic1(); info(object.doSomething(33));

Event Handler:

Event handlers are programming constructs that allow you to subscribe to specific events that occur during the execution of application logic. They provide a way to respond to actions or state changes in the system. In D365FO, event handlers are often used to react to events such as record creation, modification, deletion, or specific actions taken by users. Event handlers are decoupled from the base code and are defined in a separate class.


Advantages of Event Handlers:

  • Decoupled: Separates customization from core logic.
  • Supports centralized event management.
  • Allows multiple subscribers to the same event.

In summary, COC and event handlers are both mechanisms to customize and extend Dynamics 365 Finance and Operations without directly modifying the original code. COC focuses on extending methods in base classes, while event handlers focus on reacting to events during application execution. The choice between COC and event handlers depends on the nature of customization required and the specific use case.


Example

class PointWithEvent { // Instance fields. real x; real y; // Constructor to initialize fields x and y. void new(real _x, real _y) { x = _x; y = _y; } void move(real x_offset, real y_offset) { x += x_offset; y += y_offset; this.moved(abs(x_offset) + abs(y_offset)); } delegate void moved(real distance) { } } class PointKeeper { public void createAndMove() { PointWithEvent point = new PointWithEvent(1.0, 2.0); point.moved += eventhandler(this.writeMove); point.move(4.0, 5.0); // Output is "9.0". } public void writeMove(real distance) { info(any2Str(distance)); } }


[PreHandlerFor(classStr(MyClass2), methodstr(MyClass2, publisher))] public static void PreHandler(XppPrePostArgs arguments) { int arg = arguments.getArg("i"); } [PostHandlerFor(classStr(MyClass2), methodstr(MyClass2, publisher))] public static void PostHandler(XppPrePostArgs arguments) { int arg = arguments.getArg("i"); int retvalFromMethod = arguments.getReturnValue(); } public int Publisher(int i) { return 1; }

Support Faryal's Cusine


Default User for SharePoint Document Management

 

 SharePoint Document Management 



Problem statement

In this article, we will cover implementing default users to upload the document on the SharePoint repository.

In the OOTB Dynamics 365 Finance & Operations, You need to provide the uploading rights to every user over the SharePoint folder, so he/she can upload the documents to the SharePoint.

What if your documents are secure and you want to hide one user's documents from another one?

You can implement the XDS security on the D365FO end, but what about SharePoint? if the user can directly log in to SharePoint then he/she can see the document of all other users.

Solution

In D365FO, I introduce the feature to set the default user to upload the document to the SharePoint repository on the behalf of all D365FO Users.

At the end of the article, you will find the github link to download the project.

Reference Screenshot


Before jumping directly to the solution, first, we need to understand, how the application is making the proxy connection?


D365FO makes the proxy connection using your external identity, and external identity is populated to the record only when the user login on the D365FO at least once.

What are the classes and forms D365FO is using in uploading the documents to SharePoint?

Following is the form and the classes that are in use of Dynamics 365 Finance & Operations to upload the documents at SharePoint

Form
  • DocuParameters
Classes
  • DocGlobalHelper
  • ExportToExcelStorageHelper
  • OfficeSharePointFolderSelection
  • Docu
  • CollabsitesharepointonlineProxy
  • CollabsiteSPonlineTemplateManager
  • DocDocuActionFileWithMetadata
  • DocSharePointHelper
  • DocSharePointHelperV2

What are the Implementation steps?

First, download the solution from this Download link.
Import the project into your solution.
The solution contains the following elements.
Form
  • Extension of DocuParameters
  • Extension of DocuView
Table
  • Extension of DocuParameter(Table)
Classes
  • Extension of xUserInfo 
  • Extension of DocGlobalHelper
  • Extension of DocuValue
  • New File - DownlaodSharePointFile
Menu Item
  • Download SharePoint
Now perform Build and Sync.
Now create a separate user for document management ex. D365SharePointDoc@Yourdomain.com
Create the SharePoint folder hierarchy for document management.
Grant the permission and rights to the newly created user over SharePoint and target folder.
Revoke the rights of other users from the SharePoint document folder.
Set the user as default to the document management parameter form, reference image available on Top.
Check the SharePoint connection.

When the user will upload the document at SharePoint, you will see the name of your default user name.

Reference screenshot




But on the database level, you will see the name of the user who uploaded the document.

Reference screenshot





Important 
If you are using any custom solution for attachment and uploading the document, then perform the proper testing at your end.

I have developed and tested the solution on 10.0.24.

Support Faryal's Cusine


RecordInsertList Dynamics 365 Finance & Operations

 

RecordInsertList Dynamics 365 Finance & Operations



A shortcode example of how to can create records in a table very performant way using RecordInsertList. Who does not know RecordInsertList, can learn more about it here.

static void HowToUseRecordInsertList(Args _args)
{
    DMOPerfTest DMOPerfTest;
    RecordInsertList RecordInsertList;
    Counter c;
    FromTime fromTime = timeNow();
    
    RecordInsertList = new RecordInsertList(tableNum(DMOPerfTest));
    
    for (c=1;c<=10000;c++)
    {
        DMOPerfTest.clear();    
        DMOPerfTest.AccountNum = int2str(c);
        
        if(DMOPerfTest.validateWrite())
        {
            RecordInsertList.add(DMOPerfTest);
        }
    }
    
    RecordInsertList.insertDatabase();
    
    info(strFmt("Total time consumed: %1", timeConsumed(fromTime, timeNow())));
}

Support Faryal's Cusine


Data Management Project Using X++

 

Data Management Project Using X++


Using the following code, you can import the file and execute the project using your x++ code.

In the code, I am making the file on runtime and uploading the file into temp storage for the demo purpose
but you can use the file uploader as per your requirement.


Code

class AD_Test
{
    /// <summary>
    /// Runs the class with the specified arguments.
    /// </summary>
    /// <param name = "_args">The specified arguments.</param>
    public static void main(Args _args)
    {
        FileUploadTemporaryStorageStrategy fileUploadStrategyInstance;
        DMFDefinitionGroupEntity    definitionGroupEntityBuffer;
        DMFEntity                   dmfEntitybuffer;
        FileUploadTemporaryStorageResult result;
        SysDictClass uploadStrategyDictClassInstance;
        str entityName = 'VendVendorGroupEntity';
        System.IO.StreamWriter swriter;
        System.IO.MemoryStream   fileStream;
        DMFExecutionId executionId;
        #File



        fileStream = new System.IO.MemoryStream();
        swriter = new System.IO.StreamWriter(fileStream);
        swriter.WriteLine("VENDORGROUPID,DESCRIPTION");
        swriter.WriteLine(strFmt("%1,%2",'Ex-VendGroup','Example Vendor group'));
        swriter.Flush();

        uploadStrategyDictClassInstance = new SysDictClass(className2Id('FileUploadTemporaryStorageStrategy'));
        fileUploadStrategyInstance = uploadStrategyDictClassInstance.makeObject() as FileUploadTemporaryStorageStrategy;
        result = fileUploadStrategyInstance.uploadFile(fileStream, 'VendorsGroups.csv');
     
        fileStream.Dispose();

        CodeAccessPermission::revertAssert();

        executionId = DMFUtil::setupNewExecution('ImportVendorGroup');

        select firstonly  Entity from definitionGroupEntityBuffer exists join dmfEntitybuffer
            where definitionGroupEntityBuffer.DefinitionGroup == 'ImportVendorGroup' &&
                dmfEntitybuffer.EntityName == definitionGroupEntityBuffer.Entity &&
            dmfEntitybuffer.TargetEntity == entityName ;

       
        DMFDefinitionGroupExecution executionBuffer = DMFDefinitionGroupExecution::find('ImportVendorGroup', definitionGroupEntityBuffer.Entity, executionId, true);
        ttsbegin;
        executionBuffer.FilePath = result.getFileId();
        executionBuffer.IsTransformed = NoYes::Yes;
        executionBuffer.update();
        ttscommit;

        DMFQuickImportExport::doPGImport('ImportVendorGroup', executionId, true);
    }

}

Support Faryal's Cusine


Existing Index Changes D365FO

 

Change existing Index D365FO

 

As we all have a requirement in the past to perform the changes in the existing indexes, and as we know the customization is not allowed in the OOTB elements, so we couldn’t achieve this.

 

How we can achieve it?

 

In D365FO, we couldn’t delete or disable the existing index, but there is one way to achieve this.

We can disable the index on SQL level by using the SQL script even on prod.

 

Yes, you are reading correct, we can disable the index and it will not enable again during package deployment, please only disable the index not remove the index, otherwise, Microsoft classes will re-create the index during deployment.

 Now you can create the new index as per your requirements and it will work properly and will not make any conflict with the existing index, because it is already in the disabled state.

How you can disable the index?

 

  public void disableIndex(str _tableName, str _indexName)

    {

        str sql;

        Connection conn;

        SqlStatementExecutePermission permission;

        ;

       

            sql= strFmt("ALTER INDEX %1 ON %2 DISABLE;", _ indexName, _tableName);

            // sql = ‘delete from custTable’;

            permission = new SqlStatementExecutePermission(sql);

            conn = new Connection();

            permission = new SqlStatementExecutePermission(sql);

            permission.assert();

            conn.createStatement().executeUpdate(sql);

            // the permissions needs to be reverted back to original condition.

            CodeAccessPermission::revertAssert();

       

    }


Important

Before applying the index, please perform the analysis on your existing data, might possible

you can face the issue.

Support Faryal's Cusine


Grid Control New features


 Grid Control New features

Fast data entry: 

This feature lets users enter data in a grid ahead of the server. Therefore, it minimizes the need for users to wait for the server to validate one row in the grid before they move to another row. Users can also paste copied tables from Excel directly into grids in the system.




Mathematical formulas:

Users can now enter mathematical formulas into numeric cells in a grid. For example, you can enter =15*4. To make the system recognize a value as an expression, start the value with an equal sign (=).


General improvements:

Various enhancements have been made to improve the usability of the grid. For example, in the existing grid, users might run into situations occasionally where the grid headers and data are misaligned, or the grid jumps while users scroll through data or create new records. These issues do not occur with the new grid control.

Reorder columns:

Users can now reorder columns by dragging them. Hover the mouse pointer over the column header and then drag the gripper control that appears on the left side of the column.




Support Faryal's Cusine


Bulk Database Operations Recordset D365FO/AX 2012

 

Recordset operations or set based operators



We all noticed that AX 2012 and D365FO get slow from time to time when we performed insertion or update operations on huge numbers of records one by one, and to overcome this issue, Microsoft has a feature to update or insert in bulk in a single statement.
 
We have 3 types of Bulk Operations
  • insert_recordset
  • update_recordset
  • delete_from

insert_recordset :


insert_recordset copies data from one or more tables directly into one resulting destination table on a single server trip. Using insert_recordset is faster than using an array insert. However, array inserts are more flexible if you want to handle the data before you insert it.

insert_recordset is a record set-based operator, which performs operations on multiple records at a time.

Syntax :


The list of fields in the destination table must match the list of fields in the source tables.
Data is transferred in the order that it appears in the list of fields.
Fields in the destination table that are not present in the list of fields are assigned zero-values as in other areas in X++. System fields, including RecId, are assigned transparently by the kernel in the destination table.

insert_recordset DestinationTable ( ListOfFields )

select ListOfFields1 from SourceTable [ where WhereClause ]

[ join ListOfFields2 from JoinedSourceTable

[ where JoinedWhereClause ]]

Example : 


The records, "myNum" and "mySum", are retrieved from the table another table and inserted into the table myTable. The records are grouped according to "myNum", and only the "myNum" records with a value less than or equal to 100 are included in the insertion.

insert_recordset myTable (myNum, mySum)
    select myNum, sum(myValue)
        from anotherTable
        group by myNum
        where myNum <= 100;


update_recordset :

The X++ SQL statement update_recordset enables you to update multiple rows in a single trip to the server. This means that certain tasks may have improved performance by using the power of the SQL server.

update_recordset resembles delete_from in X++ and to UPDATE SET in SQL. It works on the database server-side on an SQL-style record set, instead of retrieving each record separately by fetching, changing, and updating.


If the update method is overridden, the implementation falls back to a classic looping construction, updating records one by one just as delete_from does for deletions. This also means that the construction works on temporary tables, and whole-table-cached tables by using the looping construction.

Example :

MyTable tableBuffer;
;
update_recordset tableBuffer
setting field1 = field1 * 1.10;

delete_from :

You can delete multiple records from a database table by using a delete_from statement. This can be more efficient and faster than deleting one record at a time by using the xRecord.delete method in a loop.


If you have overridden the delete method, the system interprets the delete_from statement into code that calls the delete method one time for each row that is deleted.

Example :

static void DeleteMultiRow1aJob(Args _args)
{
    MyWidgetTable tabWidget;
    ;
    delete_from tabWidget
        where tabWidget .quantity <= 100;

}

But these set-based operations will roll back to row-by-row operation when either of the following condition is true:

  • it is not an SQL table (Eg. temporary table)
  • Database log is enabled for the table
  • Alert is set up for this table
  • Record level security is enabled for the table
  • AOSValidation method is overwritten

when using insert_recordset
the .insert() method is overwritten

when using update_recordset
the .update() method is overwritten

when using delete_from
the .delete() method is overwritten
DeleteAction is defined



To prevent it from fallback to row-by-row operation, the following method can be used if:

  • Delete action is defined, use skipDeleteActions
  • Database log is setup, use skipDatabaseLog
  • Alert is setup, use skipEvents
  • Method is overloaded (.insert(), .update, .delete()), use skipDataMethods



Support Faryal's Cusine


Difference Between Replacement key, Alternate key, Surrogate key in AX 2012 and D365FO


  Replacement key, Alternate key, and Surrogate key



WHAT IS A REPLACEMENT KEY INDEX?

While a surrogate key is great for lookup and database performance, it is not useful for the end-user because it gives no indication of the table’s purpose, or what related tables it is linked to. For this reason,  Dynamics 365 Finance & Operations has added the ‘Replacement Key’ index property for tables. The replacement key index is a dropdown of alternate keys that have been specified for the table. There can be any number of alternate keys for a table but only a single replacement key. More than one field can be specified under a replacement key, and it is these fields that will be displayed to the end-user on a form instead of the surrogate key field.

A replacement key is an alternate key that the system can display on forms instead of a meaningless numeric primary key value. Each table can have a maximum of one replacement key.


The replacement key is chosen by setting the ReplacementKey property on the table. The drop-down list offers every alternate key as an available value.

WHAT IS AN ALTERNATE KEY?

A table can have any number of alternate keys. An alternate key may be a natural key or a single field primary key used in foreign or primary key relations with other tables. In either case, to set one, the user must create a new index and then set AllowDuplicates to “No” and AlternateKey to “Yes”. If AllowDuplicates is not set to “No” then AlternateKey should be greyed out and uneditable

WHAT IS A SURROGATE KEY?

In Dynamics 365 Finance & Operations, a surrogate key is the auto-generated primary key for a table in the database. The surrogate key is linked to the already existing RecId field within any table. This means that the surrogate key is a unique 64-bit integer value that is mandatory for the table and cannot be changed or have duplicates. The fact that it is a 64-bit integer (int64) value means table operations normally perform faster than other types of fields such as string fields. This is the main strength of surrogate keys.

Support Faryal's Cusine


Definition of List, Set, Container, and Map

 

Difference between List, Set, Container, and Map


Containers:

Containers are dynamic and have no limits. They can contain elements of
almost all data types: boolean, integer, real, date, string, container,
arrays, tables, and extended data types. However, objects may not be stored
in containers.

Containers in AX are used very often. It’s easy to work with them. But…
data in containers are stored sequentially and thus retrieved sequentially.
This means that containers provide slower data access if you are working with
_large numbers_ of records. In case of large numbers of records use temporary
tables.

List:

Lists are structures that may contain any number of elements that are
accessed sequentially. Lists may contain values of any X++ type. All the
values in the list must be of __the same__(this is the main difference
between lists and containers) type, given in the creation of the list. The
implementation of lists is such that the traversal of the list elements is __very
fast.

Take a look for example at the class Dialog addControl() method.
Their controls are stored in ctrls List.

Map:

A map is a data type that associates one (key) value with another value [An
analog – a small table in memory with two fields: Keys, Values]. Both the key
and value values may be of any valid X++ type, including objects. The types
of the key and the value are given in the declaration of the map. The
implementation of maps is such that access to the values is _very fast_.

Don’t confuse map X++ types with Map objects in AOT, which are used for
mapping tables with similar structures of fields

Set:

The functionality of Sets is similar to the list.  A Set is just an unordered list of items, while a list of items held by a Map
are indexed via a key.
Take look at
\Classes\sysLabel\LabelModuleId().

Support Faryal's Cusine


intermediate language CIL IL D365FO


 What is an intermediate language?



Intermediate language (IL) is an object-oriented programming language designed to be used by compilers for the .NET Framework before static or dynamic compilation to machine code. The IL is used by the .NET Framework to generate machine-independent code as the output of the compilation of the source code written in any .NET programming language.

IL is a stack-based assembly language that gets converted to bytecode during the execution of a virtual machine. It is defined by the common language infrastructure (CLI) specification. As IL is used for the automatic generation of compiled code, there is no need to learn its syntax.

This term is also known as Microsoft intermediate language (MSIL) or common intermediate language (CIL).

Support Faryal's Cusine


Configuration key & Security Key

 

What are the Configuration key & Security Key?



Configuration key: 

Configuration keys allow administrators to enable or disable features in the application for all users. Disabling features help to minimize the attack surface against potential attacks.
Configuration keys are applied to:
  1. Tables
  2. Fields
  3. Indexes
  4. Views
  5. Menus
  6. Menu items
  7. Form controls,
  8. Report controls
  9. Extended data types
  10. Enumerations

Security key: 

Security keys allow administrators to set security on a user group level. Minimizing access on a user group level helps to reduce the attack surface against potential attacks.
The main reasons to apply user-level security are to:
Allow users to do only their designated tasks.
Protect sensitive data in the database.
Prevent users from inadvertently breaking an application by changing code or objects on which the application depends.
You need to apply a security key to:
·                     Tables
·                     Views
·                     Menus
·                     Menu items
·                     Form controls
·                     Report controls

Support Faryal's Cusine


Virtual Fields Vs Computed Fields

  Virtual Field: A virtual field in D365FO is a field that doesn't have a direct representation in the database. It's a field that y...