Professional Documents
Culture Documents
Reference Companion Guide 80730
Reference Companion Guide 80730
The Reference Companion Guide is a Students guide and take away for this course. Please download, email or upload this
guide for future use and take notes or provide additional information on any given topic.
The Reference Companion Guide should be used in conjunction with an E-Learning or trainer led instruction course.
__________________________________________________________________________________________________
__________________
NOTE:
Module practices and demonstrations in this course are performed on prerelease version of Microsoft Dynamics AX
(Version AX7 CTP7).
All practices should be performed in the same sequence as the course, as they are interdependent.
__________________________________________________________________________________________________
__________________
CONTENTS
Module 0: Fleet Management Case Study 7
Lesson 6: Navigation 8
Lesson 7: Projects, Models, and Packages 10
Module Review 14
MODULE PRACTICE 15
Module 2: Architecture 20
Module Review 21
Lesson 1: Labels 24
Lesson 6: Resources 25
Module Review 26
Module Overview 32
MODULE PRACTICE 33
Module Review 39
MODULE PRACTICE 40
Module 6: Tables 45
Lesson 7: Queries 49
Module Review 52
MODULE PRACTICE 54
Module Review 60
MODULE PRACTICE 61
Lesson 2: Relations 64
Module Review 66
MODULE PRACTICE 66
Practice 8: Create a Table Relationship 66
Module Review 75
Module Review 83
MODULE PRACTICE 84
Module Review 92
Lesson 4: Intellisense 99
Lesson 6: Navigation
In this lesson, we will explore the various areas and menus within the Visual Studio development environment for
Dynamics AX. We will explore the major areas of the development environment which include the Application Explorer
and AOT, which is known as the application object tree. And within the AOT, we'll look at the model view so we can see
the organization of the different models in the system, and then we'll look at how the elements are organized within the
AOT. Next, we will look at the Solution Explorer window which is where our projects and elements will be located.
Then we'll check out the properties window which is where we set properties on our different elements. We'll check out
the code editor so we can see how X++ code is developed and edited in the environment. And lastly, we'll look at the
Dynamics AX menu. From here, we can do different tasks such as creating models. First, let's take a look at the
Application Explorer. By default, when you open Visual Studio, you might have some windows and panes already
populated here. I'm starting with a blank canvass so I can show you how to enable or disable certain navigational
features. So the first thing we want to do is go up to the view menu. And we're going to demo the Application Explorer.
So I'm going to click it and it will appear here on the left. I'll right click the AOT node and choose classic view and we'll
look at how this is set up first. The classic view contains all of the system elements regardless of which model they are in.
So we can see the data types node is the very first one in the list. If we expand that, we have our base enums and our
extended data types. If we expand the data model node, we can find our tables, views, queries, data entities, as well as
table maps and table collections. Under the code node, we have our classes and macros. The user interface node is where
we'll find things like forms, tiles, which is a new concept that we'll discuss in this course, as well as menus and menu
items. So these are the user interface and navigational components of AX. We also have an analytics node. This is
where our BI pieces will be located. So we have KPIs. We also have perspectives and some new concepts here such as
aggregate dimensions, aggregate measurements. Under the reports node is we will find our SSRS reports as well as our
report data sources and any images that are used in reports. Our label files are located in the labels node and our resource
files are located in the resources node. We also have a node for security as well as for references and services. Now we'll
switch to the model view. And we achieve this by right clicking on the AOT node and choosing model view. Now we
see an organization by every model that's currently in our system. And the parentheses is the name of the package that
that model belongs to. So if I expand at the Application Suite model, we can see it contains all the same nodes that we
saw in the previous view except for it's only going to have the elements that are related to this particular model. We also
have this search box up here in the Application Explorer where we can search for elements within the system. One thing
we can do is use the word type, followed by a colon, and then specify the element type. So I'm going to look for a table
and we can see my recent search history of the cust table. So when I enter this search query, it's going to return a list of
all the elements that have cust table in it of type table. So once you choose an element, it's going to tell you the model that
it belongs to here in the brackets. We can right click in the element and choose add to new project. Since I don't have a
project open, it's going to create a new project with this element in it in the Application Suite model. So once you add an
element to a new project, you'll be prompted to enter a project name. And choose OK. And once we add an element to a
project, you'll notice the Solution Explorer window appears without project name and a folder for the type of element and
then our actual element. So now we have our Solution Explorer window open. This can also be accessed from the view
menu and choosing Solution Explorer. The Solution Explorer contains our project that we just created. It's called the new
table project, and we can add multiple projects to this solution which is called new table project up here. Within our
project, we can add new folders. So if we right click the project name, we can go to add and choose new folder,
depending on how we want to organize our project. By default, every time we add an element to this, it's going to add it
to the corresponding element type folder since we set that setting in the configuration step to organize our projects by
element type. Once we select an element, we have our properties window down here which will display and show the
different properties we can set on that element. So for example, we're selecting on the cust table and we can change the
label, we can change different behaviors and settings on this table by using the properties window. The properties
window, as well as all of these windows, can be set to float or set to docked. We can also hide different windows and
arrange them as we please. Everything is free form. We can also save a window layout when you have the different
windows set up how you like by choosing window and save window layout. Next, let's look at the code editor window.
So we'll go back to the Application Explorer, and I'll choose type class and I'll look for classes with the word cust in it. So
once you have a code element such as a class or macro or method, we can right click it and choose view code. This will
open the code editor window and you're free to edit and save this code. We can also choose any class and press F7 which
will also launch code editor window. Now, we can see I have two different tabs here with the two different classes that
I'm currently modifying. The last piece of the navigation components we want to look at is this Dynamics AX menu.
From here, we can choose to deploy a package. We can also set options for model management. This includes creating
models, updating a models parameter, such as its name. We can also import projects as well as set different options in the
system.
Module Review
In this module, we learned how to set up and navigate the development environment in Visual Studio for Dynamics AX.
We defined some important terminology and concepts and we learned a bit about naming conventions. Then we looked at
how to create packages, models and projects, as well as creating elements and adding them to our projects. Finally, we
covered the different options and methods for building our elements for use within the application.
● System Requirements
● Minimums:
o 16GB RAM
o 2 CPU cores
● Elements
● Customizable
● Models
● Group of elements
● Projects
● Contained inside models
● Packages
▪ Naming Conventions
● Camel case
● Maintain consistency
● Example: DBVehicle
▪ Navigation
● Model View
● Solution Explorer
● Properties window
● Code editor
● Dynamics AX Menu
● Project properties
▪ Using Elements
● Element designer
▪ Performing Builds
● Building operations
● Database synchronization
MODULE PRACTICE
Scenario
For the introduction to Visual Studio for the fleet management scenario we will need to complete the following four tasks
in the next four practices.
● Configure the VS environment for AX development.
● Create a new model, package, and a project.
● Create an element within the project.
● Build the project.
Simon, the Systems Developer for Contoso, is tasked with creating a new model for the Fleet Management System in
Visual Studio. He is to ensure that it is ready for element creation and that the project builds.
Detailed Steps
1. Right Click on the Visual Studio icon on the desktop and select Run as Administrator.
2. Microsoft.Dynamics.AX.Framework.CodeStyleRules
3. Microsoft.Dynamics.AX.Framework.DataAccessRules
4. Microsoft.Dynamics.AX.Framework.DataEntityRules
5. Microsoft.Dynamics.AX.Framework.DeprectatedElementsRules
6. Microsoft.Dynamics.AX.Framework.MaintabilityRules
7. Microsoft.Dynamics.AX.Framework.StaticCodeValidationRules
ii. Click Projects node under the Dynamics ‘AX 7’ node.
1. Verify that the Organize projects by element type check box is selected, and
click OK.
Scenario
Simon, the Systems Developer for Contoso, is tasked with creating a new model for the Fleet Management System in
Visual Studio. He is to ensure that it is ready for element creation and that the project builds. This practice is in
continuation of the previous practice
4. Create a project
Detailed Steps
1. Right Click on the Visual Studio icon on the desktop and select Run as Administrator.
c. Layer usr
d. Version 1.0.0.0
e. Model description: Example Fleet Management System for Development Basics to illustrate and
practice development tasks.
4. Click Next
6. Click Next
b. Application Foundation
f. Application Workspaces
g. Application WorkspacesFormAdaptor
8. Click Next
13. Click OK
Scenario
Simon, the Systems Developer for Contoso, is tasked with creating a new model for the Fleet Management System in
Visual Studio. He is to ensure that it is ready for element creation and that the project builds. This practice is in
continuation of the previous practice
Detailed Steps
1. In the Solution Explorer, right click DevelopmentBasicsFMSProject
4. Select Menu
5. Name: dbfmTestElementMenu
6. Click Add
Practice 1.4: Build and Compile
Scenario
Simon, the Systems Developer for Contoso, is tasked with creating a new model for the Fleet Management System in
Visual Studio. He is to ensure that it is ready for element creation and that the project builds. This practice is in
continuation of the previous practice
Detailed Steps
1. In the Solution Explorer , right click the Solution ‘DevelopmentBasicsFMSProject’
3. Review the Output screen to review the process. Should say “Build: 1 succeeded or up-to-date”.
MODULE 1: YOUR NOTES
Module 2: Architecture
Welcome to Module 2 on architecture. In this module, we will review the high-level architecture that is used in AX. Let's
get started by reviewing the objectives. The objectives for the architecture module are to describe the elements included
in the application stack, to review the server architecture, and to explain the cloud architecture used with AX.
Module Review
In this module, we described the components included in the application stack. We reviewed the server architecture. And
we explained the cloud architecture that is used in Dynamics AX.
● Application Platform
● Core of application
● SSRS reporting
● Application Foundation
● Organization model
● Number sequence
● Source documents
● Application Suite
▪ Server Architecture
● Architecture
● Database
● Metadata
● Security
● Caches
● Workflow
● Batch
● Forms engine
● Organized by model
▪ Cloud Architecture
● Lifecycle services
● Capabilities:
o Software development
o Customer provisioning
o Reporting capabilities
● Shared services
● One Microsoft
o Single login
o Subscription management
▪ Office 365
▪ Power BI
▪ Online services
● Dynamics AX
● Different topologies
o Demo
o Development/test
▪ Demo
▪ Development/test
o Azure storage
o Networking
o Monitoring
o SQL Azure
o Etc.
MODULE 2: YOUR NOTES
Module 3: Labels and Resources
Welcome to Module 3. In this module, we'll learn about labels and resources. The objectives for this module are to learn
about labels and why we use them in AX. We will review the purpose of the labels for our fleet management scenario.
And then we will create and use both label files and labels. We will explore the search capability of the label editor, and
we will review the best practices for using labels. And finally, we will learn about resources. And we'll create some and
use them in our fleet management scenario.
Lesson 1: Labels
In the first lesson, let's discuss using labels. Label files are small data structures that keep all related and new labels in a
central storage file. For example, you can have a label file for your instance of AX, for your specific company, or simply
for a model. Labels themselves are a reference from the element or artifact in the system that point back to the label file.
This way, labels can have multiple versions depending on language settings. They could return the correct value
depending on the specified language in the system. This is also a more efficient tool than hard coding values. For
example, say a company now uses the term team member instead of employee. When we update the label, the change is
propagated to everywhere in the system where employee is currently used. You should use labels to specify the user
interface text for forms and reports. Labels are created in the label editor and then used in text-based properties in the
AOT or in X++ code.
Lesson 6: Resources
In this lesson, we will discuss how resources are created and used. Resources are the way to manage the pictures, icons,
and other visual representations that will be used within the user interface. This can be accessed through the resource
library, adding additional resources or using resources that are at a URL location. The URL location would be used in the
case of an IIS server instance with an established product photo library.
Module Review
In this module, we learned about labels in AX and how and when to use them. We reviewed the use of labels for our fleet
management scenario and then we created and used both label files and labels. Then we explored a search capability of
the label editor. Next, we reviewed best practices for using labels. And finally, we learned about resources, and then we
created and used some resources in our application.
MODULE 3 KEY TAKE AWAY
o Labels and Resources
▪ Labels
● Small data structures that keep all related and new labels in a central storage file
▪ Label creation
▪ Searching
▪ Resources
● Pictures
● Icons
● Visual representations
● Solution Explorer
Exercise Scenario
For the Fleet management System, there will need to be two items created. First, there will need to be a label file to hold
the labels that are included for the Fleet Management model. Second, for all of the artifacts and elements you create, they
will each need their own label.
Simon, our AX developer, will need to create a label file within our DevelopmentBasicsFMSProject so that all of our
label files will be contained with our model. Next, he will create the appropriate labels for our model.
Detailed Steps
1. In the Solution Explorer, right mouse click the DevelopmentBasicsFMSProject
6. Click Add
7. The Label file wizard will display.
10. Click New to create labels for the following using Description of DB FMS for all created labels:
a. Label ID: dbFMS2 Label: Car
Module Overview
Thank you for joining me in the base enumerations module. In this module, we introduced the data types node and the
Application Explorer and discussed how and when you should create new base enumerations. We also reviewed a few
examples of base enumerations that are used with AX and I showed you how to create new base enums. Finally, we
reviewed the best practices and considerations for using base enumerations with your projects.
● List of literals
● Saves space
▪ Best Practices
● Consider:
● Length
● If it should be mandatory
● If it is a special type
MODULE PRACTICE
Scenario
For our fleet management scenario, we will need to build three enumerations. These will aid in tracking the vehicle type,
service type, and the fuel type.
Simon, our AX developer, will need to create three base enumerations needed for our model.
-dbfmServiceType
None
Registration
OilChange
Maintenance
Repair
-dbfmVehicleType
Car
Truck
Van
SUV
-dbfmFuelType
Gas
Diesel
Propane
Natural Gas
Electric
High Level Steps
1. Create a base enumeration
2. Set the label
6. Build
Detailed Steps
1. In the Solution Explorer, right click the DevelopmentBasicsFMSProject
6. Click Add
7. Right click the newly create dbfmServiceType (usr) [DevelopmentBasicsFMS] in the middle
white pane and click Properties.
8. Enter Service Type in the Label field under the Properties section on the lower right side of
the screen.
10. Right click the newly created dbfmServiceType (usr) [DevelopmentBasicsFMS] in the
middle white pane and click New Element. Repeat steps 9a-c to create the following
elements:
18. Enter Vehicle Type in the Label field under the Properties section on the lower right side of
the screen.
19. Right click the newly created dbfmVehicleType (usr) [DevelopmentBasicsFMS] in the
middle white pane and click New Element. Repeat steps 9a-c to create the following
elements:
27. Enter Fuel Type in the Label field under the Properties section on the lower right side of the
screen.
28. Right click the newly created dbfmFuelType (usr) [DevelopmentBasicsFMS] in the middle
white pane and click New Element. Repeat steps 9a-c to create the following elements:
31. Review the Output screen to review the process. Should say “Dynamics AX7 build
completed”.
MODULE 4: YOUR NOTES
Module 5: Extended Data Types
Welcome to the extended data types module. X++ data types are divided into primitive data types and composite data
types. You can also create extended data types and base enums which build on the primitive data types. These can be
created only by adding these types of elements to your projects. They cannot be created in code as a language construct.
Let's get started by reviewing the objectives. The objectives for this module are to review the primitive data types within
AX, to create new extended data types that we'll use in our fleet management scenario, and to describe the best practices
for data types.
Module Review
Thanks for joining me in the extended data types module. We took a look at each of the primitive types that are used in
AX and looked at several examples of creating new extended data types and setting properties specific to those types.
Then we discussed the best practices for using extended data types in your solutions.
● Types
● Anytype
● Booleans
● Dates
● Enums
● GUIDs
● Integers
● Real
● String
o Number of characters
● TimeOfDay
● UTCDateTime
▪ Create EDTs
● Benefits of EDTs
● Provide consistency
● Reduce work
▪ Best Practices
We'll call this one dbVehicle. This will store all of the main information for the vehicles in our fleet. So once I choose
add, it opens up in the element designer. It also adds a folder here where my future tables will continue to be added. To
create a second table, we can certainly repeat that process. We can also highlight this table and copy and paste it. So I'll
right click and choose copy. I'll choose my tables folder, and I'll right click and choose paste. It's going to simply append
the name copy to the original table. I can highlight this and press F2. So I can rename it to my liking. I'll call this one
dbMaintenance. And this table will store all of the maintenance information for our vehicles. So the first property I'm
going to set is the label property. So I'll need to right click my table element and choose open to make sure that it's open
in the designer and then I am allowed to begin editing the properties on that element. So for the label, for the dbVehicle
table, we'll simply call it vehicles. I'll right click and open my maintenance table. And I'll go ahead and change the label
on this one to simply be maintenance.
We can also drag and drop EDTs, enums and fields from our project pane on to the table. So for the dbMaintenance
table, I'm going to add this enumeration of service type. I can simply drag it over to the fields node and it will populate.
Now, I've added some new fields here simply for the purpose of having more information for our tables. So we walk
through the process of creating all these different EDT types and enumerations. I've simply added a few mores in here
just to make our solution a little more robust. So for the maintenance table, we're also going to add the string for vehicle
ID. This will be our internal identification number for our vehicles. So we want this to be on both tables actually so we
can create a relationship in the future on that field. For the maintenance table, we also want to have our service start and
end dates and those are in our EDT date folder. So I will click the begin date, I'll press CTRL so I can select the
additional service end date, and then I can drag both of them on to the fields for my maintenance table. OK. And next I
want to add the vehicle type enumeration so that I know which type of vehicle is being serviced in my maintenance table.
And I'll drag that out there. So those are the fields we're going to add for the maintenance table. So I'll click over to my
dbVehicle table tab and I will add some fields to this. For the dbVehicle, we're going to have a lot of general information
about vehicles. So if I go to my EDT strings folder, we have make and model, vehicle ID and VIN number. And again,
I'm holding CTRL so I can select multiple elements so I can drag them on to my fields node. OK. Now let's go to the
EDT integers folder. Here we have an integer type of number of doors. I'll drag that onto my vehicle table. I will also go
to the enumerations and drag the drive type field. Then within my dates, I will choose my DB year to indicate which year
this vehicle was manufactured. And then we will choose the vehicle type enumeration and drag that out there. OK. So
now I have a handful of fields on both of my tables. And we can begin adding data to the table now. So let's make sure
we choose the double disk icon here to save all, which will save the changes that I've just implemented on both of my
tables. We mentioned that field groups are logical groupings of physical database fields. AX uses field groups to cluster
fields into logical collections so that they may be used with other AX objects such as forms and reports. An example of a
field group is the address group located in the address field group on the cust table. Some common uses for field groups
not only include to organize logical groupings of fields and data but also to help dynamically update some objects. For
example, if a modification is made to a field group, related objects are automatically updated to reflect the new content of
the group. So if we have a form that has the address field group on it, and then we modify the address field group on a
table to include a new field, for example, PO Box or address line two, the form with that field group will automatically
update to reflect those changes you made in the field group on the table. So adding new fields to a field group can be a
powerful technique for updating forms. We will discuss best practice checks for using field groups in the best practices
lesson of this module. OK. So we have our two newly created tables with the fields and data types added to them that we
have just done in the previous lesson and I have the dbMaintenance and the dbVehicle table opened up in the element
designer so I can go ahead and begin modifying both of them. So with the dbVehicle table selected and opened, I want to
expand my fields node just to take a quick look at the fields that we've added here. So we have handful of fields to use in
this table and now we want to create a field group. So if I highlight the fields group node, I'll expand it. And here we can
see some default field groups that are created each time you create a new table. These are created by default. If I right
click the fields group node, I can choose new group to create a custom field group. With the field group one highlighted,
I'll press F2 so I can name it to my liking. And I'll call this vehicle description. OK. Now, we can add fields to this field
group in a couple of ways. The easiest way is to go up to our fields here and drag them into it. So I want to choose DB
make. I'll hold CTRL so I can select an additional item which would be DB model and DB year. And I'll go ahead and
just drag these down into my newly created vehicle description field group and they will appear there. Now, another way
to add fields to the field group is to simply highlight the field group, right click it, and choose new field. It will create this
blank node here, and then in the properties pane, we can choose the data field drop down will allow us to choose a field
from our table. OK. So we see some system fields in here like recID, and then we see the fields that we've created there.
So we can choose any of those fields to add to the field group. For this purpose, I just want these here so I'll go ahead and
right click this blank field and choose delete. OK. So we have our vehicle description field group. It's ready for use and
we'll see how that can be beneficial in later lessons when we begin to create forms off of these tables. OK. So I'll go
ahead and choose the double disk to save all of my changes here. And then I would like to perform a database sync.
Since we've been creating these different elements and tables, we want to make sure that what we're creating is in sync
with the database or added to the database on the back end. So an easy way to do that, we can right click our project and
choose properties and we can have synchronized database and build set to true.
This way, every time we perform a build it will sync our elements with the database. So with my project selected, I'll
right click and I'll choose build. Again, we have an output here. It's walking us through the build steps and we can see
that the database sync has completed.
In this example, the FMVehicle table is what we call the base table. So FMCars and FMTruck inherit fields or properties
from this table. There's no need to have common fields like VIN number, year, or vehicle make in all of these tables
when the FMCars table and the FMTruck table can simply both inherit these. Now, you'll notice in the FMCars table, we
have fields that are specific or independent to a car such as the boolean field sedan which would be: Is it a sedan? Yes or
no. Is it a coupe? Yes or no. The FMTruck table has a field called hauling capacity which is specific to trucks. So
independently, they have fields that are important or specific to them and they can inherit other common fields from
another table so that they don't have to be recreated and re-added. In order to use the concept of table inheritance in our
example, I'm going to create an additional table. So I'll go to my project, I'll right click, and I'll choose add new item.
Again, under the data model group, I'm going to choose table, and I'll call this one DB cars. So this table will be specific
to vehicle types of cars. So this table is going to extend or inherit from the main dbVehicle table. So in order to set this
up, what we first have to do is open up these tables in the element designer. So I'm going to go to my dbVehicle table and
if I scroll down to the bottom in the properties window, there's a group called super type, subtype and a property called
support inheritance. I need to change this to yes on both the base table, which is the dbVehicle table, and the derived table
or the child table that is inheriting the traits. So I'll flip that to yes on dbVehicle. I'll save it. I'll go to my newly created
DB cars table. And I'll go ahead and flip that same support inheritance property DS. And on the derived table, there's
another property called extends that we need to set. This tells it which table it's going to derive from. So I'll simply type
in my dbVehicle table, and now it knows to inherit the traits or the fields from that table. So I'll go ahead and save this
table. Now, you'll notice if I right click on my DB cars child table here, there's an option in the context menu to go table
dbVehicle, so it knows that it's now an inheritance relationship. OK. Another thing we can do is if I right click on either
the vehicle or the cars table, there's an option called view hierarchy. And this will show us a graphical view of the
inheritance that's set up on this table. So it opens up a DGML file and we can see it has DB cars pointing to the base table
of dbVehicle. And if we were to set up additional tables that inherit from this dbVehicle table, for example a truck table
or a van table, we would see those appear here in this diagram as you continue to build out those relationships. OK. So
it's important to note that the DB cars table right now has no fields. So for example, I'm going to add a couple fields real
quick. So I have a field I created called DB coupe and one called DB sedan, and these simply are no/yeses. So is this car
a coupe? Is this car a sedan? Now, I can add those fields to the car table, and those fields are accessible from this table,
but idea with inheritance is now my car's table can access the fields from the dbVehicle table. So my dbVehicle table is
the main base table and that contains all those fields we added like VIN number, year, and vehicle make. So I don't need
to read those on to my car table. They automatically inherit those. So for example, if I were to create some code, I could
reference those fields from my cars table in the code. And then if I were to insert a record into the cars table that had a
field from the vehicle table, I could do that as well, and the code would know to insert the information into the correct
table. So if I was updating a field like vehicle make on the cars table, it would insert that here into my vehicles table as
well.
So we'll select it and we'll type a name for our query. We'll call it dbVehicle query. I want this query to be based off my
vehicle table. I'll add it. We have our new folder here with the query element itself and it's opened here in the element
designer. So let's go ahead first of all and give it a title. So we'll set this property. We'll just call it vehicles. OK. Now,
the data source's node specifies which table or tables we're going to have as a data source for this query. I could go to my
project and open up my tables folder and simply drag a table to the data source's node. So now, I have my dbVehicle
table as my data source. If I expand the data source itself, we can see there's fields which specify what fields we want to
include from that table in this query. By default, none are added. We can right click and choose new and we can choose a
field and then this will allow us to specify which table in the query that we want the table to come from and then which
field that we're going to add. So I can see here in my drop down that I'm going to have different options for choosing the
tables and fields. So here's all the fields I can add. I can add them one by one to choose only a subset of field that I want
in this query. Maybe I have a specific purpose for this query that's only going to use a couple fields, so we can go ahead
and manually add fields to the query simply by right clicking and choosing new field. We also have the option to have
some of these aggregate features in a query if we want to sum up a field from our table. We can also have that feature. So
I'm going to delete this manual field real quick. And there's another option we can use for queries which is called the
dynamic fields. So if I choose my dbVehicle data source table, and I go to the properties, there's an option here called
dynamic fields. And by default, it's unselected. We need to set this to yes or no. If I set it to yes, it dynamically adds all
of the fields, including system fields, from my dbVehicle table into the data source for my query. The benefit of this is if,
in the future, I decide to add more fields to my vehicle table, they will dynamically update here in my query that has that
table as a data source. So it's important to note if that feature would suit you. OK. So we can go ahead and close up
these tabs here and we'll save our query. So I'll drag that out to this data source's node. And we can see if I continue to
expand this nested data source, there are options to continually add more and more data sources within data sources. So
when I create this nested data source within my dbVehicle main data source, I need to specify a relationship between them
so that these data sources know how they are related and they can communicate that way. So I'll right click my relations
node in my nested data source, and choose new relation. I'll go to the properties pane over here and set a few properties to
set up the relation. Firstly, I'll go to the field property and use the drop down to specify which field in my dbMaintenance
nested data source I want to use in the relation. And that's going to be the vehicle ID field. For joined data source, if I
click the drop down, we'll notice we only have the dbVehicle table as an option because that is the only other data source
in this query and it's the parent data source for this nested data source. So I'll choose that, and then in the related field
property, I'll choose which field from this joined data source parent that I want to use in the relation. In other words,
which field in the dbVehicle table I'm going to relate to the vehicle ID field and the maintenance table. And that field is
the same, the same name in both places, dbVehicleID. So once I finish choosing those properties, we can see it populates
here this relation, the details. DbVehicletable.dbvehicleID field equals the dbMaintenance table and the dbVehicleID
field. So that's exactly what I wanted. The last thing I'll do is just give this joined relation a name, and I'll just call it the
vehicle ID relation. And I can go ahead and save this query. Some last things to note about queries are these different
options here. We already discussed adding fields to a data source and other data sources within a data source. We also
have the option within these data sources to add a range which is created on a field or fields and specifies a searchable
range or parameter for the query. And then we also have the group by having an order by. For group by and order by, we
can specify which field we want the data to be ordered by in the query or which field we want the data to be grouped by in
the query.
Module Review
Thanks for joining me in the tables module. In this module, we looked at how to create new tables and the key properties
that should be considered for them. We also looked at how to add fields and data types to a table. Additionally, we
reviewed how to create and manage field groups and discuss the concept of table inheritance. We then reviewed how
temporary tables can be used and the various types of temporary tables that are available. Finally, we took a look at the
best practices for tables and fields, field groups, and queries.
▪ About tables
▪ Table components
● Fields
● Field groups
● Indexes
● Relations
● Delete Actions
● Not used
● Methods
● State machine
● Mapping
● Includes:
● Fields
● Base enums
▪ Key Properties
● Table type
● Label
● PrimaryIndex
● ClusterIndex
● ConfigurationKey
● Support Inheritence
● Extends
▪ Table Inheritance
▪ Temporary Tables
● TempDB
● InMemory
▪ Queries
● Highly flexible
▪ Best Practices
● Table
● Naming
● Labels
● Form reference
● Title fields
● Table group
● Table types
● Consider mandatory, allow edit on create, allow edit and visible properties carefully
● Field groups
● Query
● Create queries in the Application Explorer instead of X++ code when possible
● Always use queries as the data source for Forms and Reports
Lesson3:Create an Index
We will begin by examining the process for creating an index on one of our fleet management tables. Indexes are located
within the element and type table in the development environment. They can be added by opening a table in the element
designer and navigating to the index's sub-node. An index is defined by one or more fields on the table. It is used as a
lookup criteria. When choosing which fields to use for a table index, consider fields that are often searched by range or
query or fields that are frequently used in joins. Indexes are often used for performance reasons, to speed up data
retrieval. An index can also be used to ensure the existence of unique records and prevent duplicate entries into a table.
Now let's create two indexes in our dbVehicle table. Now, remember, this table stores all of the information about
vehicles in our fleet. We added a field called vehicle ID which is our internal unique identifier for our vehicles. So the
first index we're going to add is going to be a primary index on the vehicle ID field. To create the index, we go to the
index's node in the element designer for the dbVehicle table. And we can right click index and choose new index. I'm
going to press F2 to rename this and I'm going to call it vehicle ID, and then I'm going to suffix this with IDX which is a
naming convention for indexes. So once you have created this index, we have to specify which field in the table we want
to associate with it. So I'll right click the newly created index and choose new field. Now, we get a blank field here
initially. If we go over to the properties pane, there's a property called data field. And if we click that, we'll get a drop
down and it will populate a list with all of the fields in the current table. So I'll scroll down and find my dbVehicleID
field. OK. Now, if I go back to this index node, there's a property called allow duplicates. It's currently set to no, and
that's what I want for a primary index. We don't want to allow duplicate entries on this field. This way, if someone tries
to insert or create a new vehicle in my vehicle table that has the same vehicle ID already in there, it will prevent that
insertion of that record. So let's create a second index. And this time, we'll create a clustered index. So I'll go back up to
the indexes node and I'll right click and choose new index. I'll rename this one description.IDX. And I'm going to add a
couple fields. Actually, we'll add three fields to this index. So right click and choose new. The first data field will be the
DB make for the make of the vehicle. I'm going to add another field. I'll go to my data field drop down and I'll choose
DB model. And I'll add a third field and we'll call this one the DB year. So now, this index has three fields for the make,
model, and year. And these fields are added to this index because they're commonly searched upon fields. Now,
remember, the order of these fields is also important in the index. We typically want to organize them from the most
granular to the least granular. So now that we've created these two indexes, a primary index on vehicle ID and a clustered
index and description, we want to set the properties in the table so that it knows to use those indexes. So we'll go back up
to the dbVehicle, the root node of my table, and in the properties pane, we can go up to the behavior group and we can
find the clustered index property and the primary index property. So from the primary index, we'll choose the drop down
and we'll see the two indexes I have just created our available choices. The primary index was on vehicle ID so we'll
select that. And the clustered index which organizes -- which determines how the data is organized in my table was a
description index, and that included the make, model, and year. So I'll choose that one for my clustered index. And then
we'll save our table.
Module Review
Thanks for joining me in the table indexes module. In this module, we introduced the various types of indexes that can be
added to tables and the purpose for each type of index. Then we created new indexes and reviewed the best practices for
using indexes in AX.
MODULE 7 KEY TAKE AWAY
o Table Indexes
▪ Index Types
● Primary Index
● Clustered Index
● Non-Clustered Index
● Provides way to quickly reference data found in clustered index or heap using specified
set of columns
▪ Create an Index
● About indexes
● Indexes are associated with tables and make it easier to find specific data
● Best Practices
● Add an index if the speed gained by adding it is greater than the cost of updating it
Lesson 2: Relations
In this lesson, we will describe how relations function in tables as well as the different types of table relations and their
uses. A relationship is created between tables with related data. It defines how they're related and is set on the relations
node on a table element. When you create a relation on a table, you specify which field or fields connect that table to
another one. In the screen shot here, we have a relation.
The name of it is EcoRes product. And then the relationship itself is based on inventTable and the field called product
within that table and it relates to the EcoRes product table and the recID field within that table. Another example is that
we can have a customer table which has customer account number and general information about a customer such as their
name or location. Then we can have a customer group table which may have a list of customer account numbers in one
column and their corresponding groups in another. We can relate these tables on the customer account number so that
when we perform lookups in one table or another, we can find the related records in each table. When creating forms, it's
common to have related tables as underlying data sources. These tables may be related in the query as well. We establish
this relationship so that we can access information in both tables by using a common field like account number or product.
In addition to associating rows in one table with another, relations can also be used to restrict the rows returned in a table
and enforce referential integrity. Let's take a look at some of the different relationship types and how they work in AX.
The first relationship type is called a normal relationship. A normal relation is used to specify a relation without any
conditions. In the field property, we select the field in the primary table that relates to a field in the present table. In the
related field property, we would then select a field in the related table. A field fixed relation is a relation that's used to
restrict records in the primary table. There's a field property which allows us to choose which field in the primary table
we want to use to restrict the records. There's also a value property where we enter the value of a selected field to act as a
filter. This relates only records in the primary table that match the field value . Only numeric values can be entered in the
value property. Field fixed relations can only be created on numeric fields. Each of the related fields are ended in the
table relation. They are combined. A related field fixed relation is very similar to a field fixed relation except for it's used
to specify the relation of the fields and restrict records in a related table instead of the primary table . The same properties
are used in set as in a field fixed relation. We can only set a related field fixed relation on a numeric field as well.
Another type of relation is called a foreign key relation. This is used to specify a correspondence between a foreign key
field in the present table to the primary key field in another parent table. Foreign key relations are usually set on a child
table. We often refer to a child table as a table that has the foreign key. The on delete property value is located within the
relationship properties and it dictates what should happen when a deletion occurs. Since we typically set the relation in
the child table, the on delete property specifies what should occur when a related record in a parent table is deleted. The
purpose of this is to maintain database consistency when a record is being deleted in a table that has related records in
another separate table. There are four different properties here that can be set on the on delete property. The first one is
none. That means the row in this table is deleted but nothing occurs to the tables that relate to this one. The second
option is the cascade value for the on delete property. And cascade means the row in this table will be deleted and all data
in related tables will also be deleted. The next value is called restricted. That means the row in this table will only be
deleted if there is nothing that relates to it in another table. This prevents deletion of a record that has related records
somewhere else in the system. The last option is called cascade restricted. The cascade restricted option means to allow a
cascade delete even though a record exists on related tables. This option causes a warning box to appear to the user. If
you click no, nothing will occur. If you click yes, then a cascade delete will run.
Now, in the properties, the first thing we need to do is specify the related table here. Now, the related table is going to be
our vehicle table. You can type it or use the drop down. I'll type it in there. And now we can right click this relation and
choose new and we have the option to choose a normal foreign key relation or a related fixed field foreign key relation.
We're going to choose a normal foreign key relation. It creates a new node here and a new properties pane opens up. So
the first thing we want to do is select which field here in this table in the maintenance table that we want to include in the
relationship. And that's going to be the dbVehicleID field. Then the related field, this list is populated with fields based
on the related table that we specified here. So when I go here and I click the drop down, I will see fields from my vehicle
table. And again, we want it to relate on vehicle ID. This field exists in both places. OK. So once that's established, we
can go ahead and make sure we save that relation. And if we go back to the main vehicle ID relation node here, we can
look at a few more properties if we're interested. In particular, we discussed the on delete property currently set to none.
We can set this to restricted. If we want to prevent certain types of deletion. So this means if we go into the main vehicle
table and try to delete a vehicle, vehicle ID one, however, there's a maintenance record in the maintenance table for that
vehicle, it will not allow us to perform that deletion. So it's a way to kind of protect and ensure database consistency.
Module Review
In this module, we examined how relationships are used and the different types that exist in AX. We then looked at some
properties of relations and created a new relation for our vehicle maintenance and our vehicle tables. Lastly, we reviewed
some best practices to use when creating table relations.
▪ Relations
● About relations
● Relation Types
● Normal
● On Delete Property
● Outcomes
o None
o Cascade
o Cascade + Restricted
▪ Best Practices
● Configuration key specified for field in relation must be same key or in same tree of keys
The standard flow for applying a pattern is to first acquire the target. In other words, to decide which form you want to
apply the pattern to. Next, is to determine the pattern, to decide which pattern best suits your scenario to display the
information you need to your end users. Next is to apply that pattern. Applying a pattern is as simple as right clicking the
form design and choosing the pattern you want. Lastly is to deal with errors. After the pattern is applied, you can use the
pattern tab in the pattern information panel to make sure you add the correct controls in the correct order to support that
form pattern. We will look at an example of this in the next module when we create a form. After you apply a pattern to
a form, you can also apply sub-patterns to its controls. The process is similar to applying a pattern to a form. You simply
acquire the target, determine the sub-pattern, apply the sub-pattern, and then deal with the errors. This time, the target
should be a container control on a form, somewhere under the form design. The control should have a pattern unspecified
in its name. You right click the control in question and you can select apply pattern and then choose from a list of sub-
patterns that you wish to apply. Dynamics AX has nearly 40 form patterns that you can apply to your custom forms. We
will demonstrate examples of about five different form patterns. The first one is the details master form pattern. This is a
primary method for entering data into Dynamics AX. These form patterns allow the user to view, edit, and act upon data.
All content in these form types is structured into FastTabs which can then be expanded or collapsed, allowing for multiple
FastTabs to be open at the same time. Form part FactBoxes are another form pattern we will look at. In general, these are
used to provide related information for a record. They make sure the user does not have to open additional forms to get
important information that they need such as totals, balances, or overdue orders. The FactBox grid pattern is used when
there is a child collection or potential for multiple rows of related information. A FactBox is created as a separate form
with the FactBox pattern applied and then added as a part on another form. The simple list pattern displays details for a
simple entity as a grid. This typically will have six fields or less per record with no child parent relationship. However,
there can be exceptions where a simple entity may contain up to 15 fields. A list page is another type of form pattern
which still displays data in a grid format. However, it may be data relating to a more complex entity. The fourth type of
form pattern we're going to demonstrate is called a table of contents or setup page. This type of pattern is used on a form
to display setup information. It's commonly used as a setup or parameter page that are frequently accessed through the
navigation menu as well as through workspaces. This pattern should be used when two or more logically related forms
are needed for configuring setup. There's a vertical arrangement of tabs on the left which implies the order of completion.
And finally, the last type of form pattern we're going to discuss is called the operational workspaces pattern. Workspaces
are a new concept that takes over as a primary way to navigate to tasks and specific pages. A workspace must be created
for every significant activity supported in the product. Such an activity is less granular than a task but more granular than
a legacy area page. The workspace must provide a one-page overview of an activity to help users understand the current
status, the workload ahead, and the performance or of the process for the user. There are two types of workspace form
patterns: the traditional workspace and the operational workspace. It's always encouraged to use the operational
workspace as it has superior performance characteristics due to the set of components it contains.
So we'll notice in Excel, we have columns that tell us which model the form is in, the system name for the form, as well
as the form style and the form pattern. In addition, it gives us information about the controls and the percent of coverage.
So we're free to now sort and filter and organize this list so we can determine which system form has which pattern
applied, and also which forms do not have any pattern applied. So if I want to sort on this particular pattern column, we
can go ahead and apply sort. And we can put it in alphabetical order. In addition, we can go ahead and filter on this
column and we can look at all the different pattern types. So if we want to see, you know, which forms use a specific
pattern, we can just choose one pattern and see those forms. We can also choose which forms do not have a pattern. So
we can unselect all, and we'll navigate down and see where the blanks are at. So we can see these blank values for the
pattern indicate that this particular form does not have a pattern applied. This can give us some guidance when
developing to make sure that all the forms we have in our system have an appropriate pattern. This will help provide
consistency in the UI and a better end user experience.
So let's take a look at how a details master form pattern looks like in a UI. We are currently looking at a list of all
customers. The system name for this form is cust table. By default, this opens in a grid view so we have a list of all of
our customers along with their account number, customer group, currency, and telephone number. We have a control here
called a quick filter that allows us to filter the data in this grid.
We can also switch from grid view to details view for a particular customer by doing one of two things. We have the
option to simply click the account number here for a particular customer and it will launch the details view of this details
master form. And the details view contains a lot more information about our customer entity. We have FastTabs that
organize related information about this customer, such as addresses, contact information, and payment defaults, et cetera.
We also have our summary fields here which give us some quick insights into what is within this particular FastTab
without opening it. At any time we can switch back to our grid view by using the back button in our browser. We can
also use this options button up top and go to change view to switch between grid and details view at any time. From our
page options, we also have the ability to perform advanced filtering and sorting as well as retrieving some more record
information. So let's take a look at how this form looks in the development environment in Visual Studio. So I've opened
the cust table form from the Application Explorer. I used the search feature to filter my results. And I have opened it in
the element designer. When you open a form, you will have two panes.
On the left, we have some general information about this form such as methods and events as well as data sources and
form parts. In the right pane, we have our area where we design the form. We apply our form patterns and then we add
the appropriate controls here that will satisfy the requirements of the pattern. So now let's take a look at the two different
types of FactBox patterns. There's the FactBox grid which is used when there's a child collection with the potential for
multiple rows of related information. There's also the FactBox card which is used when there's simply a set of related
fields. So I'm here again in the UI on my all customers cust table form. Now, I have a particular record selected in my
grid view here. And to open the FactBoxes, I click this little blue arrow off to the right that's pointing onto the screen. It
will open a fly-out menu with these different tabs. The first one here is statistics that I have opened is a FactBox card, is
displaying just a few sets of related fields that relate to the selected record.
These were the examples of the FactBox grid and FactBox card. Now, if I search for these parts in the Application
Explorer, for example, I will type in ContactsInfoPart. I'll be returned with a form and it's called contact info part. Now,
if I right click this one and choose open in designer, we can see that this ContactsInfoPart form has the pattern, form
pattern FactBox grid applied. Likewise, if I were to search for the customer statistics statistics form part, it would open up
a form that has the design pattern applied for the form part FactBox card. So these FactBoxes are created as a separate
kind of form and they have a pattern applied, and then they are added onto the form as a part that you want to display
them on. The third type of form pattern we're going to demonstrate is a simple list pattern.
So I'm here at the main page of a dashboard in my Dynamics AX UI. And I'll click up here on the navigation menu. And
I'm going to navigate to accounts receivable. And I'll go the setup page. And I'll go to customer groups. This form
demonstrates the simple list pattern type. We can see there's only five different columns here, five different fields, and a
small list of different customer groups. So this is really the epitome of what a simple list type pattern would look like.
Again, this form pattern does support the quick filtering, even though we only have a handful of records here. You could
potentially have more and then go ahead and filter your simple list using the quick filters control.
In this demonstration, we're going to look at the table of contents form pattern. This is also known as a setup page. A
good example of this is the accounts receivable parameters. So we'll navigate to our navigation menu and choose
accounts receivable, setup, and then accounts receivable parameters.
So here we have our table of contents form pattern. Now, we can see along the left here, this is called the vertical tab
style. They are arranged in a sequential order of these parameters that need to be set up. So each option here at the left is
a tab choice and has a different page that relates to some type of setup information. This pattern should be used when two
or more logically related forms are needed for configuring setup. This form pattern contains a collection of smaller
content regions that each follow a container pattern similar to a simple list.
In this demonstration, we're going to look at an example of the operational workspace form pattern. A good example is
located in the product information management area. So we'll go to our navigation menu. I'll go to product information
management and then we have this next area called workspaces. And then I'll choose released product maintenance.
So this is the layout of an operational workspace. It's intended to provide an overview of a specific activity, including the
current status and summary of particular items as well as the workload ahead. So we notice these objects over here are
clickable and they're called tiles. Windows 8 introduced the concept of tiles, and you'll see them used in Dynamics AX,
especially on operational workspace form patterns. It's essentially a rectangular button that behaves just like a menu item.
You can click it and navigate to different pages. You can navigate to reports as well as outside URLs. In addition, tiles
can display relevant data such as a KPI, a key performance indicator, which displays information such as total revenue.
Tiles can also include images that provide the user with some type of visual context. You'll notice we have these three
kind of panes here on the left, the summary pane with the tiles. In the center we have more information about specific
released products, and then a third pane over here is a stopped released products. And then finally, we have a section with
different links that we can quickly get to related pages.
Again, if I right click, we can see this control name is called log-in and this one here is called general. So let's go take a
look at how these are set up in a development environment. So I'm going to go back to Visual Studio and I've specified
this search query here in the Application Explorer to return me that retail visual profile form by using the type followed by
a colon and the word form which specifies which type of element I'm liking for, and then followed by space and the actual
name of the form. That returns me with this element here, so I have right clicked and opened that in my designer. Now,
again, we can see on the design node the form pattern for this entire form is the simple list and details list grid form
pattern. Now, if I click into these different tab page controls and I can begin looking at my sub-patterns. So I'll expand
this details tab. We can see the general control and the log-in control. The log-in control uses the sub-pattern of image
preview. The general tab page control uses the pattern of fields and fields groups. Now, again, the fields and fields
groups sub-pattern provide a responsive layout for containers that contain only fields. It's a good example to use on a tab
page that has a FastTab just like we have here. We have these different fields and field groups, so then we're using our
field and field group sub-pattern. Now I want to demonstrate an example of a selection tiles sub-pattern type. To do that,
we'll go a workspace form where we can commonly find these selection tiles sub-patterns. So from the navigation menu,
we'll notice this option here, all workspaces. If I choose that, these are all these different out-of-the-box system
workspaces. I'm going to go down here and choose sales order processing and inquiry. It will open up my workspace.
Again, we have these three kind of columns here that we can use in our workspace form pattern. So the one we want to
focus on here is this left area where we have our selection tiles sub-pattern.
And again, these tiles are clickable objects. I can click this one here and it will open up the all sales orders details. I can
also click here to access all customers, and then we have these different KPIs that are showing the amount of confirmed
sales orders and orders on hold. Now, let's take a quick look at how this looks in a development environment. So I'm
going to go back to Visual Studio and again, I've created a query to find this form in the system.
I have opened it up here in my element designer, and I can see that the form pattern for this entire form is the workspace
operational form pattern. And then if I expand this panorama body tab, we can see that the pending orders tab page is
configured with the sub-pattern of selection tiles. And that's what we see over here in the left pane. You'll notice when
we click that, the blue rectangle is highlighted on that area of the form. I'll also point out that this panorama body tab is a
tab style called panorama. And that's often used on operational workspace form patterns as well. It kind of signifies this
entire horizontal layout, that kind of three-pane setup that we see in the UI. Now, we mentioned that applying sub-
patterns is very similar to applying a normal form pattern. And to illustrate that, I'm going to show you here on the sales
order processing workspace form that we've already opened, and we can simply right click one of these tab page controls.
And for the sake of example, I will remove the pattern since there is one already applied, and we can see now we have this
pattern and then select next to it which indicates that there is no pattern, sub-pattern applied to this control. So to add one,
we can simply right click our tab page control and we'll go to apply pattern and we can see the only option for this one is
selection tiles. And we can go ahead and apply it. Depending on which type of control you have and which type of main
form pattern is applied, that will dictate which options you see when you go to apply a sub-pattern.
Module Review
Thank you for joining me in the module on form patterns. In this module, we looked at several examples of different
form patterns and sub-patterns as well as their applications in the form designer. We discussed the important properties
for form layouts and then we reviewed how to monitor the progress of a forms development using the form statistics add-
in and the form pattern tab.
● Acquire target
● Determine pattern
● Apply pattern
● Deal with errors
● Details master
● Simple List
● Table of Contents
● Operational Workspaces
● Sub-Patterns
● Sub-Pattern Types
● Image Preview
● Selection Tiles
▪ Layout Properties
● Value: Auto
● Value: View
● Value: Edit
● Form.RootDatasource.AllowCreate
● Value
o No
▪ Read only page
o Yes
▪ Allows creation
● Form.RootDatasource.AllowDelete
● Value
o No
▪ Can’t delete
o Yes
▪ Can delete
● Ensures consistency
● Form Statistics
● Dialog shows
In the screen shot, the action pane is the gray strip of buttons. By default, certain form types will already contain the edit,
new, delete, and modify buttons. These help change records within a certain form. It also currently consists of system-
defined actions. These are actions that aren't explicitly modeled. It also contains developer-defined actions. These are
actions that are modeled in button groups and placed directly under the action pane on a forms design node. When an
action pane tab is clicked, a file menu opens, which contains various button groups and links to perform certain actions.
We can see that this purchase order action tab opens up a fly-out menu here with several different button groups. For
example, the maintain button group which contains two buttons. Request change and cancel. Action panes are modeled
by using the following basic structure.
Note that in Dynamics AX, button groups can also be placed directly under the action pane which is the case in the screen
shot. Our action pane resides here and we have a button group directly under the action pane. Within the action pane
form control, you can set up button groups and buttons to perform certain actions. Some of the different types of buttons
in AX include the standard button for which the entire functionality must be implemented in code. Then there's the
command button which specifies a command or a specific task to run. We then have the menu item button which
specifies a menu item to navigate to or to run. Next there's the drop dialog button which opens a fly-out dialog box, the
contents of which are retrieved via a menu item. And lastly, we have a menu button. This button container opens a fly-
out which contains a list of other buttons. Tool bars are action panes for which the style property is set to strip. They are
used for actions that have a specific context or aren't page level actions and also, primarily for actions that are specific to a
FastTab, tab, or grid. In this example, we're looking at the addresses FastTab on the customer details form.
In the screen shot, the tool bar is represented by the add, edit, and map buttons right here. Tool bars were previously
known as action pane strips in previous versions of AX. A grid control in AX is the primary tool for presenting data and
letting users interact with it. There are currently three different grid styles that are implemented and supported, and those
are tabular, list, and simple read only. These are set using the grid style property. The tabular style grid is the traditional
multicolumn grid. To present data in a tabular grid, we set the style property to either auto or tabular. A list style grid is a
single column stacked format. To present data in a list grid, we set the style property to list. In a simple list grid, when
the width mode is set to auto, the width of the grid is determined by the widest field. Other fields are arranged in a left-to-
right stacked manner. The simple read-only grid style displays read-only data in a grid format. It is often used on form
parts such as FactBoxes or info parts and displays a small bit of read-only information. Let's take a look at some visual
examples of the different grid styles that we've just discussed.
The first one is the list style grid. And this is represented here in this left pane. If we click this blue grid-like icon on a
form, it will pop out a list style grid like this. We have this grid configured to show a customer's name and phone number.
This is a scrollable pane here on the left-hand side of our form. It also contains a filter so we can filter this list. Next, we
have our tabular style grid. And again, this is a traditional table style grid. It contains many rows and many columns. It
also has the ability to be filtered and edited as well. And finally, the simple read only style grid has a start date and end
date for a particular employee. And this is read only data. This is represented here in a FactBox that would live on some
other form.
▪ Form Controls
● Form.Design
o Root of page
● Group
● Tab
● TabPage
● ButtonGroup
● ActionpaneTab1
o ButtonGroup1
▪ Button1
▪ Button2
● Types of Buttons
● Button
● Command Button
● Men Item Button
● Menu Button
● Toolbars
● Grid Styles
● Tabular Style
● List Style
▪ Add Elements
▪ Best Practices
● Name the form to coincide with the main data source table
The first one is the menu item type. We can specify which type of menu item we want to associate with this menu. And
those we have our three menu item type as options. That would be display, output, and action. After selecting which
menu item type, we can then use our menu item name property. The menu item name will be filtered based on the menu
item type you select. So if we choose display for menu item type, then the menu item name has to be a display type menu
item in the system. Then we have the configuration key property. And this is used to set which configuration key we're
going to use for the menu. The normal image property specifies which image will be used when the menu is enabled.
And finally, the label property is the UI friendly name of the menu that the user will see in the navigation menu or
submenu. So we've created a menu item and attached it to our VehicleListPage form. Now, I went ahead and created a
second menu item called dbVehicleMaintenance that is linked to the vehicle maintenance form. So now, we need to place
these menu items on a navigational page on a certain menu so that we can click them in the UI. And for this example,
we're going to add our VehicleListPage onto the organization administration navigational menu page. And to do that, I'm
going to go to the Application Explorer and I'll right click on the AOT node and choose model view. Now, I can see all of
the elements in the system organized within their certain model. And I need to go to the Application Suite model. So I'll
expand it. Then I'll expand the user interface node. And finally, I'll expand the menus node. Now, here we can see all the
different navigational menus in the system. If I launch my client, we can see here there's accounts payable with these
options for submenus. So if I go here, I can see accounts payable with those specific submenus. So it's set up the same
exact way what we see in the UI. Now, for this demonstration, I'm going to scroll down to the organization administration
menu and I'll right click it and I'll choose this option called create extension. And what that does is create an extension of
the organization administration menu item here, or menu page rather, in my project. I could then right click this and
choose open. And it's going to show me again all of these submenus and the menu items within this menu page. So for
this example, I'm going to just expand this folder here, this submenu called resources and I'll go to my project under my
display menu items folder. I'll drag out my DBVehicleListPage menu item. Again, this is linked to my
DBVehicleListPage form. So I'll add it here to the resources folder. And we'll see it appear here at the bottom of the list.
Now I'll go ahead and save this and I'll go ahead and I'm going to press CTRL SHIFT B for the shortcut key to form a
build on my project. When the build completes, we'll be notified here with the AX build completed. And now we can go
check on the UI to see if these changes have taken effect. So what I'll do is I'll open up my browser page and I'll press F5
to perform a refresh. And when the page reloads, we'll go ahead and check our organization administration menu and see
if we can find our menu item. So it will load up here in my dashboard page. And I'll go up to the navigation menu. I'll
locate the organization administration page. And then I'll click into the resources submenu where we added our display
menu item. And here it is. I provided a label value of all vehicles for that menu item so that's what we see here when we
click this. So I'm going to go ahead and click it and it's going to bring up our all vehicles form. And here are the fields
that we added to the grid when we were designing the form as well as our quick filter control. Now, currently, we do not
have any data in here. We can certainly add some by using this new command which would add records into our form
grid control here. And in the next demonstration, what we're going to do is we're going to add a button group here in this
gray pane that's going to allow us to click into our vehicle maintenance form. So it will kind of be set up like a shortcut to
launch a menu item from this button group here instead of from one of the navigational menu pages here. So we just
added our menu item to display our VehicleListPage form to the organization administration menu page. What we want
to do now is add a menu item to act as a button here so that when we click it, it will launch the vehicle maintenance form
from the all vehicles list page form. To do that, we'll go back to Visual Studio, into the development environment, and
we'll open up our DBVehicleListPage form. So I need to add a button group. And to do that, I'll right click my action
pane control. I'll choose new and I'll choose button group. I'll go ahead and give this button group a caption. We'll call it
vehicles. And now, we'll add an individual button within this group. To do that, I'll right click the button group control. I
choose new. And I choose menu item button. This specifies that this button is going to be linked to a menu item. Now,
I'll go into properties here on my menu item button control. And we have these properties, again, the menu item type and
menu item name. The menu item I want to link to this button is it's dbVehicleMaintenance display menu item. So to do
that, I'll simply type in here my dbVehicleMaintenance. This references the display menu item called
dbVehicleMaintenance. And that's right here in my project. And this menu item is linked to our dbVehicleMaintenance
form. You can see as soon as I do that, the preview pane here for this form updates with the button I just created. Now,
we're free to change the caption here. Or the label. It's used the vehicle maintenance by default since that's the label value
for the menu item. So we'll go ahead and leave that. We'll save our changes. And we'll perform a build. I'm going to use
the CTRL SHIFT B shortcut key. Once the build has completed, we can go refresh our form and see how our changes
took effect. So I'll go back to the form here in the browser and I'll press F5 to perform a refresh. And once the form
loads, we can verify here that our vehicle maintenance button has been added. Now, if I click this button, it goes ahead
and opens up my vehicle maintenance form. This form is currently blank. We didn't specify any particular grid or any
data for this form. However, we can verify that the link does work correctly.
Module Review
Thanks for joining me in the menus module. In this module, we covered creating menus and extending system menus as
well as associating menu items with menus.
● Display
● Action
o Specifies which form to use when form is opened from a menu item
● Normal Image
o Specifies image used when menu item is associated with enabled button control
● Open Mode
● Help Text
● Label
● Enum parameter
● Create permissions
● Delete permissions
● Configuration key
▪ Creating Menus
● About Menus
● Prebuilt to include all accessible items
● Configuration Key
● Normal Image
● Label
So that's why it's used in the runnable class. Now, in between these two brackets I'll go ahead and paste in this line of
code, which is telling us to display an Infolog with the textual string message, hello AX world. So I'll go ahead and save
this. And what I want to do first is to right click this class for my project, and I'll choose set as startup object. Now, when
I perform my build, it will execute this specific class. So now, I can go ahead and press CTRL SHIFT B to perform my
build. Alternatively, we can right click the project and choose build. And we'll press the CTRL F5 key to actually run the
project. And we'll press CTRL F5, it performs a build first, and then it goes ahead and runs or executes that startup
object. We can see here our build has completed and we're getting this notification window from Internet Explorer. And
we can open up class runner. And it notifies us here that the class hello world has completed execution and here is the
message from our Infolog. The hello AX world. So that's a quick overview of how to create a runnable class with a
simple output message here in the Infolog. And we'll go ahead and look at some more examples of code snippets as we
go throughout this chapter.
Lesson 4: Intellisense
In this lesson, we will discuss IntelliSense. IntelliSense is a predictive typing tool that aids developers during the coding
process. It prompts the user for known methods and possible choices of elements directly from the AOT. IntelliSense
also helps ensure that items are being consistently used within your code. It also helps maintain consistent spelling of
elements. The features of IntelliSense may vary depending on the version of Visual Studio that you're running. So let's
go ahead and demonstrate a little bit about how IntelliSense works in the code editor. So I'm here in my runnable class
dbHelloWorld that we saw output this hello AX world message to the Infolog. Now, we can declare some objects to use
within our code here at the beginning of our static void main method. So I'll go ahead and begin typing. If I type the
word C-U-S-T for cust, you'll notice this popup appears with all these different objects in the system. This is IntelliSense
kind of predicting what we're typing. And if we scroll through, we can see there's many different objects. This little grid
icon represents a table. This CustAuditorTemp table. We have a lot of different classes. We also have extended data
types and enums would appear in this list as well. Anything that begins with cust. As I continue to type, it will continue
filtering down the list. So I can see if I typed a T, it recommends the cust table. So we can go ahead and hit tab or click it
from the list. And it will make that selection for us. And then we can go ahead and give it a reference in our code. So
let's see how it works with the base enum. So in our project, we have these four base enums right now. And if I type DB,
you can see it automatically makes that recommendation for the dbDriveType enum. I'll hit tab to complete that selection.
I'll give it an alias or a reference here to use throughout my code followed by semicolon. And now I can begin using that
enum in code. So if I type dbDriveType, followed by two colons, IntelliSense will show me the values that are available
of the different element values for that enum. We configured this enum to have the following drive types. So when you
are using your base enuming code, you use the double colon to signify you want to choose the value for that enum. So we
can have something like this. Obviously maybe we'd have this in a more complex kind of if statement to say if our drive
type is four-wheel drive, then perform some other logic.
We have a class called DevBasicsEDTSample. Within this class, we have a static void method and then we have three
lines of code. The first line declares our EDT, our EDT is a primitive data type string. It's called DBVehicleType in the
system. Directly next to it, we specify an alias or a reference for this DBVehicleType EDT. This is what we're going to
refer to as going forward in our code. In the next line, we set the value of an EDT to the world truck. We then specify to
output an info box and pass through the value of our EDT vehicle type.
So I've gone ahead and pasted the code from our slide directly here into our runnable class. I'll press CTRL S which
performs a save and also checks our syntax and logic to make sure there are no errors. So this code looks good to go.
There were no red underlines or errors, and now I can go ahead and press CTRL F5 to perform a build and we can see
how the output would look. So go ahead and do that. All right. So our build has completed. I'll now open up my
browser window for the class runner to verify the output, and here we can see we have a message of repeat customer.
Now, if we jump back into the code, we can see that our oil change variable is three. And this condition here, if it's
greater than or equal to two, can display the repeat customer message has been met. So that's why we're seeing that
message. OK. So now let's go ahead and demonstrate an example of a switch case. So we'll use the same code snippet
from our slide. And we'll paste it in here. And I'll go ahead and use the CTRL S keyboard shortcut to ensure there are no
errors in the code. And I'll try to tab things over to keep things lined up with our cases here. OK. So now we can go
ahead and use CTRL F5 to build this and verify the output. All right. So our build has completed. If I verify my class
runner output, we have a message of frequent customer. Now I'm going to flip back to the code in Visual Studio and we
can see that our switch case on the oil change variable which has a value of three met the default case here where answer
was set to frequent customer and then outputted to us in the info message. The case one was not true because oil change
is equal to three. And case two is not true because oil change again is equal to three and not two. So we had to output
based on the default case which handles every other scenario where the oil change is not one or two. In this example,
we're looking at a code snippet for a while loop. And this is the same code snippet from the slide that we discussed. And
I'm using my runnable class again as a basis to paste this code into a static void main method which is set as my project
startup object, which I execute by pressing CTRL F5. Now, this while loop again, we're initializing a counter variable of
called counter1 and setting it to zero. And then we're executing the while loop as long as that counter1 variable does not
equal four. As soon as it equals four, this condition is no longer true and, thus, the loop will stop executing. And we
increment our counter variable by one each time the loop goes through. So let's go ahead and press CTRL 5 to perform a
build and run our class here and verify the output. So our build has completed. We can go ahead and verify the results by
launching the class runner window. And we can see here on the info output it has a value of three. However, if we go to
the right, it's telling us there are four different outputs with a down arrow. We can click that and we can see we have zero
outputted, then we have a next line with the value of one. The next output has two and the final output has three. We
have four results from that loop. It went through the loop four times, first on the value of zero, and as we incremented our
counter variable, it continued to execute and print these lines until it reached the value of four, at which point it did not
enter the loop and, therefore, we do not see the value of four outputted in our messages here. In this example, we're
looking at a code snippet for a for loop. Again, this is the same piece of code from our slides that we discussed. And I've
pasted this for loop here into my static main method in my runnable class called dbHelloWorld. And what I want to do
first again is press CTRL S. This performs a save. It's the same thing as clicking this little disk icon here. And the save
also goes through and checks for any syntax and logic errors that we need to be made aware of before we can run this
class. So it's looking good. There are no errors. Again, to run this, I'll go ahead and press CTRL F5. And it will perform
a build and execute this class. So again, we can verify that our build has completed. And if I go to the Internet Explorer,
I'll see my class runner window that has executed this for loop. And again, we have this drop down arrow which indicates
there are four more messages. Currently it only displays three at a time so we have to use the scroll bar to make sure we
can see all of them. And the output is counter to zero for the first line. Then it continues. Counter2 is one. Counter2 is
two. And counter2 is three. So it's similar to the output from our while loop in the sense that it outputted the values of
zero through 3 and stopped the execution as soon as the value of four was hit for the counter variable and does not
therefore print the value of four. Now, we noticed this one includes the text counter2 is. We can go back to our code and
see that in our Infolog where we're sending out this sentence that says counter2 is. And again, this percent one is replaced
by the first variable after the comma. If I were to go in here and type something like also percent two, and then I placed a
comma after this counter2 variable, and if we had another variable declared, you know, counter3, for example, this value
for counter3 would then be outputted here in place of percent two since it's the second value or the second variable after
the commas. So that's something to keep in mind when outputting using the Infolog format.
Module Review
In this module, we explored the code editor and created a runnable class. We then previewed how IntelliSense works and
introduced variable declaration. Next we reviewed basic syntax, keywords, and operators to use in X++. We then
discussed comparison tools and using the debugger in Visual Studio. Finally, we examined the best practices to use when
coding.
▪ Code Editor
● Visual Studio Environment
● CIL can efficiently reference classes that are available in other .NET assembly DLL files
● Compiler
● Standard compilation unit for X++ is same as other .NET languages, i.e. C#.
▪ IntelliSense
▪ Data Types
● Anytype
● Booleans
o Can only contain the values false and true
● Dates
● Enums
● GUIDs
● Integers
● Reals
● Strings
o Number of characters
● TimeOfDay
● Utcdatetime
● Arrays
● Containers
o All tables defined in the data base can be handled as class definitions
● Benefits of EDTs
● Properties set for EDT are used by all instances of that type, reduces work and promotes
consistency
● Can create hierarchies of EDTs inheriting the properties that are appropriate from the
parent and changing other properties
▪ Variable Declaration
● Easier readability
● Easier to find
▪ Key Operators
● Assignment operators
● =
● +=
o Assigns variable on left to the current variable value plus expression on the right
● ++
● -=
o Assigns the variable on left to the current variable value minus expression on the
right
● --
● Arithmetic Operators
● <<
● >>
● *
● /
● DIV
● MOD
● ~
● ^
● |
● +
● -
● ?
● Relational Operators
● Like
● !
o Not
● !=
● #
● &&
o Logical AND.
● ||
o Logical OR
● <
o Less than
● ==
● >
o Greater than
● >=
● Unary operators
o –
o ~
o !
o *
o /
o %
o DIV
o <<
o >>
o &
o ^
o +
o –
o |
● Relational, equality
o <
o <=
o ==
o !=
o >
o >=
o Like
o As
o Is
o &&
o ||
● Conditional
o ?:
▪ Basic Syntax
● Starting parenthesis on method declaration and calls should be the character just after the method
name (no space).
● If there are one or two parameters, the parameters can be listed on the same line.
● More than two parameters, move each parameter onto a new line, and indent by 4 spaces
● Break up complex expressions that are more than one line – make it visually clear
● Add one space between if, switch, for, while and the expressions starting parentheses.
● Use braces around all code blocks, except for around case clauses in a switch statement
● Use braces even if there is only one statement in the block
● Basic Output
● Create a box
● If and if…else
● Switch
● While
● Do while
● For
▪ Comparison Tools
▪ Debugger
● Infolog
● Autos window
▪ Best Practices
● Naming Conventions
● Code Placement
● Comments
Lesson 4: Methods
In this lesson, we will review methods. Method declarations consist of a header and a body. The method header declares
the name and return type of the method. The return type could be void which indicates that there is no value being
returned from that method. The method header also contains parameters and method modifiers. The method body
consists of variable declarations, method declarations, and code statements. Let's review some of the main types of
methods. A class declaration specifies the name of the class and the necessary variables. It can also specify if inheritance
is going to be used. Instance methods or object methods are embedded in each object that is created from the class. They
are called by using the syntax objectname.methodname, and then followed by parentheses. You must instantiate the
object before you can use the method. Static methods are also known as class methods. And they belong to a class and
are created by using the keyword static. They are called by using the syntax class name colon colon method name and
then the parentheses. You do not need to instantiate an object before you use static methods. Static methods are widely
used in AX to work with data that is stored in tables. And lastly, we have main methods. A main method is a class that is
executed directly from a menu option. A good example of this is the static void main methods we've been using in our
runnable classes. The method should only create an instance of the object and then call the necessary member methods.
The underscore arch parameter allows you to transfer data to the method. So I've added some code to our
dbfmVehicleEntry base class that we created earlier in this module. This code creates a dialog box or a quick entry kind
of form that takes a user's input values and uses them to insert data into the underlying table, so that eventually we can see
that data on our VehicleListPage form. So let's go through this code and see what's going on.
We have our class called dbfmVehicleEntry. At the beginning, we're creating a dialog object and we're creating dialog
fields. Three of them. And then we're also instantiating our dbVehicle table and giving it the reference called vehicle
table. We have several methods within this class. The first one here is the void method of main. Now, the main method
instantiates our class dbfmVehicleEntry and we're giving it a reference of a new name called VehicleEntry to be used
within our code. And then we set an equal to and we use the new operator which tells us to go instantiate a new instance
of our class, dbfmVehicleEntry, and then we call our class VehicleEntry.run. So we're calling the run method on our own
class here. So if we go down to the run method here on line 23, we can see it's a public method of type void. The void
indicates it does not return a value. It's just performing some logic here. We will discuss what the public keyword means
in the best practices lesson on this module. It's essentially a scope, so we're saying that the variables and methods within
this particular method can be accessed by outside classes and methods. So the first thing this run method is doing in our
class is calling another method called setupDialog. We use this keyword to reference that the setupDialog method is in
this class. So we call this .setupDialog. And our setupDialog is located right here, and this method is also void, which
means we're not returning any values. What the setupDialog does is create the dialog box, the dialog window. And we
have these three different dialog fields that we created up here. They are all of the object type dialog field, simply with
different names. So we have three dialog fields, one for the vehicle make, one for the vehicle model, and one for the VIN
number. Now, we're using the dialog.add field and we're calling -- we're using the extended type of string. So we're
saying these DB VIN, make and model feeds are not extended data types of string. After the comma, we're specifying
what to put them -- what label value to supply for the dialog window for each of these fields. So again, the field in
parentheses is our actual field that we're using from our table, the DB make, the DB model, and the DB VIN. OK. So if
we go back to our run method, we'll continue walking through this step by step. We have the dialog.run method which
now runs our dialog. We have our three fields created on that dialog window. And then we have the dialog.wait method
which causes us to wait until we receive the user input. Then we execute an if statement to say once the closed or OK
button was chosen on the dialog, to go ahead and execute this logic. So when the dialog has been closed and the values
have been supplied, we call a method called getFromDialog. And that method is right here. It's also a void method.
Now, the getFromDialog method, we're creating three string values within our code, make, model, and VIN, and we're
setting each of those to be equal to the value typed in on the dialog box in each of the respective dialog fields. We then
set our vehicle table buffer variable fields to be whatever the user typed in here in the dialog box. And then when we go
back up to our main method, or our run method, after the getFromDialog, the next line of code is VehicleTableInsert. So
then, we have these values passed in the dialog box. They've been assigned to our buffer variable, our vehicle table, and
now we're going to insert them with the vehicle table that insert method command. And this is the insert method on the
table. OK. So that's a quick walk-through of what these different methods are doing. Let's go ahead and press CTRL F5
to run this and see how the dialog.entry form works. So I'll go ahead and press CTRL F5 to build and run this class.
Keep in mind, I have set this as my startup class, or my startup object, so that when this project builds and executes, we
will see the output from this particular class. OK. So we verify that our build has been completed here. And we can go
ahead and open up our class runner window.
And here, we have our quick VehicleEntry form with our three dialog fields that the user can type in, supply values, and
choose OK. And that's ultimately going to insert them into our vehicle table. Now, we can see here in this void new
method, we're setting the new dialog and then we're supplying the label here and that's where we get in heading from. So
let's go ahead and type some information in this dialog box. Now, here, I have our VehicleListPage pulled up in the UI. I
went ahead and just entered in some random data here, just to give us something to look at. Then when we supply some
values here on our dialog, we should be able to see those appear then on our VehicleListPage. OK. So let's go ahead and
just make up some information, so we'll call this a Lincoln, and we'll call this an MKX. And we could just make up a
number for the VIN, and let's go ahead and hit OK. All right. Now, when we come to our list page over here and refresh
it, we should be able to see that record we just typed in the dialog be visible. OK. There it is at the bottom of the table,
we typed in Lincoln MKX. And this particular form actually does not show the VIN. However, if we had that set up,
then we would also see that value.
Module Review
Thanks for joining me in the classes module. We reviewed the structure of a class and the use of methods as well as the
different types of methods. We then demonstrated how a base class can use the concept of inheritance, and then we
created a child class to inherit from that base class. Finally, we reviewed the best practices for using classes.
▪ Class Structure
● Class Construct
● Blue print
● Instance method
● Work order
● Useable code
▪ Methods
● Class declaration
● Instance methods
● Objective methods
● Static methods
● Class methods
● Main methods
▪ Class Inheritance
● Objects created from Child have same methods and variable as Parent
● Objects created from Child may have methods and variable that do not exist in Parent
● Objected from Child may have methods from parent that are overridden or altered
● Best practices
● Clean up code
● Protected
● Private
● Public
We also have options to order our results or group our results. We can have them be ordered ascending or descending and
we can have them grouped by specific fields. So if we want to select all records from the cust table ordered by customer
account number, ascending, we can certainly do that with the select statement. We also have the WhereClause and the
JoinClause with specified conditions on certain records that we want to return. For example, we can select all records
from the cust table where a customer lives in a certain state. We would say where the state field equals, and then we
could put in quotations the name of the state. The JoinClause allows to join to other tables. So we can construct a query
similar to how one would construct a query in SQL or we can select data from a table and join it to another table. While
select statements are used to handle data, they're the most widely used form of the select statement in X++. While select
loops over many records that meet a certain criteria, if we were to specify in a WhereClause, and they can execute a
statement on each record that they loop over. In a while select, the select statement itself is executed only one time,
immediately before the first iteration of the statements in the loop. Also any expressions such as counter, less than one,
that are added to the while select are only tested one time. This differs from how the while statement behaves in other
languages such as C++ and C#. When you perform data manipulation by using the while select statement, you would
typically do this in a transaction to ensure data integrity. Let's consider the following sample while select statement.
In this code snippet, we have declared two tables that we'll be using in our code. The custTable and the dirPartyTable.
These are the aliases or the references that we're going to be referring to these tables as in the code below. We have a
while select statement and we are selecting the dirPartyTable and ordering it by the name column. Now, notice here we
didn't say while select name from dirPartyTable order by name. We could do that. However, we can also simply say
while select table name to select each record one by one from that table. And the results are going to be ordered by the
name field. It's important to keep in mind the order of these clauses. After our select statement, we perform our orders
and group bys, and then we perform our joins and where clauses. So in this example, after we specify to begin selecting
records from the dirPartyTable ordered by their name, we join the custTable, and in the where statement, we specify this
criteria to perform this join on. So we're joining the custTable where the custTable.Party field is equal to our
dirPartyTable.recID field. And these are related fields that we can use as lookups between these two tables. So it's going
to give us records from both tables and loop over each one where there exists a record in each one for the party in recID
field. And then once we're inside this loop, for each record, we're going to display an info message that includes the
dirParty name followed by a comma and then followed by the customer account number. So let's go ahead and take a
look at how this will output in our development environment. I have pasted in our code snippet that we just analyzed on
our slide here. And again, we're declaring these two tables to use in our while select statement. We're selecting every
record from the dirPartyTable one by one, ordering them by name, and then we're joining the custTable on this mutual
field of custTable.Party and dirParty.recID. And then we're going to output each line the dirPartyTable.Name field
followed by a comma and then the customer account number. So I'm going to go ahead and press CTRL F5 to run this
class. Again, this is a runnable class that I've set as my startup object in my project. Therefore, when I press CTRL F5, a
build will be performed and the class will be ran. I'll go ahead and do that now. And the build process will start. So our
build process has completed. I'll open up my class runner window in the AX client. And we can see here, we have 30
records that were outputted. If I click the drop down here, you can scroll through them one by one, and we have our
dirPartyTable.Name field here followed by the comma and the associated customer account number with that customer.
We can go ahead and scroll through these one by one and we'll notice that the name field that we specified in our while
select to be ordered by the name is indeed ordered by the name. So here at the beginning, we have Birch Company and
we continue to scroll up through our records that were outputted in the loop and we can see that name field is in
alphabetical order.
Module Review
Thanks for joining me in the database manipulation module. In this module, we covered how to retrieve and review
records. We explained the transaction tracking system and discussed the best practices to use when updating data. Then,
we reviewed how to insert, update, and delete data using X++ code.
▪ Database Retrieval
● Select statement
● Fetching additional records with the “next” and “while select” statements
● Loops over many records and can execute statements on each record
● In a while select, the statement is executed only one time, immediately before the first
iteration of statements in loop
● When performing data manipulation using the whole select statement, you would
typically do this in a transaction to ensure data integrity
● Ttscommit
● Ttsabort
● Used as exception to abort and roll back transaction to state before ttsbegin
▪ Data Insert
● Only specified columns of rows selected by query are inserted into named table
● Table columns being copied from and those of the table being copied to must by type compatible
▪ Data Updates
● Update command modifies existing data in table with contents of table buffer
● Before records can be updated, use “select forUpdate” to exclusively set record for update
▪ Data Deletion
● Use this method, specify which rows are to be deleted by using a where clause.
● Delete method can be overridden, for example, to add extra validation before records are deleted.
MODULE 14: YOUR NOTES
Module 15: Exception Handling
Welcome to Module 15 on exception handling. The objectives in this module are to define the different exception types,
to discuss the key commands to use in X++ code, to review the code statements for exception handling and to create a
try/catch statement.
And within our run method, we're creating a dialog object with the heading that says create new customer and it's going to
have two dialog fields. The user can input values for the customer account number and the customer group number and
then we're going to set those values or insert those values into our customer table. However, first, we're going to make
sure -- we're going to perform this validation using a try/catch statement. So we have an if statement that says if the
dialog object is running, we go ahead and call our try statement. The try statement encapsulates everything within the
opening and closing brackets so the opening bracket is here. The closing bracket is in another segment of code on the
next slide. So at the beginning of this try statement, we're simply assigning the value inputted in the dialog box by the
user to our custTable AccountNum field and then the same thing for the CustGroup field in the custTable. Now, in the
following slide, here's the ending closing bracket for our try statement.
Therefore, all of this is included. And we have another if statement here that's calling the ValidateWrite method on the
custTable. Now, the ValidateWrite method ensures that the data being inserted is able to be written correctly, that it
passes the validation tests. For example, it has the required mandatory fields for that table. Now, we have an exclamation
point preceding this method call which means if not, if the ValidateWrite method does not pass, then we're going to throw
this error. It's an exception of type error and output the message please enter all required fields. If, however, this
ValidateWrite method passes, we skip this if logic and we go directly to our else statement. And from there, we simply
insert the records because they're already validated. Now, below our try statement, after the closing bracket, we have a
catch statement. And the catch statement is looking out for an exception of type error. And when this throw error comes
through, if the ValidateWrite method does not pass, it will get caught in our catch statement. Therefore, we will see an
error message outputted that says an error occurred, please try again. In this demonstration, we're going to look at a
try/catch statement to handle errors in our VehicleEntry form. So what I have created here is a new class called
dbfmVehicleEntry with exceptions.
And it's identical to our VehicleEntry class that we saw in the previous example that takes in these three different dialog
fields for vehicle make, model, and VIN, and then ultimately attempts to insert them into the vehicle table. The only
difference in this class is that we've changed the heading for demonstration purposes to quick VehicleEntry form with
VIN validation and we've added our actual validation here in the getFromDialog method. In our getFromDialog method,
we have our try statement here. And it's encompassed in between everything in between these two set of brackets, so all
this code is in our try statement, and then we have our catch statement immediately afterwards. So in our try block of
code, we have our three variables for make, model, and VIN that we are assigning the value from the input on the
respective dialog fields. And we begin our validation with an if statement. And what this if statement says is if the string
length for the VIN variable or field is less than 17 characters, we will throw an exception of type error with the message
please enter a valid VIN number. We have the else statement which handles the situation where this if condition is not
true. So if we have a valid VIN number that is 17 characters or greater, this statement here will not execute. It will go
immediately to the else block where we will assign those variables to our table buffer for the make, model, and VIN, and
ultimately call the insert method to insert the data into our vehicle table, since the criteria was met for validation on the
VIN length. Now, again, if the VIN string length is less than 17 characters, it will throw this error message, and then our
catch statement here is looking for an exception of type error. Once it finds that exception of type error from this throw
message, it will also execute this block of code here which is an error statement that says an error occurred, please try
again. So if we attempt to insert a VIN field with less than 17 characters, we should observe this error message here in
addition to this error message here. Now, we'll notice this exception. We mentioned this is a system enum. So just to
demonstrate how this works, if I use the double colon right after the exception, IntelliSense will populate a list of the
different exception types I can choose from for this system enumeration. Now, we're using error for this example, so I'll
just leave that. You'll also notice we have these breakpoints inserted in this class here. So in this gray pane on the left, we
have the red dots and we can add these simply by clicking a line and then clicking again to remove. Additionally we can
use a shortcut key of F9 to insert breakpoints. Now, when I run this code, we're going to use two different scenarios. In
the first scenario, we'll enter a VIN number with less than 17 characters to observe the errors and how our try/catch
statement handles those. And then we'll attempt to insert a VIN with a valid string length of 17 or 18 characters at which
point the data should be inserted into our vehicle table. Now, to begin the debugger, I launch our code from our first
breakpoint here which is the call to the getFromDialog. We press F5. In previous examples, we've been running all of
our classes or forms using the CTRL F5 shortcut key which runs the project without debugging. And you'll notice if we
click the debug menu, we can start debugging and it has the F5 as the shortcut key, or we can start without debugging.
Additionally, we have the shortcut keys of F10 and 11 to step through our code while we're in the process of debugging.
So I'll go ahead and press F5 to start the debugging process and we can step through the breakpoints and observe how this
code is executing. OK. So now, we are in debugging mode and we can see our lines of code that have breakpoints have
kind of been highlighted here in this maroon color. So what's happened is the code has executed all of this code so far,
and it comes to my first breakpoint and now stops. And we can observe that our class runner has executed this code, and
now we have our quick VehicleEntry form with VIN validation opened.
And we're stuck here on this call to the getFromDialog method. So I'll go ahead and enter some data here. And then we'll
proceed stepping through the code and see how the validation will occur. For my VIN number, I'm going to type in a VIN
with a character length of 16. So this should throw an error. So we'll press OK. And it's going to begin processing so I
can go ahead and use the F10 key to step through my code. And we can see now it's highlighted in yellow with a little
yellow arrow here in the left pane to show me which line of code I'm on. So I've pressed F10. Now I come to my if
statement where we are performing this comparison. I'll press F10 again. It's going to continue going through the lines of
code one by one each time I press the F10 key. And we can see it hit this throw error line. It then came directly to the
catch statement. We did not enter this else criteria since our string length was less than 17 characters. So I'll keep
pressing F10 until I reach the end of my code. OK. So now we've started back through again at the beginning. I'll press
the little stop button here. We can also use the shift F5 shortcut key to stop the debugger. Now go back to my class
runner, and here we have our error messages.
There's a drop down to indicate that there are two messages. The first, please enter a valid VIN number from our throw
error statement, and the second, an error occurred, please try again, from our catch statement. So that data was not
inserted into the table. Now we're going to walk through an example of where our VIN number has a valid string length
of 17 characters or greater and, therefore, will pass our try/catch validation. So again, we're here in the same class and
I've already pressed F5 to enter our debug mode, and we can begin stepping through this step by step. So since I'm in the
debug mode, all of my code from the beginning of the class is executed up until this very first breakpoint on the call to the
getFromDialog method. So that means our class runner has opened, and we can begin entering values into this dialog. So
I'm going to try again with a Ford Mustang. And this time the VIN number is going to have 18 characters. So I'll pipe
this up to eight again. So that's 18 digits. And we'll press OK. And it's going to begin executing the code. So again, we
notice this yellow highlighted line on the call. And we'll press F10 to step through and we'll follow along. Now we're in
our if statement. OK. So we can see it skipped over this throw error code because it met the criteria for the else statement
which is 17 characters or greater. Now, if I keep pressing F10, it will go through these three lines of code to assign our
variables. And ultimately, this line here where it's going to insert the data into our table. It skips over the catch statement.
It does not execute that code since there was no exception of error thrown. OK. Now, that completes the walk-through of
those blocks of code. I can go to my class runner now and verify that this has been inserted into our table. So now we'll
go ahead and stop debugging so I'll go back to Visual Studio. And stop the debugging process. We'll go back to our class
runner and we can see that the class has completed executing. There are no error messages to display. So let's go to our
VehicleListPage form here and we'll refresh it to see if that record for the Ford Mustang was indeed inserted. And here
we have it. So we didn't set a vehicle like D on that form, but we did insert the Ford Mustang into the underlying table,
and it has a VIN number associated with it that is valid.
Module Review
Thanks for joining me in the exception handling module. In this module, we covered the different exception types. We
discussed the key commands in X++ to use with exception handling. We then reviewed some code samples and
demonstrated the functionality of a try/catch statement.
MODULE 15 KEY TAKE AWAY
o Exception Handling
▪ Exception Types
● Info
● Warning
● Deadlock
● Informs user that the system encountered a deadlock situation the database
● Error
● Numeric
● Indicates an error has occurred during the use of str2int, str2int64 or str2num functions
● Dderror
● Break
● Internal
● CLRError
● CodeAccessSecurity
● UpdateConflict
● UpdateConflictNotRecovered
● Indicates error has occurred in a transaction using Optimistic Concurrency control, and
that the code will not be retired
▪ Key Commands
● Try
● Catch
● Retry
● Finally
First, the user signs in to AAD, which is Azure Active Directory. Next, Azure Active Directory redirects to the Dynamics
AX client or the web application. And finally, the Dynamics AX start page is displayed. OData services, JSON-based
custom service, and the REST metadata service support standard OAuth 2.0 authentication. Certain applications can
consume AX web services. For example, PowerBI can consume data from the OData service. Microsoft Azure Active
Directory uses two types of authentication. The first is the native client application. This is the flow that uses a user name
and password for authentication. Next, is what's known as the confidential client or the web application, and this is an
application that can keep a client password confidential to the world. The basic flow in this diagram is that the first step is
outlining a user authenticating and consenting for access. The client would then receive an authorization token. This is in
step two. In step three, the client requests access to a resource with an authorization code. In step four, the client would
then receive an access token. In step five, the client requested data with this access token. And finally, in step six, the
client would then receive the data that it requested. The following diagram represents the security model in AX.
The security model is hierarchical, and each element in the hierarchy represents a different level of detail.
Permissions represent access to individual securable objects like menu items and tables. Privileges are composed of
permissions. And they represent access to tasks such as cancelling payments and processing deposits. Duties are
composed of privileges and represent part of a business process such as maintaining bank transactions. Both duties and
privileges can be assigned to roles to grant access to in AX. AX security is role-based. This means many security roles
and duties are provided to help base security definitions. Using role-based security, users are assigned to roles based on
their responsibilities in the organization. Instead of identifying and granting access to application elements, the
administrator assigns duties which users in the role perform. Because rules can be set up for automatic role assignment,
the administrator does not have to be involved each time a user's responsibilities change. After security roles and rules are
set up, role assignments are updated based on changes in business data. A single set of roles apply across all companies
and organizations. The administrator does not have to create and maintain a separate user group for each company. Even
though roles themselves are not specific to a company or organization, the administrator can still specify a company or
organization context for a particular user in a role. Let's take a closer look at how this structure and elements in security
work with each other.
Authentication for users can occur in Active Directory or Active Directory Federated Services, for example. The
authorization process for users includes security roles. Each user must have at least one security role but they may have
multiple roles. And each role we mentioned can have privileges and duties assigned to them. The privileges contain
permissions for application elements to perform a specific task on that element. Data security is implemented through
data security policies, record level security, and the table permissions framework. In the following screen shot, we're
seeing an example of the system administration users and user's page where we can see the details of a particular user.
Security roles that are assign to a user determine the duties that the user can perform and the parts of the user interface
that the user can view. Administrators can apply data security policies to limit the data that the users in a role have access
to. An example of this would be a user in a role may have access to data only from a single organization. The
administrator can also specify the level of access that the users in a role have to current, past, and future records. By
managing access through security roles, administrators save time because they do not have to manage access separately
for each user. Security roles are defined one time for all organizations. In addition, users can automatically be assigned
to roles based on business data. An example of this could be the administrator set up a role that associates a human
resource position with a security role. Anytime that users are assigned to that position, those users are automatically
added to the appropriate security roles. Users can also be automatically added to or removed from security roles based on
the Active Directory groups that they belong to. Security roles can be organized into a hierarchy. A role hierarchy
enables roles to be defined as a combination of other roles. For example, the sales manager role can be defined as a
combination of the manager role and the salesperson role. In the security model for AX, duties and privileges are used to
grant access to the program. For example, the sales manager role can be assigned to maintain revenue policies and review
sales orders duties. By default, sample security roles are provided. All functionality in AX is associated with at least one
of the sample security roles. The administrator can assign users to the sample security roles, modify the sample security
roles to fit the needs of the business, or create new security roles. By default, the sample roles are not arranged in a
hierarchy. The following screen shot shows an example of the system administration security and security configuration
page.
And from here, we have different tabs where roles, duties, and privileges can be assigned and configured. We talked a
little bit about security roles and we mentioned they can be assigned duties and privileges. We also have process cycles.
A process cycle cannot be assigned to a role. However, a process cycle is a business process that is coordinating a set of
activities in which one or more participants consume, produce, or use economic resources to achieve an organizational
goal. To help the administrator locate the duties that must be assigned to roles, duties are organized by the business
processes that they are a part of. In the context of a security model, business processes are referred to as process cycles.
An example of this is in the accounting process cycle, you may find the maintain ledgers and maintain bank transactions
duties process cycles used for organization only. The process cycles themselves cannot be assigned to roles. We also
discussed duties a little bit and we can see here in the screen shot how duties can be added to a specific role. Duties
correspond to parts of a business process. And the administrator assigns them to security roles. A duty can also be
assigned to more than one role. In the security model for AX, duties contain privileges. An example of a duty is the
maintain bank transaction duty, and it contains the generate deposit slips and cancel payment privileges within that duty.
You can assign related duties to separate roles. These duties are said to be segregated. By segregating duties, you can
better comply with the regulatory requirements such as those from Sarbanes-Oxley or the United States Food and Drug
Administration. In addition, the segregation of duties helps reduce the risk of fraud and helps you detect errors or
irregularities. Default duties are provided. The administrator can modify the privileges that are associated with the duty
or create new duties. We then have privileges. In the security for AX, a privilege specifies the level of access that is
required to perform a job, solve a problem, or complete an assignment. Privileges can be assigned directly to roles.
However, for easier maintenance, it's recommend that you assign only duties to roles. A privilege contains permissions to
individual application objects such as user interface elements and tables. An example of a privilege is the cancelled
payments privilege which contains the permission to the menu items, fields, and tables that are required to cancel
payments. By default, privileges are provided for all features in Dynamics AX. The administrator can modify the
permissions that are associated with the privilege or create new privileges. We also have the concept of permissions. And
in the security model for AX, a permission grants access to logical units of data and functionality like tables, fields, and
forms as well as server side methods. Only developers can create or modify permissions. For more information about
how to work with permissions, refer to the Dynamics AX developer documentation. We will discuss the data security
elements in more detail later in this module. The screen shot on the right shows the security configuration form where
administrators can create and edit roles and view the duties and privileges and so on that are related to one another. The
extensible data security framework in AX enables developers and administrators to secure data and share tables such that
users have access to only the part of the table that is allowed by the enforced policy. This feature can be used in
conjunction with role-based security to provide more comprehensive security than was possible in the past. The
extensible data security commonly abbreviated as XDS is an evolution of record level security that was available in
previous versions. XDS security policies, when deployed, are enforced regardless of whether data is being accessed
through the AX web interface, SQL Server reporting services reports, or other services. An XDS policy starts with a
query to define the filters or limits that should be placed on the primary table or tables. The data, that is. Then you will
create a security policy which is linked to the query and primary table that you want to restrict data for. Next, you will
define the context for the rule which could be based on a string for a role or group of roles. This could require additional
programming to function properly. Lastly, you can define the list of constrained tables which are related tables that store
data from the primary table that you're attempting to restrict a subset of data for. Several common design principles are
used when creating the base 80-plus roles. These design principles include the following.
Roles represent the common access rights that are required for the job positions within an organization. Roles account
for the organization size, culture, and industry focus. Users are assigned to one or more roles according to their job.
There are also different role types. For example, a functional role could be a warehouse worker. An organizational role
might be an employee. And an application role could be a system user. We also have role segregation categories.
Functional roles are designed to accommodate segregation of duties. Different categories of roles exist that each focus on
their own type of responsibilities. For example, validation. Clerks focus on recording transactions. Or verification.
Verifiers validate the correctness of recorded transactions. Another segregation category is authorization. Supervisors
authorize the processing of transactions. And then we could have management. Managers review transactions
periodically and apply changes to the process as needed.
Module Review
Thanks for joining me in the security basics module. We took a look at the architecture for authentication and the security
model in AX. We also looked at how to create new roles and duties from the Application Explorer in Visual Studio. And
lastly, we looked at key security related properties for buttons, table fields, form fields, and menu items in AX.
MODULE 16 KEY TAKE AWAY
o Security Basics
▪ Security Architecture
● AAD redirects to AX
● Security roles
o Determines duties user can perform and what they can view on interface
● Process cycles
● Duties
● Privileges
● Permissions
● Query
● Security policy
● Context
● Constrained tables
● Role types
o Functional role
o Organizational role
o Application role
● Button Properties
● Needed permission
● Needs record
● Table Fields
● Allow edit
● Mandatory
● Minimum read access
● Forms Fields
● Allow edit
● Needed permission
● Mandatory
● Menu items
● Correct permissions
● Create permissions
● Delete permissions
o Specifies name of another object who’s permissions are applied to this menu item
● Read permissions
o Specifies whether read permission will be available to select when privileges are
assigned to this menu item
● Update permissions
o Specifies whether update permission will be able to select when privileges are
assigned to the menu item
MODULE 16: YOUR NOTES
Module 17: Introduction to Advanced Topics
In this module, we're going to introduce at a high level some of the more advanced features and capabilities of AX. The
objectives for this module are to review the business intelligence features, to review the reporting framework, to explain
the services and integrations, and to define and create data entities.
Module Review
Thank you for joining me in the introduction to advanced topics module. We reviewed some of the exciting BI features
like KPI modeling and integration with PowerBI. We then discussed reporting capabilities, financial reporting, as well as
services and other integrations. Finally, we reviewed types of data entities and their different uses.
▪ Business Intelligence
● BI Features
● Types of BI
● Contextual BI
● Embedded BI
● Self-Service BI
● Power BI Integration
● Data refresh and mobile access
● Dynamics data
o Feeds
o Export
o Pre-built
● Insights in Excel
o Discover
o Analyze
o Visualize
● Collaborate in PowerBI.com
o Share
o Find
o Mobile
● Embed in Dynamics
o Pin
o Launch
o Act
▪ Reporting Services
● Overview
● Simplified development
● Simplified administration
● Development Process
● Parameterized views and drill-through navigations to other AX pages and other reports
● Financial Reporting
● Overview
● Office Integration
● Export to Excel
● Workflows
● Consistent processes
● Process visibility
● Centralized work list
▪ Data Entities
● About
● De-normalized View
● Customer
o Account number
o Customer group
o Bank account
● Party
o Party number
o Name
● Address
o Postal address
o City
● Electronic Address
o Phone
o Email Address
o Fax
● Customer Entity
o Account number
o Customer group
o Bank account
o Party number
o Name
o Primary email
o Primary fax
● Parameter
● Reference
● Master
● Document
● Transaction
● Synchronous services
● Asynchronous integration
● Data migration
● Business intelligence