Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 195

Reference Companion Guide

Course 80730 Development Basics in Microsoft


Dynamics AX

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

Module 1: Introduction to Visual Studio 7

Lesson 1: Module Overview 7

Lesson 2: Fleet Management Scenario 7

Lesson 3: Setup and Configuration 7

Lesson 4: Terminology and Concepts 8

Lesson 5: Naming Convention 8

Lesson 6: Navigation 8
Lesson 7: Projects, Models, and Packages 10

Lesson 8: Using Elements 12

Lesson 9: Performing Builds 13

Module Review 14

MODULE 1 KEY TAKE AWAY 14

MODULE PRACTICE 15

Practice 1.1: Configure Visual Studio 15

Practice 1.2: Create a Project 16

Practice 1.3: Create an Element 17

Practice 1.4: Build and Compile 18

Module 2: Architecture 20

Lesson 1: Application Stack 20

Lesson 2: Server Architecture 20

Lesson 3: Cloud Architecture 21

Module Review 21

MODULE 2 KEY TAKE AWAY 21

Module 3: Labels and Resources 24

Lesson 1: Labels 24

Lesson 2: Fleet Management Scenario 24

Lesson 3: Create and Use Labels 24

Lesson 4: Search Labels 25

Lesson 5: Best Practices for Labels 25

Lesson 6: Resources 25

Lesson 7: Create and Use Resources 25

Module Review 26

MODULE 3 KEY TAKE AWAY 26


MODULE PRACTICE 27

Practice 3: Create Labels 27

MODULE 3: YOUR NOTES 29

Module 4: Base Enumerations 30

Lesson 1: Fleet Management Scenario 30

Lesson 2: Create a Base Enumeration 30

Lesson 3: Best Practices 31

Module Overview 32

MODULE 4 KEY TAKE AWAY 32

MODULE PRACTICE 33

Practice 4: Create Base Enumerations 33

MODULE 4: YOUR NOTES 36

Module 5: Extended Data Types 37

Lesson 1: Fleet Management Scenario 37

Lesson 2: Primitive Data Types 37

Lesson 3: Create an EDT 37

Lesson 4: Best Practices 39

Module Review 39

MODULE 5 KEY TAKE AWAY 39

MODULE PRACTICE 40

Practice 5: Create Extended Data Types (EDTs) 40

Module 6: Tables 45

Lesson 1: Fleet Management Scenario 45

Lesson 2: Create a Table 45

Lesson 3: Adding Data Types 46

Lesson 4: Key Properties 47


Lesson 5: Table Inheritance 48

Lesson 6: Temporary Tables 49

Lesson 7: Queries 49

Lesson 8: Best Practices 50

Module Review 52

MODULE 6 KEY TAKE AWAY 52

MODULE PRACTICE 54

Practice 6.1: Create Tables 54

Practice 6.2: Create Queries 56

Module 7: Table Indexes 59

Lesson 1: Fleet Management Scenario 59

Lesson 2: Index Types 59

Lesson 3: Create an Index 59

Lesson 4: Best Practices 60

Module Review 60

MODULE 7 KEY TAKE AWAY 61

MODULE PRACTICE 61

Practice 7: Create an Index 61

Module 8: Table Relations 64

Lesson 1: Fleet Management Scenario 64

Lesson 2: Relations 64

Lesson 3: Creating a Relation 65

Lesson 4: Best Practices 65

Module Review 66

MODULE 8 KEY TAKE AWAY 66

MODULE PRACTICE 66
Practice 8: Create a Table Relationship 66

Module 9: Form Patterns 69

Lesson 1: Form Patterns and Sub-patterns - Part 1 69

Lesson 2: Form Patterns and Sub-patterns - Part 2 70

Lesson 3: Form Patterns and Sub-patterns - Part 3 72

Lesson 4: Layout Properties 73

Lesson 5: Check Form Pattern 74

Module Review 75

MODULE 9 KEY TAKE AWAY 75

Module 10: Form Creation 78

Lesson 1: Fleet Management Scenario 78

Lesson 2: Create a Form 78

Lesson 3: Form Controls 78

Lesson 4: Adding Elements 80

Lesson 5: Best Practices 83

Module Review 83

MODULE 10 KEY TAKE AWAY 83

MODULE PRACTICE 84

Practice 10.1: Create Forms 84

Practice 10.2: Adding Elements 85

Module 11: Menus 89

Lesson 1: Fleet Management Scenario 89

Lesson 2: Creating Menu Items 89

Lesson 3: Creating Menus 90

Module Review 92

MODULE 11 KEY TAKE AWAY 92


MODULE PRACTICE 93

Practice 11.1: Create Menu Items 93

Practice 11.2: Create a Menu 94

Module 12: X++ Overview 98

Lesson 1: Fleet Management Scenario 98

Lesson 2: Code Editor 98

Lesson 3: Create a Runnable Class 98

Lesson 4: Intellisense 99

Lesson 5: Data Types 99

Lesson 6: Variable Declaration 100

Lesson 7: Key Operators 101

Lesson 8: Basic Syntax - Part 1 102

Lesson 9: Basic Syntax - Part 2 104

Lesson 10: Comparison Tools 105

Lesson 11: Debugger 105

Lesson 12: Best Practices 106

Module Review 107

MODULE 12 KEY TAKE AWAY 107

MODULE PRACTICE 112

Practice 12: Create a Runnable Class 112

Module 13: Classes 114

Lesson 1: Fleet Management Scenario 114

Lesson 2: Class Structure 114

Lesson 3: Create a Base Class 114

Lesson 4: Methods 114

Lesson 5: Class Inheritance 116


Lesson 6: Best Practices 117

Module Review 118

MODULE 13 KEY TAKE AWAY 118

Module 14: Database Manipulation 121

Lesson 1: Fleet Management Scenario 121

Lesson 2: Data Retrieval 121

Lesson 3: Reading Records 122

Lesson 4: Transaction Integrity Checking 123

Lesson 5: Data Insert 124

Lesson 6: Data Updates 126

Lesson 7: Data Deletion 127

Module Review 127

MODULE 14 KEY TAKE AWAY 128

Module 15: Exception Handling 130

Lesson 1: Fleet Management Scenario 130

Lesson 2: Exception Types 130

Lesson 3: Key Commands 130

Lesson 4: Code Statements 131

Module Review 133

MODULE 15 KEY TAKE AWAY 133

Module 16: Security Basics 136

Lesson 1: Security Architecture Overview 136

Lesson 2: Create a Role 138

Lesson 3: Create a Duty 139

Lesson 4: Security Properties on Key Elements 139

Module Review 140


MODULE 16 KEY TAKE AWAY 140

Module 17: Introduction to Advanced Topics 144

Lesson 1: Business Intelligence 144

Lesson 2: Reporting Services 145

Lesson 3: Services and Integration 145

Lesson 4: Data Entities 146

Module Review 147


Module 0: Fleet Management Case Study
Throughout this course, we're going to progressively build upon the Fleet Management scenario. As we proceed through
the different lessons we will develop the case study further and further with
business requirements, demonstrations, and examples for each module.
The Fleet Management case study is a scenario designed to give you exposure to the main components and elements of
the development environment and Visual Studio. For our scenario, we have a company called Contoso Entertainment
Systems USA. They're going to extend their operations to manage their internal fleet of vehicles.
In order to meet the business requirements, developers at Contoso will modify the application to meet those needs. At a
high level, the system will be used to track all fleet vehicle information
and service and maintenance of those vehicles.
So, in the screenshot, we have two tables and one is going to be a general vehicle table that contains information like
make, model and VIN number. Another table will have maintenance information, such as the type of maintenance, date of
service, parts used and so on.

Module 1: Introduction to Visual Studio

Lesson 1: Module Overview


Welcome to the first module of the course. In this module, we will introduce the development environment in Visual
Studio. Let's begin by reviewing the objectives. The objectives for this module are configuring and setting up the
development environment; defining important terminology and concepts; demonstrating basic navigation within Visual
Studio; creating projects, models, and packages; creating and using elements; and finally, building elements for use within
the system.

Lesson 2: Fleet Management Scenario


In this lesson, we will discuss the fleet management scenario for the introduction to Visual Studio module. For the fleet
management scenario, we need to complete the following five tasks. First, we'll configure the Visual Studio environment
for AX development. Second, we'll create a new packaging model. Third, we'll create a project within that model to hold
our elements. Fourth, we'll create an element within that project. And fifth, we will build that project. The scenario is as
follows: Simon, the system developer for Contoso, is tasked with creating a new module for the fleet management system
in Visual Studio.

Lesson 3: Setup and Configuration


The first time you use Visual Studio to develop with AX, you will need to complete some basic configuration. In this
lesson, we'll look at some settings to configure before we can begin using Visual Studio. First, let's take a quick look at
some of the system requirements for using Visual Studio to develop with AX. The first thing to note is it can be hosted
locally or in the cloud using Microsoft Azure. Secondly, a minimum of 16 gigabytes of RAM is recommended along with
two CPU cores for a smooth development environment. However, the more RAM and CPU cores you have will translate
into faster compile times. There are a few settings we want to configure in Microsoft Visual Studio that will make the
development experience with AX a little smoother. The first option we want to set is to organize projects by element
type. To do this, we'll go to the Dynamics AX menu and we'll choose options. In the left navigation pane, under the
Dynamics AX group, we want to expand that and choose projects. The first checkbox says organize projects by element
type. We want to make sure this is checked so that when we create projects and we add elements, they're organized and
easier to find. The next setting from the same options is in the text editor group. So we'll expand this and we'll go to all
languages. We want to make sure that line numbers checkbox is enabled so that in our text and code editors, we can see
the line numbers. This makes it easier for development and debugging. The next setting is in the IntelliTrace group. So
we'll click the root node on the IntelliTrace group and we'll uncheck this enable IntelliTrace option. We do not want this
enabled because it's not supported with X++ debugging and it could cause performance issues. So we'll uncheck this and
choose OK and then we'll restart Visual Studio to make sure our changes are taking effect.

Lesson 4: Terminology and Concepts


In this lesson, we will discuss the terminology and concepts related to the development environment in Visual Studio.
Four main components to understand in Visual Studio include elements, models, projects, and packages. Here, we're
looking at a screen shot of the Application Explorer. Within it, there's an AOT node. All of the sub-nodes below the
AOT node are different models. This is called model view. We can switch between model view and classic view by right
clicking this AOT node and selecting the appropriate view. Each of these models contains its own set of system elements.
If we expand one of them, we would then see the underlying elements such as data types, tables, and classes that relate to
that model. The package name that the model resides in is located in parentheses to the right of the model name.
Elements in Dynamics AX are the objects that reside in the AOT and the Application Explorer. Some examples of
elements are tables and forms. Collectively, these elements are what define the system and dictate what the user will see
in the front end. Elements can be customized once they are added to a specific project or model. A Dynamics AX model
is a group or collection of elements that represent a distributable software solution. A model is a design time concept.
For example, there could be a model on warehouse management or fleet management. A particular model may contain
multiple Visual Studio projects. However, a project may only belong to one model. A Dynamics AX package is a
deployment unit that may contain one or more models. In addition to elements, it includes model metadata, which is
description data that defines the properties and behavior of the model. A package can be exported to a file which can then
be deployed into a staging or production environment.

Lesson 5: Naming Convention


In this lesson, we'll discuss best practices for naming your elements in projects. When naming elements, it's a best
practice to use camel case. For example, in our development basics fleet management example, we'll prefix our elements
with DB. So we can have an object like DB table name or DB class name. We also want to make sure we're maintaining
consistency throughout the model and throughout the system so that our elements are easy to locate and easy to find when
we need to edit them. We also want to avoid reserved keywords. These are words the system uses. And lastly, we want
to prefix with a company name or a project name so that, again, things are easier to find in the system. For example, if we
are creating elements related to a customer, we can prefix them with cust. So we're going to prefix our development basic
elements with DB. So for example, when we create the dbVehicle table later in the course, we'll call it dbVehicle. We're
going to adhere to this prefixing convention when creating additional elements for our fleet management project such as
forms, classes, extended data types, and so on. In addition to prefixing element names, it's also wise to prefix company-
specific elements. For example, if you have multiple companies, it makes them easy to identify which company those
elements belong to.

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.

Lesson 7: Projects, Models, and Packages


We've looked a little bit at how projects and models work with each other in the Visual Studio development environment.
Now let's look at how to create model to use for our fleet management scenario. We defined a model as a collection of
elements that represent a distributable software solution. Creating a model involves specifying metadata like the model's
name and description. We can create a model using a wizard. And when we create a model, we have the option to choose
whether we want to create that model in a separate package or in an existing package. These two choices will determine
the development approach that we'll be using. If we create a model in a separate package, that implies we will be using
the extension development approach. If we create a model in an existing package, that means we'll be using the
overlayering or customization development approach. Next, we'll look at how to update model parameters after we have
created a model, and we'll look at how to view a model's dependencies, that is what other models it is dependent upon.
These are also called referenced models. So first, we'll use the wizard to create a model for a fleet management scenario
and then we'll create projects to associate with that model. In AX, we have two options for approaching development.
Those are overlayering and extensions. If we choose to create a model in an existing package, you must select a model
that contains the elements you wish to customize as a referenced model in the wizard. This way your new model has
access to those elements. Taking this approach allows you to customize metadata and source code at a higher layer. For
example, you can change the design of a form in the user layer. However, this method could potentially increase the cost
of upgrading to new versions of AX in the future. If we choose to create a model in a new package, this implies we're
going to use the extension model approach. Developing this way allows us to access the elements from any models that
we selected as referenced models and the wizard. It also allows us to add functionality to existing code. We can create
new elements as well as create extensions of referenced elements in our projects. By creating extension elements, all of
the customizations and code are stored in a separate assembly. It only contains the code that was added or changed in the
extension file. Since this code resides in a separate assembly, it improves performance and the ability to upgrade and test.
This approach is also ideal when it comes to upgrading so we can eliminate metadata conflicts in our code. Developing
using the extension model will be discussed in greater detail in advanced development courses. So let's begin by creating
a new model that we can use for our fleet management scenario. And then we'll create a project to associate with our
model. To create a new model, we'll going to the Dynamics AX menu, and under the model management group, we'll
choose create model. This opens the model wizard. And from this window, we can specify our model name. So we were
going to call ours DBFleetManagement. We'll give it a short description. And then this also the model display name that
we'll see in the Application Explorer in the AOT. So we'll leave that as DBFleetManagement. And for the publisher, we
can stick our name in there. And then we'll choose the next button. Now we're presented with this option if we want to
create a new package for our model. And again, this implies we'll be taking the extension development approach. If we
choose select an existing package, this means we'll be using our overlayering or customization development approach.
For our fleet management scenario, we're going to create a new package so we're going to use the extension development
approach. So I'll choose an option and select next. Now, here is where we are going to select our referenced models,
which means which other models are our new models going to be able to see or which elements it's going to be able to
access. So there are some system models such as Application Platform, application foundation, and Application Suite that
host a lot of the tables like the customer table, the vendor table. So for the purpose of our scenario, we'll just leave it at
the Application Platform and we'll choose next. We'll be presented with a summary window of our model name and
display name. And we're going to have this checkbox to say, hey, let's create a new project right away to start building
and adding elements. So we'll choose finish. And now we're prompted to give a name for our new project to associate
with our new model. So I'll call it DBProject1. And choose OK. So now we have our new model and our new project
and we're ready to begin adding and customizing elements. Once we have our model created, we can also go back and
update the model parameters at any time. To do this, we'll go to the Dynamics AX menu. Under model management, we
can choose update model parameters. And this will bring us back to the wizard screen. So the first thing we have to do is
select our module name from the drop-down. The model that we want to modify. So we just created our
DBFleetManagement model. We'll select that and we can see it brings up the details about that model. So we can change
the display name, the description, and the publisher on this screen. We cannot change the actual name. If we hit next, we
can now change the dependency information. So if we want to add another model as a dependent model so we can access
the elements from that model, we would do that at this screen by selecting the checkbox next to the model we want. So
for this particular model, I just have the Application Platform as a referenced model. So once we complete going through
the wizard again, we'll get a summary screen and we can choose finish. Another important thing to know from the
Dynamics AX menu is this option under model management to view package dependencies. This is going to open up a
DGML file which is a graphical file that shows all the dependencies of the different models in the system. Now, if I zoom
in using my scroll wheel, we can see here's my DBFleetManagement model that we just created. We can hover over it for
some information. We can also click it, and it's going to give us that basic summary information that we just saw in the
wizard. And we can see that it points to the Application Platform. This is the referenced model that I selected and this is
the only referenced model that I had selected so we could see here this relationship between my DBFleetManagement
model and the Application Platform model. We can also scroll around to see all of the different relationships that exist
between the different models. When working with projects, it's important to note that each project can only contain
elements from one model. If you need to use elements from multiple different models, a new project will be created for
each set of elements that originates from a different model, or you have to have your model configured to reference the
models you need. When we want to customize elements, we can add them to our project from the Application Explorer in
the AOT by right clicking the element and choosing add to project. In the next demonstration, we'll look at creating
projects and adding them to solutions as well as setting the properties of the project. And then finally, we'll look at adding
elements to our projects. The diagram below gives an overview of the different properties that we can set on a project. Of
these properties, the model property is particularly important. You must specify which model your project is to be
associated with. All of the elements in the project must be in the selected model. The startup object type is another
important property to note. When you want to test or debug your application, you set the startup object type as the type of
element you wish to debug. For example, if you want to test a form you're developing, we would set the startup object
type as form. And then the startup object property specifies the specific form that you're going to be setting as your
startup object. We can run a project by pressing CTRL F5 and it will invoke the startup object when you run that project.
Another property to note is a synchronized database on build property. This simply specifies if you want to perform a
database synchronization when a build action is performed on the project. When we created a new model, it automatically
gave us the option to create a new project with that model. If we want to create a project manually, we can also do that.
We currently have the solution DBProject1 open with a project called DBProject1. If we right click the solution from the
Solution Explorer, we can choose add and hit new project. This will add a new project to the same solution. We can also
go to the file menu and choose new and project. We'll choose Dynamics AX project, and then we can specify a name for
our project. We'll call this DBProject3. And then from this drop down here, we can specify again if we want to add this
project to the currently open solution or if we want to create that in a new solution file. We could also import and export
project package files. A project package file contains all of the elements from a project. We can use these package files
to import and export between different instances of AX. A project package file is saved with a .AXPP file name
extension. To export a project, we go to the project menu, and we choose export project. This will export the currently
open project with all of the elements along with it. Since this current project does not have any elements with it right
now, it will not let us create an export. However, we would go in here and specify a name for the project package and
choose save. Then, when you want to import a project, we go to the Dynamics AX menu and we choose import project.
From here, we can choose a file path and some other options for the import. For this example, I'm going to choose an
AXPP file that I have on my local disk here. I'll load it in and it will come up here with all the details of the different
elements in this project. If I keep expanding, we can see all the different XML files that relate to each element in that
project. We also have the option to open the project in the current solution or a new solution as well as to overwrite
elements if they already exist. An important thing to note when importing projects into other instances of AX is that if
you have a project associated with a model that you export, and then you want to import it into another instance of AX
that does not have that model created, the project import process will automatically create a model for that project.
Lesson 8: Using Elements
So we've talked a little bit about where elements are located in the Application Explorer and the AOT and how they're
organized. So let's take a deeper look at how we work with elements and customize them within our projects. When
editing elements, we use what's called the element designer to configure the properties and set different options for that
element. For example, we can add fields to a table using the element designer. We could then set properties on those
fields and tables using the properties window. We can also find related elements by right clicking in a particular element
and finding other elements that may relate or associate to that one. Here's a screen shot of what the element designer
looks like. It opens in a tab in Visual Studio and allows you to customize the element. So here, we're looking at a table
called FMCustomer. It belongs to the model fleet management. It contains all the various pieces that we can change on a
table such as fields, field groups, relations, and indexes. And we'll look at all these concepts later on in the course. It's
important to note that all development is done against local XML files. These XML files are stored on your local disk in
folders organized by package and model. The actual XML file contains both the metadata for an element as well as any
source code for an element. This means when you customize a table, for example, it will store the properties of the table
such as the name and the table type along with any X++ code written for that table all in a single XML file which is stored
locally. Here's a view of a properties pane for a particular element. If we select the element, the element type and name
will appear here at the top of the properties window. And then within the properties pane, we can scroll up and down and
see all the different properties available here for editing this element. They can be organized in different ways. So
currently, the property's organized by category. So we have a category called data and then all the properties that relate to
changing the data of that element. We can also have these properties organized by frequency of use as well as
alphabetically. So this properties window contains details about the highlighted top-level node, in this case, is our table,
the FMCustomer. There are several ways to add a new element to your project. We can right click the project from the
Solution Explorer. And we can choose the add option, and then we can choose new item. We can also use a shortcut key,
CTRL SHIFT A, to add a new item to the project. Now, in the middle pane, it's going to show an alphabetical list of all
the different element types or artifacts that we can add to our project. These are all AX elements. I'm going to click table
and I'll give it a name here at DB table and choose add. And you'll notice it will automatically create a folder called tables
so that each successive table that we add will be organized in this folder. And it opens up the element designer by default.
So now, I can go in here and right click on fields and add fields to my table. And I could add a different primitive data
type. We can also choose our element and press ALT enter to bring up the properties pane here if it's not already visible
in your window layout. So once you add an elements, you can go ahead and begin editing it using the element designer
tab as well as changing the properties on it. We can close out the element designer by choosing the X on the tab here.
And we can reopen the element designer by right clicking in the element and choosing open. This will bring back our
designer. Now, if you notice on the left, we're looking at our model view, so these are all the different models in the
system. This current project is associated with the DBFleetManagement model. So if I were to go into another model, for
example, the Application Foundation, and I tried to add one of these base enum data types to my project, I can right click
the element and you'll notice the add to project is grayed out. That's because this current project is associated with a
different model. Since we're using the extension development approach, I cannot add an element from a different model
into this current project that's associated with another model. There are options, however, to add to a new project will
create a new project connected to this model where this element lives. If we go to our DBFleetManagement model, we
don't really have any elements in here yet besides this table that I've just created and added to our project. So if I go to the
data model node and expand tables, we can see there's my DB table. So once you have an element in your model, you can
drag it over to your project. You can also right click and choose add to project. Since we already have this element in our
project, we don't need to add it any further. It's just important to note that when you're adding elements to your project,
they need to be in the model that your project is associated with.

Lesson 9: Performing Builds


When we create new models and projects that contain new elements or customized elements, we need to build them so
that they can be used by the application. The elements of a model must be built so that they can be used by the
application. A full build can be performed on an entire model or multiple models. A build can also be performed on a
project, meaning it will only build the elements that are in the current project. When a build is done on a project, it will
only build the elements that are new or changed since the last build was performed. So during a build operation, various
validations are performed. So metadata and X++ code will be validated. A best practice check can be performed. Report
design generation will be completed. Compilation and creation of .NET assemblies is also done in a build, as well as
label and resource file generation. And lastly, database synchronization can also be done in a build. And we'll take a look
at the different options we can set, what we want to encourage during a build process. For example, if we don't want a
database sync to occur during a build, we can specify that before we perform it. So in order to perform a build on our
project, we can go up to the build menu, and we'll choose build DBProject1, which is our currently open project. An
output window will display, giving the status of the build as well as each step being performed. When we choose to do a
build, it only builds new or changed elements. It's important to note that if we delete an element from a project, we must
use the rebuild option in order for that deletion to take effect. Performing a rebuild also forces a build of all objects in the
project regardless of whether they have changed or not. So for example, if I wanted to delete my DB table, I can right
click and choose delete. And now, I will have to go to my build menu and choose rebuild DBProject1 in order for that
deletion to take effect. And I'm here in my output window, and it says that the rebuild has succeeded. We can also
perform builds by right clicking on our project name from the Solution Explorer and choosing build or rebuild. If we
want to build an entire model, we can go to the Dynamics AX menu and choose build models. And from here, we can put
a checkbox next to every model that we want to build along with the option to build the referenced models. If we go to
the options tab, here's where we can select what we want to happen during the build process. So we have the option to run
a best practice check, to perform a database synchronization, as well as build reports and precompiled forms and cross-
reference data. Lastly, if we right click our project and choose properties, we can go through the different options for the
project. And at the bottom, we'll notice again synchronize database on build. Currently, by default, it's set to false. But
we can flip this to be true if we want a database sync to be performed each time which build it. It's set to false for
performance reasons, so it's not performing this sync each time we do a build. However, the choice is yours to make.

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.

MODULE 1 KEY TAKE AWAY


o Introduction to Visual Studio

▪ Setup and Configuration

● System Requirements

● Hosted locally or on Microsoft Azure

● Minimums:

o 16GB RAM

o 2 CPU cores

● More RAM & CPU = Faster compiles

▪ Terminology and Concepts

● Elements

● Objects residing in AOT

● Tables and forms

● Customizable

● Models

● Group of elements

● Design time concept

● Projects
● Contained inside models

● Can only be associated with one model

● Packages

● Deployment unit that contains models

▪ Naming Conventions

● Camel case

● Maintain consistency

● Avoid reserved words

● Prefix with a company/project name

● Example: DBVehicle

▪ Navigation

● Application Explorer and AOT

● Model View

● Solution Explorer

● Properties window

● Code editor

● Dynamics AX Menu

▪ Projects, Models, Packages

● Creating a model with the wizard

● Overlaying vs. Extension

● Create model in existing package

o Allows customization of metadata and source code in higher layer

o Could increase cost upgrade to newer AX versions

● Create model in a new package

o Allows access to elements from any selected referenced models

o Can add functionality to existing code

o Create new elements and extensions of referenced elements


o Improves performance of building and testing

o Ideal for upgrades

● Updating model parameters

● Project properties

● Most important = model property

o Must specify which model the project is associated with

● Startup object type and startup object properties

o Useful for testing and debugging

▪ Using Elements

● Element designer

● Finding related elements

● Setting element properties

● Can be organized in various ways

● Contains details for highlighted, top-level node

▪ Performing Builds

● Building operations

● Metadata and X++ code validation

● Best practices check

● Report RDL generation

● Compilation and creation of .NET assemblies

● Label and resource file generation

● Database synchronization

MODULE PRACTICE

Practice 1.1: Configure Visual Studio

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.

High Level Steps


1. Open Visual Studio

2. Set Text Editor Options

3. Set Best Practice Options

4. Set Projects Options

Detailed Steps
1. Right Click on the Visual Studio icon on the desktop and select Run as Administrator.

2. Open Dynamics ‘AX7’ > Options.

a. Expand Text Editor node

b. Select All Languages node, under Settings:

i. Select the Word wrap check box


ii. Select the Line numbers check box.
c. Collapse the Text Editor node

d. Expand the Dynamics ‘AX 7’node

i. Select Best Practices node and check the following:


1. Microsoft.Dynamics.AX.Framework.BestPracticeFramework.UIRules

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.

Practice 1.2: Create a Project

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

High Level Steps


1. Run the Model Wizard

2. Set the Model parameters

3. Create a new package with selected reference models

4. Create a project

Detailed Steps
1. Right Click on the Visual Studio icon on the desktop and select Run as Administrator.

2. On the Visual Studio menu, click Dynamics ‘AX 7’

3. Click Model Management > Create Model

a. Model name: DevelopmentBasicsFMS

b. Model publisher: AX Developer

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.

f. Model display name: DevelopmentBasicsFMS

4. Click Next

5. Select Create new Package

6. Click Next

7. Select the following referenced models


a. Application Platform

b. Application Foundation

c. Application Suite Electronic Reporting Integration, Application Suite

d. Application Platform Form Adaptor

e. Application Suite Form Adaptor

f. Application Workspaces

g. Application WorkspacesFormAdaptor

8. Click Next

9. On Summary, ensure check boxes are checked for:

a. Create new project

b. Make this my default model for new projects.

10. Click Finish

11. Select Dynamics AX7 Project

12. Enter DevelopmentBasicsFMSProject in the Name field.

13. Click OK

Practice 1.3: Create an Element

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

High Level Steps


1. Create an element

Detailed Steps
1. In the Solution Explorer, right click DevelopmentBasicsFMSProject

2. Click Add > New Item

3. Under AX7 Artifacts, select User Interface

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

High Level Steps


1. Run the Build process

2. Review the results

Detailed Steps
1. In the Solution Explorer , right click the Solution ‘DevelopmentBasicsFMSProject’

2. Click Build (or use Ctrl+Shift+B)

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.

Lesson 1: Application Stack


The application stack and server architecture in AX is designed to align with three key pillars, w hich include the web-
based client, cloud readiness and the Visual Studio development stack. The application stack has been divided into three
distinct models. The Application Platform, the Application Foundation, and the Application Suite. This is for overview
purposes and does not represent the actual model hierarchy within Visual Studio. Let's start at the bottom of the diagram
with the Application Platform. This is the core application. In this layer, we have the runtime and data access which
stores the core business logic that AX operates from. We also have workflow and services which allow you to integrate
other programs and run configurable business processes through your defined flows and review and approvals. Next, we
have the client and presentation component. This layer creates the graphical user interface. This is the web-based
application that users will navigate to and use on a daily basis to perform their job functions. And finally, we have the
SSRS reporting component. This is used to present operation reports in the rich client using SQL Server reporting
services. The Application Platform technology is used to support the core functions of AX that the Application
Foundation is built upon. In the Application Foundation, we have things like the organizational model. This supports
visual modeling of your organization entities such as business units and departments. Next, we have number sequences.
This supports logical numbering of your data and documents through the system. For example, the automatic numbering
of sequential purchase orders. Next, we have the global address book. This is used to design and centralize and share
address information for various entities such as customers, vendors and employees within the system. Finally, we have
the source document framework which supports documents such as purchase orders and free text invoices just as a few
examples. And finally, we have the Application Suite. The Application Suite is rich in functionality and includes things
like financial management, inventory and warehouse management, as well as human resources management and much
more. The application can also be extended to include customized applications which we'll be doing throughout the
course with our fleet management example.

Lesson 2: Server Architecture


In this lesson, we will review the server architecture. Starting from the bottom, the aggregate data store and database are
at the lowest level. Next comes the data access layer. This enforces a security to the underlying data store and the
database. The group of objects included on this layer include the metadata and other components such as security,
workflow, batch engine, and caches. These can directly relate to the OData service endpoints or to the forms engine
which is ultimately used for the user interface interaction layer. The services endpoints on the server is responsible for
returning all form and controls metadata as well as other data to the browser-based client. The form objects run in the
server and are rendered for a browser and other clients. The server, including the application code base, is deployed to an
IIS web application. In the cloud, it's deployed to the Azure infrastructure as a service virtual machines. The metadata
subsystem incorporates the compiler and Visual Studio-based development model. The model store is represented as a set
of folders and locally stored XML artifacts organized by model. The Dynamics AX preview model elements, like tables,
forms, and classes, are represented by an XML file containing both metadata and source code.

Lesson 3: Cloud Architecture


In this lesson, we'll review how the cloud architecture functions with AX. The cloud architecture includes services that
automate software deployment and provisioning, operational monitoring and reporting, and seamless application lifecycle
management. The cloud architecture consists of three main conceptual areas. The first is lifecycle services. This is a
multi-tenant shared service that enables a wide variety of lifecycle-related capabilities for Dynamics AX. Capabilities
specific to this release include software development, customer provisioning, service-level agreement monitoring, and
reporting capabilities. The next component is Dynamics AX. AX virtual machine instances are deployed through
lifecycle services to your provided Azure subscription. Different topologies are available. Demo, development, and test
environments, and high availability production topologies. The third component is shared services. AX uses a number of
Microsoft services to enable a one Microsoft solution where customers can manage a single log-in, subscription
management, and billing relationship with Microsoft across Office 365, PowerBI, and other online services. Dynamics
AX uses many features of the Windows Azure platform including Azure storage, networking, monitoring, and Azure SQL
databases. Shared services operationalize and orchestrate the application lifecycle of the AX environments for
participants. Together, Azure functionality and lifecycle services built for Dynamics AX offer a robust cloud service.

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.

MODULE 2 KEY TAKE AWAY


o Architecture
▪ Application Stack

● Application Platform

● Core of application

● Runtime and data access

● Workflow and services

● Client and presentation

● SSRS reporting

● Application Foundation

● Organization model

● Number sequence

● Global address book

● Source documents

● Application Suite

▪ Server Architecture

● Architecture

● Aggregate data store

● Database

● Data Access Layer

● Metadata

● Security

● Caches

● Workflow

● Batch

● Forms engine

● UI Interaction layer (WCF)

● OData Endpoint (WCF)

● Server deployed to an IIS web application


● In cloud deployed as service Virtual Machines

● Model stores are set of folders and XML artifacts

● Organized by model

▪ Cloud Architecture

● Lifecycle services

● Capabilities:

o Software development

o Customer provisioning

o Service level agreement monitoring

o Reporting capabilities

● Shared services

● One Microsoft

o Single login

o Subscription management

o Billing relationship with Microsoft

▪ Office 365

▪ Power BI

▪ Online services

● Dynamics AX

● Deployed through lifecycle services to Azure subscription

● Different topologies

o Demo

o Development/test

o High-availability production topologies:

▪ Demo

▪ Development/test

▪ High-availability production topologies


● Microsoft Azure

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 2: Fleet Management Scenario


In this lesson, we will cover labels and label files in the fleet management 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.

Lesson 3: Create and Use Labels


In this lesson, we will review the creation and use of labels. Let's take a look at a demonstration of how to create a label
file and then a label within that label file. Since this is the first artifact or element we are going to be using in our fleet
management scenario, I'm going to start off by creating a new project that we will use going forward. So I'm going to go
to file, new and choose project. And we'll make sure we choose Dynamics AX project, and we'll call this DB FMS
project. Let's going to be our development basics fleet management system project. OK. So once we have this new
project loaded, we can begin adding our elements. So in my Application Explorer, I'm currently looking at the classic
view, which is all the system elements. So I'll right click and switch to model view. And you notice that my Solution
Explorer is not visible because I've closed it. So I'm going to go back to view and Solution Explorer. And here's my
newly created DB FMS project, and now I'm going to begin adding elements. So to add a label file, you can right click
our project. We'll go to add and then new item. Now, again, in the middle pane, all the different available elements are
organized in alphabetical order. In the left pane, we can see them broken out by group. So I can click labels and
resources, and I want to make a label file. We'll call this DB -- let's call it DB demo label file. And I'll choose add. And
now it brings up the label file wizard. So I'll leave the label file ID as what I just specified in the previous step and choose
next. On this page of the wizard, we have the option to choose different languages to associate with our label file . For
this example, I'm going to keep the default, United States English language. And I'll choose next again. And then finally,
we'll choose finish to create our label file. So we can see it's created a folder for a label files and then it's created this
actual label file here. Now, to create a new label in the label file, we would right click our label file here which ends in
a .txt extension. And we'll choose open. This is going to open the element designer for the label file. And here, we have
the ability to search and add new labels. So I simply click in this box here where label ID and I'll type in a label ID for a
label file such as DB label one. I can tab over to the next column, which is label. This is what the actual label will be, so
we'll call it vehicle example. I'll tab over to the description column, and I can add some more details. We'll just say label
demonstration. So those are the high-level steps of adding a label file and an actual label to a project.

Lesson 4: Search Labels


In this lesson, we will review how to search for labels. Now I'm going to demonstrate how searching for labels works in
Visual Studio. So I have my label file designer opened. I achieved that by right clicking on the label file and hitting open
and it opens this tab here with my label file and all of the labels contained within it. So we can, you know, add new labels
and delete labels from here. And we can also search. There's three options for searching. We can search by text, by the
entire word, or to match exactly. So for example, we see I have this label ID DB label one. If I type DB and L, that label
still shows because I'm just searching by text and DB L is in this string here. If I were to type a letter like Y, for example,
no matches match this particular combination of letters. We can also search for strings or words in the label column and
the description column. So if I were to type in demonstration, this label is still returned in my search results. Likewise, if
I choose match word, the demonstration word appears right here in the description column, so it's going to still yield this
result. However, if I backspace, that entire word is no longer in my results.

Lesson 5: Best Practices for Labels


Let's review some best practices to consider when using labels. The following are the best practices for using labels. You
should use labels for every element or artifact that you create. You should ensure that labels contain the appropriate
translation of activity or item. Use labels when programming for all external strings. Create a label file with the same
name as the associated model. And before you create a new label, always do a get latest on the label file you are editing.
This ensures you have the most up-to-date and recent version of the label.

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.

Lesson 7: Create and Use Resources


In this lesson, you will create and use resources. The basic flow for creating and using resources is outlined in this
diagram. We will go to the Solution Explorer and locate our project. We will choose to add a new item to the project of
type resource. Once the resource is added, we can specify and locate which image file we want to use for our resource.
You can also hover over the resource to display a small thumbnail preview of the image file that it contains. Finally, we
want to change the name of the resource and set the label property appropriately. So let's take a look at the process for
adding a resource or an image file to our project. To do this, we'll go to the Solution Explorer and right click our project.
Again, we'll go to the add and new item. And on the left, I'll choose the labels and resources category under the AX
artifacts group. I'll choose resource. And then we'll give it a name. I'll call it DB demo resource. And I'll choose add.
As soon as we do that, we're going to be prompted with a File Explorer to select a resource file. So it wants to know
which resource we're going to associate with this resource that we're adding to our project. So I'll choose an image from
my local computer and select open. And you'll see it automatically creates a resource folder for us. Here's our resource
and here's the image that references a resource. And you can see by hovering over it, we get a little preview. We can also
right click and choose open. And we'll get a full-sized preview of our image here. And we can also edit it from here as
well.

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

● Reference from element or artifact that point back to label file

▪ Label creation

▪ Searching

▪ Best Practices for Labels

● Use labels for every element/artifact

● Ensure labels contain appropriate translation of activity/item

● Use when programming for external strings

● Create label file with same name as associated model

▪ Resources

● Pictures

● Icons

● Visual representations

▪ Create and Use Resources

● Solution Explorer

● Add new item for project

● Select resource file

● Change name of resource


MODULE PRACTICE

Practice 3: Create Labels

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.

High Level Steps

1. Open Visual Studio


2. Set Text Editor Options

3. Set Best Practice Options


4. Set Projects Options

Detailed Steps
1. In the Solution Explorer, right mouse click the DevelopmentBasicsFMSProject

2. Click Add > New Item


3. Under AX7 artifacts, select Labels and Resources

4. Select Label File


5. Enter dbFMSLabelFile in the Name field.

6. Click Add
7. The Label file wizard will display.

a. Ensure Label file ID: dbFMSLabelFile


b. click Next

c. Ensure Selected languages: en-US


d. Click Next.
e. Click Finish to create the Label File.
8. Right click dbFMSLabelFile_en-US.label.txt, click Open.

9. Click New to create a label and enter the following:


a. Label ID: dbFMS1

b. Label: Vehicle Type


c. Description: DB FMS

10. Click New to create labels for the following using Description of DB FMS for all created labels:
a. Label ID: dbFMS2 Label: Car

b. Label ID: dbFMS3 Label: Truck

c. Label ID: dbFMS4 Label: Van

d. Label ID: dbFMS5 Label: SUV

e. Label ID: dbFMS6 Label: Service Type

f. Label ID: dbFMS7 Label: Repair

g. Label ID: dbFMS8 Label: Oil Change

h. Label ID: dbFMS9 Label: Maintenance

i. Label ID: dbFMS10 Label: Registration

j. Label ID: dbFMS11 Label: Fuel Type

k. Label ID: dbFMS12 Label: Gas

l. dbLabel ID: dbFMS13 Label: Diesel

m. Label ID: dbFMS14 Label: Propane

n. Label ID: dbFMS15 Label: Natural Gas


o. Label ID: dbFMS16 Label: Electric
MODULE 3: YOUR NOTES
Module 4: Base Enumerations
Welcome to the base enumerations module. In this module, we will introduce the data types node in the Application
Explorer and discuss how and when you should create new base enumerations. In the simplest terms, a base enumeration,
or sometimes referred to as an enum, is a list of literals with an assigned value. You will need to create base enumerations
before you can begin using them in your code. Let's get started by reviewing the objectives. The objectives for this
module are to define a base enumeration, to list examples of base enumerations, to create new base enumerations, and
finally, to review best practices for base enumerations.

Lesson 1: Fleet Management Scenario


To build upon our fleet management example that we're developing for this course, base enumerations will be required.
Let's take a look at the scenario and the details for the base enumerations that we will create. For our fleet management
scenario, we will need to build three enumerations. These will aid in tracking the vehicle type, the service type that a
vehicle receives, and the fuel type. Here are the high-level steps we're going to cover. We will create a base enumeration.
Then we will set the label property for that base enumeration. Then we will create elements within the enumeration. And
set labels on those. And finally, we will build those elements so that we can use them in our application.

Lesson 2: Create a Base Enumeration


Now let's take a look at the process for creating a new base enumeration. The X++ language has an enumerable type, or
enum, which is a list of literals. You need to create an enum before you can use it. Enum values are represented
internally as integers. This means that they're stored in the database as a number instead of a value. This can be useful
because it saves space. The first literal has a number zero assigned to it. The next has a number one, followed by the
number two and so on. You can use enums as integers in expressions when you write X++ code as well. Each literal or
enumeration is assigned a text value through a label property. The label property is displayed to the end user in the user
interface of the application. The system automatically does this conversion for you in the user interface so that no
additional programming is required on the forms that display to the users. So let's take a look at a few types of base
enumeration examples. The first is a no/yes enumeration. This has two associated literal values where the no value is
represented by zero and the yes value is represented by the value of one. Typically, this type of enumeration appears as a
slider in the system in the user interface. These are also referred to as the boolean primitive data type. Another example
is the sales order status enum. This enumeration is used to set the status of a sales order automatically behind the scenes
in code. You just can view the status of a sales order in the UI. However, they cannot manually change the status of the
sales order in the interface. Next is an example of the ABC codes enumeration. ABC codes are used in several areas of
the system to rate customers, vendors, or an item for example. The user is presented with a list of options and they can
select one option from the list. Another example is a posting type. For this example, the user is displayed a variety of
radio buttons. When each radio button is selected, the user interface updates with the new values or information related to
the selected radio button. In this demonstration, we're going to add two base enumerations to our development basics
fleet management system project. To do this, we'll repeat the same process to add new elements to our project by going to
the Solution Explorer, right clicking the project name, going to add, and choosing new item. An enum is categorized
under the data types node. So from the left, we'll choose the data types group and the first option in alphabetical order is
base enum. So I'll select that and I'll give my first enum a name. We're going to call it dbDriveType to specify the type of
drive for the vehicle. And we'll choose add. I'll go ahead and repeat that process. This time I'm going to use the shortcut
keys, CTRL SHIFT A with my project highlighted. And it will bring up that same window to allow me to add new
elements to my project. Again, we're going to choose base enum and we'll call this one DB status type. This will indicate
the status of the vehicle's maintenance. I'll choose add. And it's going to add it to my base enums folder. We can see my
two newly created enums. And now we can begin adding new elements or new options, new status types, and new drive
types to these enums. And to do that, we can right click and choose open. However, both of these are already open here
in different tabs. We have my DB status type enum and my dbDriveType enum. Let's start on the status type enum. We
can right click the root node here in the element designer and choose new element. This represents a new choice, a new
status type in this enums list. We're going to have five different status types. So I'll keep adding new elements until I
reach five. And then we'll go through and assign system names to the enums and labels. So on the first choice, if I right
click here on the node and hit rename, it's going to allow me to add the system name for this enum. So this first status is
going to be available. And then in the properties pane on this choice, I'll set what I want the label to be. The label is what
the user will see on forms and reports. So I'll keep the label as available. That's a very user friendly status. The next
option is going to be in maintenance. Now, I can right click and hit rename. And I'll type in maintenance. Now, we
notice I can't use spaces here because this is just a system naming convention for in choice. And the label, I'm free to add
spaces and type it as I please. OK. We'll continue on to the third choice. This time I'm going to use a shortcut key. I'll
press F2 with this choice highlighted as a quick way to rename an element. This option will be in repair. I'll go down to
my label property and type in repair. For the fourth choice, we'll use in detail. And again, I want to mirror that on my
label with a space. And for the final choice, I'll hit F2 to rename it, and it's going to be out of service. And for my label,
type out of service with spaces. OK. So now, what we can see, if I click the very first option on the list, which is the
status of available, the enum value property is zero. It begins at zero and then it increments from there. So I have five
choices which are represented by zero through 4. As I click the different element choices, we can see the enum value
increases. And that continues through the list until I reach the last one. And remember, this numerical value is what's
stored in the database. OK. So now that we've finished that element, let's go over to the dbDriveType enum and we're
going to have four different drive types. So again, I'll right click the root node of my enum. And choose new element
until I get to four choices. And we're going to have four four-wheel drive, all-wheel drive, rear-wheel drive, and front-
wheel drive. So, I'll specify those values as FWD for front-wheel drive, and the label, I can spell it out fully but FWD is a
common acronym for front-wheel drive vehicles. So I think my users would appreciate that. We'll continue on the list.
This one will be RWD for rear-wheel drive. I'll have my label be the same. The next one will be AWD for all-wheel
drive. And the final one, we'll call it four-wheel drive. And for my label, I'll use the number four instead as 4WD to
indicate that vehicle has four-wheel drive. OK. So now, these elements are created. I've added my choices. They have
enum values and labels. So I can right click each tab up here and save to save that individual enum. And make sure all
my changes are being saved to my project. Alternatively, we can click this icon here with two disks to save all of the
elements. The shortcut key for that is CTRL shift S. OK. So now, we just want to go ahead and make sure we do a build
on our project to make sure there's no errors and everything is looking good. I'll right click the project and choose build.
We can see in the output down here, it updates with the status of our build. It will notify us when it's complete, and then
we can continue developing and adding new elements to our project.

Lesson 3: Best Practices


There are many considerations you should keep in mind when deciding to use a base enumeration. Let's review some of
the guidelines that should be followed. We should define and use enums when a field or variable can have a limited fixed
number of predefined outcomes. If there might be an unlimited number of user-defined outcomes, it's recommended to
use a to-be-related-to table instead. If you want to make an enum a mandatory field on a table, make the first outcome
with the value zero as none and set the label property to not selected. Most enums can be regarded as specialized types
and should be used as they are. Some enums, like no, yes, and table group all, can be regarded as more general types.
They can be specialized by using extended data types. If you want a default value for your base enumeration, the value of
the zero must be used. Otherwise, you need to add code to the appropriate table where the defaulting must occur . If you
are going to manually delete any enumeration, modify an existing enumeration or its values, you should consider the data
related to that enumeration. You will need to determine whether it has been used in persistent storage and existing tables
and if old data must be taken into account. Let's review a few more best practices for working with enums and constants.
Always let the constant be an enumerator. Never use numeric constants instead of enums. Never use other constants such
as other enum types instead of enums. Do not make boolean tests on enum fields except where the zero or false value is
clearly the one with the false outcome. You should never use relational operators on enums. You should also never
compare or assign to enums of different types. And finally, do not expect the enumerators to have a numeric value in the
range of zero which is the number of enumerators minus one.

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.

MODULE 4 KEY TAKE AWAY


o Base Enumerations

▪ Create a Base Enumeration

● X++ enumerable type (enum)

● List of literals

● Enum must be created in Application explorer

● Represented internally as integers

● Stored in database as number

● Saves space

● Can use enums as integers in expressions writing X++

● Assigned a text value through label property

● Label property is displayed to end user in GUI

● System automatically converts

▪ Best Practices

● Consider:

● Length

● If it should be mandatory

● If it is a special type

● If you want a default value

● Data if deleting an enumeration or value

● Always let constant be enumerator

● Never use numeric constants instead of enums

● Never use other constants instead of enums

● Do not make Boolean tests on enum fields

● Never use relational operators on enums


● Never compare or assign to enums of different types

● Do not expect the enumerators to have a numeric value in the range of 0

MODULE PRACTICE

Practice 4: Create Base Enumerations

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

3. Create the Elements

4. Set the labels on the elements

5. Create the remaining enumerations

6. Build

Detailed Steps
1. In the Solution Explorer, right click the DevelopmentBasicsFMSProject

2. Click Add > New Item


3. Under AX7 Artifacts, click Data Types

4. Select Base Enum


5. Enter dbfmServiceType in the Name field.

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.

9. Right click the newly created dbfmServiceType (usr) [DevelopmentBasicsFMS] in the


middle white pane and click New Element.

a. Right click on EnumValue1 and Click Rename

b. Enter None in the Name field and click Enter.


c. Enter None into the Label field.

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:

a. Name: Registration Label: Registration

b. Name: OilChange Label: OilChange

c. Name: Maintenance Label: Maintenance

d. Name: Repair Label: Repair

11. In the Solution Explorer, right click the DevelopmentBasicsFMSProject


12. Click Add > New Item

13. Under AX7 Artifacts, click Data Types


14. Select Base Enum
15. Enter dbfmVehicleType in the Name field.

16. Click Add


17. Right click the newly create dbfmVehicleType (usr) [DevelopmentBasicsFMS] in the middle
white pane and click Properties.

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:

a. Name: Car Label: Car

b. Name: Truck Label: Truck

c. Name: Van Label: Van

d. Name: SUV Label: SUV

20. In the Solution Explorer, right click the DevelopmentBasicsFMSProject

21. Click Add > New Item


22. Under AX7 Artifacts, click Data Types

23. Select Base Enum


24. Enter dbfmFuelType in the Name field.

25. Click Add


26. Right click the newly create dbfmFuelType (usr) [DevelopmentBasicsFMS] in the middle
white pane and click Properties.

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:

a. Name: Gas Label: Gas

b. Name: Diesel Label: Diesel

c. Name: Propane Label: Propane

d. Name: NaturalGas Label: NaturalGas

e. Name: Electric Label: Electric


29. In the Solution Explorer , right click the Solution ‘DevelopmentBasicsFMSProject’
30. Click Build Solution (or use Ctrl+Shift+B)

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.

Lesson 1: Fleet Management Scenario


In this module, we will create extended data types from the primitive types that we will then use in our fleet management
example. The basic flow is to determine the primitive data type that we need that will create an extended data type from
that, we will set the label value that will be displayed for our users and the UI, we will configure any additional properties
on the extended data type element, and then we will build the element. The scenario we're going to use is as follows. The
business users at Contoso have identified a variety of information that needs to be tracked in the new system as part of the
fleet management system. Simon, the system's developer at Contoso, has reviewed the list and categorized each piece of
information into the type of data that will be stored. And now he needs to find existing extended data types to use for the
fleet management solution. Extended data types are commonly abbreviated and referred to as EDTs. The following
tables represent a list of EDTs that Simon is considering creating for the fleet management system. We can see an EDT of
type date is going to be used to represent which year the vehicle was made. An EDT of type string could represent the
VIN number, or the vehicle identification number, for a particular vehicle.

Lesson 2: Primitive Data Types


The basic set of primitive data types in AX map to underlying data types that exist in the physical database. These
primitive data types can be expanded to create extended data types which are reusable data types that have a specific
definition and specific properties set. Let's take a look at the primitive data types available in AX. The data type, any
type, can be used as a placeholder for any data type. Booleans are a data type that can only contain the values true and
false. These are commonly used as a slag or a switch in the system. The data type of dates contain a day, month, and year
value. The data type of enums we discussed in the last module are an abbreviation for enumerated text, a set of literals.
GUIDs are globally unique identifiers. The data type integers represent a number without a decimal point. This is a
whole number for example of ten. To declare an integer in code, we use the keyword int, or I-N-T. A data type of real is
also a numerical data type that includes a decimal point. These can also be referred to as decimals. The data type of
string represents a certain number of characters. To declare a string in code, we use the keyword STR. A string can be
any kind of sentence or word. The time of day data type contains hours, minutes, and seconds. To declare a time, we use
the system type time of day. And finally, we have the UTC date and time. This contains the year, month, day, hour,
minute, and second.

Lesson 3: Create an EDT


Now that we went over some of the primitive data types, let's review the process for creating a new extended data type.
An EDT is a primitive data type or container with a supplementary name and some additional properties set. For
example, we can create an EDT called name based on the primitive data type of string. Thereafter, we can use that new
EDT in variable and field declarations in the development environment. Let's look at some of the benefits of EDTs. The
first is that code is easier to read because variables have a meaningful data type. For example, name instead of string.
Properties of EDTs can be inherited. This means the properties we set for an EDT can be used by all instances of that
type which promotes consistency and also reduces work. For example, account numbers are based on the account num
data type and they have the same properties throughout the system. You can create hierarchies of EDTs which inherit the
properties that are appropriate from the parent down to the child. For example, the item code data type is used as a basis
for the markup item code and the price disk item code data types. Most fields in AX tables are based on extended data
types. After its created, it can be reused as many times as is needed in the application. In this demonstration, let's go
ahead and create some EDTs or extended data types to use for our fleet management system. We'll begin by adding new
EDTs to our project. So we'll right click the project, we'll go to add and we'll choose new item. From the left pane here,
we are going to go into the data types group and we'll see we have all these different types of EDTs that are based on
different primitive data types.
So in the first example, we'll do an EDT of type string and we'll call it DB VIN to represent a vehicle identification
number. And we'll choose add. This will create an EDT string type folder here with our EDT inside of it. So we also
have our EDT element designer open and we can go set some properties on this EDT. So in the label, let's go ahead and
type in VIN and we want to change the string size probably to be a little larger than ten because the vehicle identification
numbers can be quite long. So let's go ahead and just change this to 25. And we'll set our help text to a simple sentence
to describe what this is. So I typed a sentence that says this represents the vehicle identification number. OK. So we can
right click this element and save it. And then we'll continue adding new EDTs. So we'll repeat the process by right
clicking our project, going to add, and new item. This time, let's create an EDT of type date and we'll use this as a field to
represent the year that a vehicle was made. So we'll call this DB year. And we'll choose add. It makes a new folder.
This is an EDT of type date. We can see our element in there and we can go ahead and set properties on that again. Let's
continue making our -- the rest of our EDTs, first. So we'll repeat again. And this time we'll choose an EDT of type
integer. This will represent a number, a whole number. And we'll call this one DB num of doors. So this integer is going
to represent the number of doors a particular vehicle has. OK. So there's our folder created with our element. I'll
highlight my project again. This time I'm going to press CTRL SHIFT A for the shortcut key. That allows me to add new
elements to the project. We'll continue adding different EDT types and this time, let's use an EDT of type real which is a
decimal number. And we'll call this DB fuel capacity. So we can have a fuel tank that is 12.5 gallons for example. So
we'll need a real or a decimal type to represent that. So our folder is created. That's great. We'll close that and continue
adding. I'm going to use the CTRL shift A shortcut again. And now we can choose to add another EDT type. And this
time, let's use an EDT of type enum. So we discussed base enums in the last module. They represent a list of literals. So
we'll call this DB fuel type code. So there's a finite list of fuel type codes that refer to different fuel types. And we'll add
that. So now, we have a list of different folders that represent our different EDT types. It's nice and organized. We can
go in there and then set properties on our individual EDTs. So now that I've set these properties on this DB VIN EDT, I
can reuse this on any table anywhere else in the system and it's going to maintain these properties that I've set, which is
the label and the string size. So any properties that you set on it are going to be saved in that EDT and they can be reused.
We can also extend this type which will inherit all of these properties and then we can change additional properties. So
it's almost like a complete copy with some minor changes if that's something you would require. So one more thing we
can do with EDTs is have them extend from another EDT or inherit the properties. So for example, I'm going to go to our
EDT dates folder where I created this DB year EDT which represents the year a vehicle was made. And I can go down to
find -- well, first of all, we have to right click and choose open. So we have it in our element designer. And then we can
go through the properties and set them. OK. So I can go through here and have this EDT extend from another EDT. The
extends properties located in the data group, so once I put my cursor here, it brings up this drop-down arrow where I can
click and choose another EDT in the system that I want though one to inherit the properties from. We can also type it in if
we know the name of it off the top of our head. I'm going to try to find one called trans date which is a commonly used
data EDT to represent different types of dates. OK. So now that I've chosen that as my extended form, it will inherit the
properties from that trans date system EDT.

Lesson 4: Best Practices


It's important to follow best practices when creating new extended data types. Let's consider the following guidelines
when developing new solutions in AX. The basic rules for using extended data types are as follows. You should use an
EDT whenever possible. An EDT should be created for each atomic entity in a situation that your application is
modeling. It should pass the is a test, which means the hierarchies that you create among extended data types should be
able to pass this test which implies that an extended data type should be a member of a parent data type. For example, the
subitem ID is a item ID but the subitem ID is not a class name. You should only create subtypes when they are needed. If
you want to add a field to a table or to a dialog, do not choose a type that is too general. Instead, create the type from the
beginning and reuse it everywhere else. Also, you do not want to directly use the system data type for recID or table ID.
It's recommended to use the extended data type ref recID or an extended data type that is derived from ref recID. Now
let's review some best practices for setting extended data type properties. The first one is to follow naming standards.
Next, we want to use labels for all user interface text. This provide's clarity for our end users. The help text property
should not be the same as the label. It should be a little more informative. It's recommended to leave a display length and
style as auto when possible. You also want to specify the enum type for all enums.

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.

MODULE 5 KEY TAKE AWAY


o Extended Data Types

▪ Primitive Data Types

● Map to underlying data types that exist in physical database

● Can be expanded to create extended data types

● Types

● Anytype

o Placeholder for any data type

● Booleans

o Can only contain values false and true

● Dates

o Contains day, month, and year

● Enums

o An abbreviation for enumerated text – set of literals

● GUIDs

o Globally unique identifier

● Integers

o Number without decimal point

o To declare use keyword int

● Real

o Numbers with decimal point


o AKA decimals

● String

o Number of characters

o To declare use keyword str

● TimeOfDay

o Contains hours, minutes, seconds

o To declare use system type timeOfDay

● UTCDateTime

o Contains year, month, day, hour, minute, second

▪ Create EDTs

● Benefits of EDTs

● Code is easier to read

● Properties are inherited

● Provide consistency

● Reduce work

▪ Best Practices

● Use EDTs whenever possible

● Create one for each atomic entity

● Pass the “is a” test

● Only create subtypes when they are needed

● Do not directly use system data type for recID or tableID

● Following naming standards

● Use labels for all user interface text

● Help text should not be same as label

● Leave display length and style as Auto when possible

● Specify enum type for all enums

MODULE 5: YOUR NOTES


Module 6: Tables
Hello, and thank you for joining me in the tables module. We will discuss some of the key properties and features of
tables and how they work in the Visual Studio development environment. Let's get started by reviewing the objectives.
The objectives for this module are to create a table to store information, to add data types such as fields, EDTs, and base
enumerations to the table, to extend a table using the concept of inheritance, to set key properties for a table, to create a
temporary table, to create a query that uses a table as a data source, and finally, to review the best practices for tables.

Lesson 1: Fleet Management Scenario


Tables will be required to build upon our fleet management example for this course. We will use the base enumerations
and extended data types that we created in the earlier modules to create our tables. Let's review the scenario. Two tables
have been identified for the new fleet management module for Contoso. One table will store basic vehicle information
and a second table will store vehicle maintenance information. The table for the vehicles will need to track the following
information. Fuel level, fuel type, gross vehicle weight, inspection date, vehicle make, mileage, vehicle model, notes,
number of doors, seating capacity, third-row seating, a unique vehicle ID, vehicle type, VIN, and year. The table for
maintenance, we need to track the following information. Service type, engine description, service start and end dates,
and the vehicle ID. The scenario is as follows. Simon, the developer for Contoso, needs to create tables to store
information about various types of vehicles in the fleet. Add two tables to the project to achieve this goal. The flow will
be to create a table to store key information, to create labels for that table, to set properties on the table, and then to add
our EDTs or fields to the table, and finally, to build the table.

Lesson 2: Create a Table


In this lesson, we'll review how to create a table in Visual Studio. The main purpose of tables is to store data such as
company transactions, inventory, and journals. Tables contain rows and columns. These rows are called records. You
can think of a table like a spreadsheet. Collectively, they're stored together in a database and work together to deliver data
to the end user and outputs such as forms and reports. Tables can also contain metadata which is not business or
transactional data, but rather description data such as systems setting. The following screen shot shows the element
designer view for a table.
Here, we have a table called table one and below it, all the components that make up the table. The first component is
known as fields. Fields make up data in a table. For example, we can have a field called customer name or customer
address. Fields can also be base enumerations or extended data types. Field groups are logical groupings of physical
database fields. Field groups can be used on forms and reports so that when a modification is made to the field group,
related objects are automatically updated to reflect the new content of that group. Indexes are a way to speed up retrieval
of data from a table and relations define how this table relates to records in other tables . The delete actions node will not
be used. Delete actions node will be used for upgrading from previous versions. However, delete actions on new
elements are set within the relationship properties. We'll look at these pieces in the coming modules. Methods are pieces
of code that are added to a table that can be executed when certain events or changes in the data occur . For example, there
can be a method to insert or find data in a table. Events store code to be executed when something happens in the table.
The state machine feature enables workflow events to be bound to state transitions in the underlying entity state machine.
This enables you to perform state transitions within a workflow without writing any additional code. With a map, you
associate a map field in one or more tables. This enables you to use the same field name to access fields with different
names and different tables. For example, in two separate address tables, one can refer to the zip code field as zip code and
the other table may call it postal code. Now we're going to add two tables to our project to store information for our fleet
management system. To add a table, we repeat the same process that we do to add any element to our project. So we
right click, we choose add, and we choose new item. In the left pane under the AX artifacts, we want to choose data
model. This is where the tables reside. So we'll select table as our element type.

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.

Lesson 3: Adding Data Types


In this lesson, we will add data types to the table so that we can store information. Data types include fields, base enums,
and extended data types. We will use some of the previously created extended data types along with some new fields to
build our tables. So now that we've added two tables to our project, and we've set the label property on them, we can
begin to add elements, data types, and fields to our table. So currently, I have the dbMaintenance table opened. Now, I
can begin adding fields by highlighting the field node and right clicking, choosing new, and then selecting a data type.

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.

Lesson 4: Key Properties


In this lesson, we'll explore some of the important properties that can be set on tables. Let's take a look at some key table
properties. The first one is table type. This determines if it's a regular table stored in the database or if it's a temporary
table. We'll discuss the different types of temporary tables later in this module. The name and label properties are used to
determine the system name and the user-friendly name. The primary index properties specifies which field to use for the
primary index. Only a unique index can be selected. This property is used for database optimization purposes. Indexes
are set on a field or fields from the table. A cluster index is to be set on the table and it determines how data is organized
within the table. A cluster index should never be left blank. We will look at indexes more in depth in the module on table
indexes. A configuration key property should be set in most tables. This ensures that the table is removed when the key
is disabled. Configuration keys are a way to allow system administrators to enable or disable certain parts of an
application. The support inheritance property can be set to yes or no. Setting this option to yes indicates that a table can
be extended or inherited. Then, the extends property chooses which base table that the selected table will inherit or extend
from. We will also discuss this concept later in this module.
Lesson 5: Table Inheritance
Now let's take a look at the concept of table inheritance in Dynamics AX. When we extend a table, we're using the
concept of table inheritance. A table can be extended from or derived from another table. Each table has a support
inheritance property and the extends property, which together, control table inheritance. We can set the support
inheritance to yes and then use the extends property to choose which base table in the system we want to extend with the
current table. In the terminology for table inheritance, we say that the derived table extends its base table. The purpose of
table inheritance is to reduce work by allowing the sharing of attributes and fields from another table. Let's check out an
example of how inheritance works. Let's consider the following three tables.

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.

Lesson 6: Temporary Tables


In this lesson we will review how to create and use the different types of temporary tables. There are two main types of
temporary tables. An inMemory temporary table and a tempDB temporary table. These are controlled using the table
type property on the properties node of a table. Common uses for temporary tables include reporting. A tempDB table is
created in the database only when it is in use or instantiated by a particular process. It is then dropped when it's no longer
needed. TempDB tables are often used to store data from reports as they may be joined with other tables. An inMemory
table is instantiated when the first record is inserted and continues to exist until the buffer variable controller goes out of
scope. InMemory tables are held inMemory until the size reaches 128 kilobytes. Once this threshold is exceeded, it
begins to allocate the additional space between the RAM and disk. This can cause performance to suffer. Because of this,
it's recommended to use a tempDB table to handle larger data sets. A general rule of thumb is to use a tempDB table if
you anticipate your data set or report will exceed 5000 rows or records. The data in these temporary tables is controlled
through code and cannot be seen by using the temp table browser feature. When you create a temporary table, it's always
a best practice to prefix the name with TMP so that it can be easily recognized as a temporary table.
Lesson 7: Queries
In this lesson, we'll talk about the creation, use, and benefits of queries. A query element can be designed as a modular
business object. Queries can contain one or more tables as a data source. These tables may be nested within each other if
they are related like in the screen shot. We have a FMT customer table and an FMT customer group table nested and
related to that table below it. Queries are flexible because they're easily changed and can be modified at runtime. For
example, a report that uses a query as a data source can have parameters set dynamically at runtime before the report is
executed. You can also change other options like ordering by certain fields at runtime as well. A query object can then be
reused as a data source to provide data for other forms and reports in the system. So now let's go ahead and add a query
element to our project. Now, we discussed a bit about queries and how they are very flexible and very reusable. They're a
good data source that we can reuse for forms and reports. And they also allow us to specify details at runtime before we
execute them. So if we right click our project again, we can choose add and we'll add new item. And queries live here in
the data model element type group just above table.

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.

Lesson 8: Best Practices


In this lesson, we're going to look at some of the best practices to consider when creating tables, field groups, and queries .
Some best practices for tables include prefixing the name with the module name that the table relates to. For example,
cust vend or invent should be prefixed on the table name that relates to those modules. Another example is to prefix it
with a logical description of the table's contents. For example, cust collection letter trends. For temporary tables, we
prefix them with TMP. You can also post fix the table name with the type of contents. For example, a table that contains
transactions might end in the world trans or a table that contains line level details might end in the word line, like sales
line. The primary tables for the major business areas are post fixed with the word table itself. For example, cust table is
the master table for customers. We also want to make sure we're setting the label property. This helps end users have a
more friendly name of what the table is and what it includes. For tables where the form ref property is set to display menu
item, the display menu item must exist. The title fields properties include title field one and title field two. Title field one
should be a key field for the records in the table. Use a descriptive title if the key field has information for the user. Title
field two should be a descriptive field for the records in the table. For example, the table invent item group table, the title
field one property is item group ID, and the title field two property is set to name. If the value of title field one and title
field two are the same, an error will occur. The table group property is a mandatory property set to group for tables that
contain grouping and categorization information. Deleting records from a group table can sometimes result in an unstable
situation. Enable confirm deletion for this situation. Typical examples of group tables from the standard application are
cust group and vend group. The table type property is used to set which type of table it is, if it's a regular table or a
temporary table. You can use the set TMP table method to make a non-temporary table temporary rather than creating a
copy of the table and changing the property. This way, the two versions of the table do not become out of sync. There's
also the created and modified fields that can be added to the tables. Carefully consider if you need to track the created by
date and time along with the modified date and time. Only set these properties if you need this information. Now let's
look at some of the best practices for table fields. For table ID and rec IDs, we do not want to directly use the system data
types recID or table ID. Instead, we use the extended data types ref recID for fields that refer to record IDs and ref table
ID for fields that refer to table IDs. You should review the use of memo and container fields in application tables. Memo
and container fields have the following characteristics. They add time to the application fetch and they add time to the
database fetch. They also inhibit array fetching and cannot be used in where expressions. Consider using text fields with
a specific number of characteristics instead of memo fields. For example, use the addressing extended data type for the
addressing fields. Or use the item free text extended data type for the item description on order lines. We should also
consider the mandatory allow edit on create, allow edit and visible properties. Allow edit on create determines if you can
edit the field on a new record. You should use the allow edit property to indicate if you can edit the field on an existing
record. This is usually set to yes. When it's set to yes, the field will be editable when the record is created. Set to no
when the field would be set programmatically for new records. If the allow edit is set to no and allow edit and create is
set to yes, you can edit the field on a new record but not on saved records. The visible property is usually set to yes but it
can be set to no for system only information. That's information that will not be shown in the user interface. Lastly, we
always want to use extended data types or enums as fields on the table. Fields that contain the same information should
share the same extended data type or enumeration. Let's look at some of the best practices for using field groups on tables
and forms. You should use field groups to organize related fields and related data. It's a best practice to use field groups
when designing forms as well, because when additional fields are added to the field group on a table, it will dynamically
update the form with the new field that was added to the field group. You should place at least two fields in the auto
report field group for each table except for parameter tables. The fields placed there should be the ones that the user
expects to print when they first click on print from the file menu to run the auto report. The fields used for the title field
one and title field two properties are often candidates for this field group. If you do not put anything into the auto lookup
field group, the auto lookup form will contain the fields used in the title field one and title field two properties plus the
field in the first unique index. Queries are more flexible and allow the user to modify ranges and parameter criteria at
runtime. They also allow for sorting at runtime. Because of this, it's a best practice to use a query when the nature of data
being selected is not known at runtime. When possible, it's also a best practice to create queries by adding them to your
projects and editing them with the element designer instead of building them in code. Due to queries being dynamic and
flexible, it's a best practice to use them as the underlying data source for forms and reports.

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.

MODULE 6 KEY TAKE AWAY


o Tables

▪ About tables

● Stores business transactions and metadata used in system

● Made up of records (rows)

▪ Table components

● Fields

● Make up data in the table

● Can be base enumerations or extended data types

● Field groups

● Logical groupings of physical database fields


● Used on forms and reports

● Indexes

● Speed up retrieval of data from tables

● Relations

● Define how table relates to records in other tables

● Delete Actions

● Not used

● Specified on properties of a table relation

● Methods

● Pieces of code added to a table executed when certain events occur

● State machine

● Enables workflow events to be bound to state transitions

● Mapping

● Associated map field with a field in one or more tables

▪ Adding Data Types

● Includes:

● Fields

● Base enums

● Extended data types

● About field groups

● Types of field groups

● Common uses for field groups

● Best practice checks for field groups

▪ Key Properties

● Table type

● Label

● PrimaryIndex
● ClusterIndex

● ConfigurationKey

● Support Inheritence

● Extends

▪ Table Inheritance

● Controlled by support inheritance and extends table properties

● Allows for sharing attributes or fields from a base table

▪ Temporary Tables

● Two main types

● TempDB

● InMemory

● Defined by the Table Type property value on the table properties

● Commonly used for reporting

▪ Queries

● May contain one or more tables as a data source

● Highly flexible

● Can specify details at the run time

● Reusable on forms and reports

▪ Best Practices

● Table

● Naming

● Labels

● Form reference

● Title fields

● Table group

● Table types

● Created and modified fields


● Table fields

● Table ID and Record IDs

● Memo and Container fields

● Consider mandatory, allow edit on create, allow edit and visible properties carefully

● Always use EDT or enums

● Field groups

● Use field groups to organize related fields

● Use field groups to design forms

● Auto report should have at least two fields

● Auto lookup reverts to TitleField1 and 2

● Query

● Use queries instead of select statements when structure of “select” is unknown

● Create queries in the Application Explorer instead of X++ code when possible

● Always use queries as the data source for Forms and Reports

Module 6: Your Notes


Module 7: Table Indexes
Welcome to the table index module. In this module, we'll define indexes and review the different types of indexes in
Dynamics AX. Let's begin by reviewing the objectives. The objectives for this module are to discuss the main types of
table indexes, to provide examples of each type, and then to demonstrate how to create a new table index.

Lesson 1: Fleet Management Scenario


To continue to build upon our fleet management example, we will create indexes on our fleet management tables for
efficient data retrieval. Let's take a look at the scenario. The scenario is as follows. Simon, a systems developer at
Contoso, has evaluated the amount and type of data that will be stored in the vehicle tables. He determines that an index
should be added for the vehicle ID field will prevent duplicate entries in the table. In addition, users will frequently
search these tables by vehicle type and VIN number. So an additional index will be created for each of these fields to help
improve the data retrieval process.

Lesson 2: Index Types


In this lesson, we will review the main types of indexes used in AX along with examples of each type. The first type of
index that we're going to discuss is a primary index. A primary index provides a unique key to each record in a table.
This is the index that's used for record caching in Dynamics AX. In order to be a unique index, the allowed duplicates
property on the index must be set to no. This prevents the insertion of duplicate key values in a table. The second type of
index we're going to discuss is called a clustered index. A clustered index organizes the data in the table in the order of
the index. A clustered index can also be unique in the case that the primary index and the clustered index are the same. A
phonebook is a good example of a clustered index. The data in a phonebook is first sorted by last name and then by first
name. For each last name and first name listed in the phonebook, there is a corresponding phone number and address.
The data for a table can only be organized one way; therefore, there can only be one clustered index. The third type of
index we're going to discuss is called a non-clustered index. A non-clustered index provides a way to quickly reference
data found in the clustered index using a specific set of columns. An example of a non-clustered index is the index at the
back of a textbook. You can look up the topic you want and the index provides you with a list of page numbers that have
information on that topic. For example, you could add a phone number index to a phonebook so you could more quickly
find an address by searching for a phone number. With this index, you could look up a phone number then. This would
provide a last name and first name, the key columns for the clustered index. Next, you can use these to look up the
address. This process involves a second lookup but is much faster than looking at every phone number in the phonebook.
The order of the columns in an index is very important. For efficiency, an index should be organized from the most
granular column, which means the highest number of unique values, to the least granular column.

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.

Lesson 4: Best Practices


There are many considerations to keep in mind when deciding if you should use an index. Let's review some of the best
practices. You should always maintain indexes in the development environment using the element designer on a table.
You should always specify a clustered index. This determines how the table should be organized. You should also
always specify a primary index to determine the unique key on the table. You should only add an index if the speed
improvements gained are greater than the cost to update the index. Every time a table is updated with an index on it, the
index must also be updated. And lastly, we should limit the number of columns used in an index.

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

● Provides unique key to each record in a table

● Used to record caching

● To be unique, Allow duplicates property must be set to No.

● Clustered Index

● Organizes the data for a table in the order of the 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

● Defined by one or more fields on a table

● Improve performance of data retrieval

● Can ensure existence of unique records

● Best Practices

● Always maintain indexes in the development environment

● Always specify a clustered index

● Always specify a primary index

● Add an index if the speed gained by adding it is greater than the cost of updating it

● Limit the number of columns in an index

Module 7: Your Notes


Module 8: Table Relations
Welcome to the table relations module. In this module, we will introduce how relations function on a table and discuss
how and when you should create them. Let's begin by reviewing the objectives. The objectives for this module are to
define the different types of table relations, to define the on delete property on a relationship, to create a new table
relation, and finally, to review the best practices for table relations.

Lesson 1: Fleet Management Scenario


To build upon our fleet management example that we are developing for this course, we will create a relation between two
tables in our fleet management scenario. The scenario is as follows. Simon, the system's developer at Contoso, has
identified that the vehicle table and the vehicle maintenance table are related to each other by the vehicle ID field. Each
vehicle record in the vehicle table can be related to multiple maintenance records in the vehicle maintenance table. It is
important that you are not able to delete the vehicle records if records already exist in the vehicle maintenance table.

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.

Lesson 3: Creating a Relation


Now let's take a look at the process for creating a relation between tables in Dynamics AX. So let's create a relationship
between our vehicle table and our vehicle maintenance table. We're going to create a foreign key relationship on the
dbMaintenance table. The maintenance table is known as the child table. And we always set foreign key relationships on
child tables. Now, the reason the maintenance table is a child table is because it has -- multiple vehicle ID fields can exist
within it. For example, in our main vehicle table, we have a vehicle ID one which is a certain vehicle type. And then that
particular vehicle can have many maintenance records in the maintenance table. So for that reason, we call it a child
table. To create a relationship, we go to the table we want here in our designer and under the table node, we have an
option for relations. We can right click this and specify new and we can choose relation or foreign key relation. In this
demonstration, we'll use a foreign key relation. It creates the initial relation here and we can rename it by editing this
name property or highlighting it here and pressing F2. We will call this vehicle ID relation.

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.

Lesson 4: Best Practices


There are many considerations to keep in mind when deciding to use relations between tables. Let's review some of the
important guidelines that should be followed when creating relations. When using table relations, the name of the relation
should contain the name of the table it relates to. This makes it easy to identify. A relation should be defined in the table
holding the foreign key. This is typically the child table. The validate property on the relation must be set to yes, which is
the default value for a foreign key relation. If you are using a configuration key, the key that is specified for the field in a
relation must be the same key or in the same tree of keys as the one used in the related field. Navigational relationships
do not enforce integrity constraints but they're used for navigational purposes. For example, when a form is opened
within another form. The validate property on these should be set to no. Defining navigation relationships make the
application easier to navigate.

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.

MODULE 8 KEY TAKE AWAY


o Table Relations

▪ Relations

● About relations

● Defined between tables with related data

● Relations are set on relations node beneath a table element

● Useful for performing lookups for forms

● Enforce referential integrity

● Relation Types

● Normal

● Field fixed relation

● Related field fixed relation

● Foreign key relation

● On Delete Property

● Dictates what happens when deletion occurs

● Outcomes

o None

▪ Nothing occurs to related tables

o Cascade

▪ All data in related tables is deleted


o Restricted

▪ Row is only deleted if nothing relates to it

o Cascade + Restricted

▪ Delete even though recorxds exist on related tables

▪ Best Practices

● Name of relation should contain the name of the table it relates to

● Relation should be defined on the table holding the foreign key

● Configuration key specified for field in relation must be same key or in same tree of keys

● When using navigational relationships, validate property must be set to No

Module 8: Your Notes


Module 9: Form Patterns
Hi. Welcome to the module on form patterns. In this module, we will explore different examples of form patterns as well
as sub-patterns and their application within AX. The objectives for this module are to illustrate form pattern examples.
We will then run the form patterns report and understand the data within it. Then we will apply patterns to forms. We
will apply sub-patterns to form controls, and we will define important properties.

Lesson 1: Form Patterns and Sub-patterns - Part 1


During this lesson, we will discuss form patterns and sub-patterns. Form patterns are applied to forms and determine the
specific layout as well as the controls and containers that are required for that particular pattern. Sub-patterns are applied
to certain controls or tabs on the form. Let's review the steps involved when deciding which form pattern to apply. AX
makes development easier by providing a guided experience for applying form patterns to ensure they are correct and
consistent. They help validate form and control structures and the use of controls in certain places. Using patterns also
ensures that each new form encountered by a user is immediately recognizable in appearance and function. Form patterns
can provide many default control properties which leads to a more guided development experience. The use of form
patterns also ensures better compatibility with upgrades. In Dynamics AX, many of the existing form styles and patterns
from previous versions continue to be supported and those that are not supported have a migration path. The foundational
elements of Dynamics AX are being built with those legacy form styles and patterns in mind so that the transition is as
easy as possible. Applying a pattern is a straightforward process that can modify properties on multiple containers and
controls on a form.

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.

Lesson 2: Form Patterns and Sub-patterns - Part 2


In this demonstration, we're going to look at how to run the form patterns report. This report is generated through Visual
Studio and gives us information about all of the forms in the system with the corresponding form patterns. To run this
report, we go to the Dynamics AX menu, and from the add-ins menu, we choose run form patterns report. This will
generate a CSV file that we can open in Excel. When the report is finished generating, you'll be notified with a dialog
box. It gives you the path and the name of the report. So we'll navigate to this path to open the CSV file. I'll go to my
documents and I can open my PatternsReport.CSV file.

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.

If I expand the contacts tab, this opens a FactBox grid.


We can see it's a little mini grid with just two columns that are displaying some contact information for my selected
customer. And we can hide the FactBoxes by simply pressing this arrow. And now we can go check out how they are set
up and what they look like in the development environment. So in my form design here, I have my cust table form open
again, since this is the form we were just looking at that had those FactBoxes. If I expand the parts, we can see that cust
statistics, statistics, and the ContactsInfoPart.

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.

Lesson 3: Form Patterns and Sub-patterns - Part 3


After you apply a pattern to a form, you can apply sub-patterns to a form's controls, like a tab page, for example. You
may notice a control that says pattern unspecified after the name. This means there is no sub-pattern applied to that
control. However, one may be added. The process for applying sub-patterns is similar to applying a pattern to a form.
We acquire the target control. We determine which sub-pattern we want to apply. Then we apply the sub-pattern. And
finally, we handle the errors. This time, the target should be a container control on a form somewhere under the form
design and the control should have this pattern unspecified designation after the name. We can then right click that
control and choose apply pattern and click the sub-pattern we want to apply. The available sub-patterns include sub-
patterns that can be used to migrate controls from previous versions of AX. There are many available sub-patterns in AX
so let's look at some examples. Some common sub-patterns that may be applied to a form's controls include custom filters
and custom quick filters. These are used where filters are modeled on the form. Custom quick filters is very similar to a
custom filter. The only difference is that the form pattern requires the quick filter sub-control. Image preview can be
used for most images within a form container, especially within a FastTab or group. This could be used in conjunction
with the fields and field group sub-pattern for combining images and any associated fields. It is not used for tiles or
buttons or the field status images. The fields and fields groups sub-pattern provides a responsive layout for containers that
contain only fields. For example, a tab page containing a FastTab. Selection tiles show a set of tiles or charts in a
workspace section. This should be modeled on a tab page in a workspace form . In this demonstration, we're going to
look at the sub-pattern of custom filters. And here we're looking at our general journals form. If we right click the form,
we can find out form information and it tells us the system name of the form which is ledger journal table. So our custom
filter sub-pattern is being applied right here. It's allowing us to choose this combo box to show all general journals posted
or not posted. We also have an additional filter which is a checkbox where we can show user created only journals. If we
go to the all customers form, we can also see an example of the sub-pattern custom quick filters here. This one, however,
is not configured as a combo box but simply we can type in any values we want and filter a list of customers. OK. So
let's go into the development environment and take a look at how this custom filter sub-pattern is applied on the ledger
journal table form. So I'll click back into Visual Studio and I've opened the ledger journal table in my form designer.
Now, if I go over here to the right, I can see we have this group called top fields and the sub-pattern applied is called
custom filters. So again, the main pattern of the form is applied up here on the design node and this form pattern is called
task single. Then, within our groups and our tabs and controls, we have sub-patterns we can apply to some of those. And
you can see if we expand this group, we have our two different filters, the open posted field combo box and then the show
user created only checkbox. And you'll notice once I click this group here, a blue rectangle outlines the portion of the
form here in my preview pane of where those are located. And if I select this combo box, again, it references that specific
filter right here. So now let's take a look at the image preview sub-pattern type and the fields and fields group sub-pattern.
And both of those can be illustrated on this form here.
It's the POS visual profiles form. Now, again, I can right click into any of those controls here and click form information
and I can find the form name which is the name of it in the system and the development environment and that is retail
visual profile, and then the control name which is screen. Now, if I expand this log-in background FastTab, this illustrates
the image preview sub-pattern type.

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.

Lesson 4: Layout Properties


In this lesson, we'll look at some of the commonly used properties to determine a form's layout. One form property we
want to discuss is the view edit mode property. And this is set on the design node of a form. There's the auto value which
opens the page in view mode by default. And that mode has an edit button which toggles the done, save, and restore
buttons. It's important to note that some page styles do ignore the view edit mode property, and an example of that is a
dialog box. So setting the view edit mode property to view means the page opens in view mode as well and it has no
buttons that are related to editing the page. It's always view only. If we set the view edit mode to edit, the page opens in
edit mode which means it has the save and restore buttons and the page is always editable. So then we can add an edit
records to our form. There's also an allow create and an allow delete property which is located on the root data source of
the form. Setting the allow create property to no means the page is read only. It has no new or delete buttons on that form
to allow any insertion or deletion into the underlying data source. If we set allow create to yes, this indicates that the page
allows creation of records and it has a new button. Setting the allow delete to no means the page does not allow deletes.
You cannot delete data from the underlying data source. If we have the allow delete property to yes, that means the page
does allow deletes and you will see a delete button on that form. It's important to note there's also a show/hide property
on the form design node that allows the developer to choose whether or not they want to show and hide the new and delete
buttons. We're now looking back at the cust table form to demonstrate some of the different types of form properties. On
this root form node, we have a data sources node. And if we expand that and select one of the data sources such as cust
table, we can then explore some of the properties on this data source. So we can see that we've discussed the allow create
and allow delete properties and it's set to yes for this data source. These can be defined on the individual data sources that
live within the form. If we go over to the design node, we'll notice some other properties. The caption property specifies
which text we're going to display at the top of the form which is right here. This is a system label that refers to the text
customers. So if we were to go to the Dynamics AX menu and go to find labels and I type this label in, you'll see it
returns a result with this label ID that corresponds to the value of customers. We also have the options for showing the
delete and showing the new button in our view edit mode that we discussed, which is set to auto for this form. If we go
with an individual tab or control here, we can see additional properties. These controls have properties such as the
arrangement method of the controls and fields here. We can also expand if we go to our tab page grid which shows the
grid of data, and we go to our actual grid control, we can see there's a data source property on the grid control as well that
specifies which data source on this form node is being used on this grid. And that uses the cust table since that's where
most of the customer information is stored.

Lesson 5: Check Form Pattern


In this lesson, we will cover the form pattern tab which is located in the pattern information panel. This is a tab in Visual
Studio that allows the developer to monitor the form development process and to make adjustments where needed. It
displays which controls are required and where they are needed to satisfy the requirements of the chosen form pattern.
The form pattern tab shows a visual representation of how the form should be laid out. This allows for guided
development. If a different sub-control is clicked like a tab page, the pattern tab will then update its visual with the
needed components that fall beneath that particular control. This allows the developer to ensure that every control has the
pieces needed to maintain the pattern consistency. It also notifies the developer of any errors that are in need of
correction, and then it will indicate missing controls with a red rectangular box. The form statics dialog can be opened by
right clicking the root form node and choosing add-in, then form statistics. A well-designed form will show a statistic of a
hundred percent pattern coverage. This gives you guidance in terms of making modifications to a form. This dialog also
shows a summary of different form statistics such as the control count, the data sources count, and the method override
count. It gives you the form pattern name as well as the percentage of controls that are covered by the pattern . When you
apply a form pattern like the details master in this example, the pattern tab will show you the additional controls needed to
adhere to that form pattern. We can see we have the application bar, the navigation list, and the panel tab. These are the
three subcomponents that need to be added to satisfy the requirements of this form pattern. In parentheses, we have the
system type of sub-control to add, so this is the group type, this is the action pane, and this is a tab control. We also notice
these checkmarks next to each name. These checkmarks indicate that each of these controls and their sub-controls within
them have been properly added in the correct order. If you happen to see a red rectangular box around any of these
controls, that indicates that there's an issue with this control or some of the controls within it. The main issues can be that
the control's missing or that it's not in the correct order to satisfy the pattern. We will look at a demonstration of this
functionality step by step when we create a form in the next module.

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.

MODULE 9 KEY TAKE AWAY


o Form Patterns

▪ Form Patterns and Sub-Patterns

● About Form Patterns

● Provide many default control properties

● Allow for guided development

● Create consistency and ensure better compatibility with upgrades

● Steps for Applying Patterns

● Acquire target

● Determine pattern

● Apply pattern
● Deal with errors

● Form Pattern Types

● Details master

● Form Part Fact Boxes

● Simple List

● Table of Contents

● Operational Workspaces

● Sub-Patterns

● Can be added to various form controls

● Can be prefixed with Pattern:<unspecified> after the name

● Applied in similar manner as form patterns

● Sub-Pattern Types

● Custom (Quick) Filters

● Image Preview

● Fields and Field Groups

● Selection Tiles

▪ Layout Properties

● Value: Auto

● Opens page in view mode

● Has an edit button

● Value: View

● Opens view mode

● Value: Edit

● Opens in edit mode

● 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

▪ Check Form Patterns

● About Form Pattern Tab

● Allows for guided development

● Ensures consistency

● Notifies user of errors and areas in need of correction

● Form Statistics

● Dialog shows

o Summary of form stats

o Form pattern name

o Percentage of controls that are covered by the pattern


Module 9: Your Notes

Module 10: Form Creation


Welcome to the form creation module. In this module, we will look at the form creation process and review some of the
different types of form controls. The objectives for this module are to create a form, to add data sources to a form, to
define the important types of form controls, to add controls and data types to a form, and to apply patterns and sub-
patterns to forms and form controls.

Lesson 1: Fleet Management Scenario


In the last module, we reviewed some of the different form patterns. Now let's begin creating forms to use with our fleet
management scenario. We'll create two different forms to help us effectively display data to our users. The scenario is as
follows. Simon, the developer for Contoso, needs to create a list page form and a details form to properly display
information for the fleet management system.

Lesson 2: Create a Form


In the first lesson, we will create a form to display information to the end users. The physical presentation of forms and
controls is now HTML, JavaScript, and CSS within the browser. In this demo, we're going to create two forms to add to
our project. And to do this again, we repeat the steps for adding elements by right clicking our project, choosing add, and
choosing new item. The forms live here in the user interface group. So we'll select this group and we'll choose form as
our element type. And for the first form, we'll call this DBVehicleListPage. Because we're going to end up applying a list
page form pattern to this form. OK. So we have our new folder for forms and our very first form. So I'll go ahead and do
this process again for our second form. And we'll call this one dbVehicleMaintenance. OK. So we have our two forms
opened here in the element designer. So first let's set the caption property for this form. So my dbVehicleMaintenance
form, if I go here to my properties pane, we'll see a property called caption. And this is essentially the heading, what we'll
see here on the form. So we want to make this a user friendly, a descriptive phrase. We'll just call this vehicle
maintenance. And we'll notice it appears here in my preview pane. OK. So I'll click the tab for the VehicleListPage
form. And for the caption property, we'll just call this all vehicles as this will be a list of all the vehicles in our fleet
management system. And again, we see the heading appear. So we'll go ahead and choose save to save both of our
forms. And we can see now we have these two panes in our form element designer. On the left, we have our root form
node, the dbVehicleMaintenance form. And within that, we have methods and events for adding code. We also have our
data sources and our form parts where we can add things like FactBoxes. And the right pane is where all the design will
occur. We can see right now we have this pattern unspecified. We have this new form, it's a blank canvass, and we can
right click and apply patterns to this form which would then begin the process of actually designing and adding controls.
And as we continue to add our controls, we can see them appear here in our preview pane. In our pattern pane, we will
see the different controls that are required for the pattern and the order they are required in. So we'll take a look at adding
data sources and elements and designing the form in our next demonstrations.

Lesson 3: Form Controls


Now that we've created a form, we need to add a data source and form controls so that we can define the layout and
display information. Let's begin by reviewing some of the types of form controls. First, let's review some of the various
controls that you can add to forms. Certain form patterns require certain controls to be added in a particular order. This
ensures consistency in design. Some controls are nested inside of other controls. For example, a tab page can have more
tab pages in groups beneath it. There are two panes in a form element designer. The right pane is where you will find the
root form.design node. And from there, we can begin applying patterns and adding controls. You're also able to add
group containers. These help organize how the form will store information. A tab control can be used to create FastTabs,
vertical tabs, drop list tabs, and panorama tabs. These are all configured using the tab style property. And we'll
demonstrate examples of each of these. There's also another control called a grid. This is a special type of control that
has some container behaviors such as flexible sizing. Grids display data in a table-like format. So now, let's take a quick
look at the different types of tab styles. Now, these are set using the style property on a tab control within a form. The
first one we're going to discuss is the tab style called tabs. Now, this is your standard tab page where we're clicking the
tab from up here. So here's an example. Tab page 1, tab page 2, with each tab containing different information.
Obviously we can add some more tab pages to continue building these out to the right. It's up to you. However many you
want to have. The tab style of vertical tabs is actually what this form uses here because we're clicking through these
vertical tabs here on the left. And that's kind of just re-represented here in example where we have tab page 1, and we
have some information, some fields, tab page 2, some more information and fields, and we can continue adding these just
like we have here to the left. Now, the tab page vertical tabs is very commonly used with the table of contents form
pattern which is used on setup pages. For example, when we're setting accounts receivable parameters, we would have a
tab page that relates to some type of information. The next tab page where we can set some other information. So that's
the concept of the vertical tabs. It's a vertical list and we click them and we have different information within each one.
The tab style of FastTabs, this is commonly seen on details masters forms where we're looking at the details of some
entity, for example a customer. We have this ability to kind of expand and collapse these FastTabs by using this arrow
and when we expand them, we see information, some fields related to a particular kind of group. For example, we could
have addresses be the name of this FastTab. And then within it, we have things like address line one, address line two, zip
code, et cetera. Now, the tab style for panorama, you actually don't have to click to get to the other tab pages like we saw
in the previous examples. It's kind of a horizontal layout within the same page. So for example, this kind of column here
is the tab page one. And we scoot over and we have our tab page two column and we can continue adding more columns
that kind of represent a tab page within the same view. And the panorama style is very commonly used on the workspace
form patterns and the operational workspace form patterns. It kind of creates this panorama of different activities within
these certain kind of panes or columns within the page. The last tab style is called a drop list. And this is represented by a
little drop down arrow and we can choose from a list of tab pages within that drop down. And again, each tab page has its
own kind of set of information within it. The action pane or application tab runs across the top of a form and contains
buttons and tabs to perform certain actions within that form.

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.

Lesson 4: Adding Elements


In this lesson, we will add elements to a form. The first item we need to add is a data source. We will specify which table
or query we want to add to feed data into the form. Now that we have our two forms created and we've set up our
captions, let's go ahead and add data sources to each form and apply our form patterns to each form. So I'll start here with
my dbVehicleMaintenance form. And I will add a data source from my project. And what I'm going to do is expand my
simple queries folder and I'm going to use my dbVehicleMaintenance query as the data source for this form. And I can
simply click it and drag it out here to the data sources node on my form. And remember, when we created this
dbVehicleMaintenance query, we added two tables. The dbVehicle table and the dbMaintenance table. In the query, we
nested them and related them. However, here, on the form, they just show up in a kind of list format, just to specify which
tables are actually included in this data source. So that's a quick way to add a data source to a form. And to apply our
pattern, we'll go over here in the right pane to our design node. We can right click. And we'll choose apply pattern. And
for this form, we're going to use one called task single. And we'll notice here the pattern tab automatically populates with
these different controls that are required to create this form with the task single form pattern. And these are the order that
they're required in. So we'll take a look at building these out step by step in another demonstration. For now, let's flip
over to our DBVehicleListPage form and I'll click my tab here since it's already opened. And again, I'm going to add a
query as a data source for this form. I'll choose my dbVehicle query. Drag it on to the data sources node. And we'll see
this query only has the dbVehicle table so that's what we're getting. And now, we'll go over to the design node. We'll
right click and we'll choose apply pattern. And for this form, we're going to use a list page pattern. So I'll choose that.
Again, we see our controls that are required for this pattern. They're currently all highlighted in red because they have not
been added yet. It's an indication that we need to add those to satisfy this form pattern. So for now, we'll go ahead and
save all, just save the changes that we've made to both forms. And then in the next demonstration, we'll go ahead and
begin adding these controls to build out the actual design for both of our forms. Now that we have our form pattern, let's
go ahead and start building the actual controls we need for this form. And in this demonstration, we're going to build out
our DBVehicleListPage form which uses the list page form pattern. To begin adding controls, we simply right click on
the design node and we'll choose new. And from here, we have all these different types of controls that can be added to
the form. However, we want to follow what's in this pattern tab here. So it's showing us the first one we need is the
application bar, and parentheses, it's called action pane. This is typically the name that we'll see here in our form pattern
list. So action pane is right here. I'll choose it. And we can see once we choose this control, the form pattern
automatically refreshes with the requirements for this control. So if we go back up to our design node, we can go back
and see which controls are needed for the overall high level design. And as we start adding these, more controls will be
required for the sub-controls. So let's go ahead and continue building out our main design node here. So we've added our
action pane. Now we need to add a group control. So again, I'll right click. I'll choose new. And I'll go down -- it's in
alphabetical order -- to find the group. And I'll choose that. And we can see this particular control has this pattern and
then a select designation which means this one will allow to you add a sub-control to this particular control, or a sub-
pattern to this particular control. So go back up to my root design node again. You can see that the application bar and
custom filter group have been added. Now I need to add a grid. So right click the design node. I'll choose new. And I'll
go to grid. OK. So let me go back up to my design node and we can see now there are checkboxes next to each type of
control to indicate they've all been added and they are in the correct order. Now, if I click my action pane control, there's
no requirements here for this sub-control. So that one is good to go. If I choose my form control group one, again, this
one doesn't have any specific requirements. And the grid control does not have any specific design requirements.
However, we can definitely set some properties on these so a good idea would be to set the caption and the name if you
wanted to rename this particular action pane. We can also do that for each control so the group, if this was representing a
specific group, so maybe this is going to be now vehicles. OK. Now, for our grid, this is where we are actually going to
display data on the form. So what we need to do in the properties for the grid is go to this data source property which is
within the data group, if you have your properties pane organized by category, and we can choose the drop down next to
data source and we'll choose dbVehicle. This is our main table that's going to be the data source for this form. And we're
also going to use this as a data source in our grid which is ultimately going to display data to the end user. OK. So now
that we have our grid, we can begin adding different fields to this grid. So for example, if I expand my data sources in the
left pane, and I'll expand my dbVehicle table, and then I will expand fields, we can see my fields that I have available in
that data source. And for my VehicleListPage, I can just drag these fields over here onto the grid and that's going to
indicate which fields I want to display on the form and in which order. So let's go ahead and start by dragging the
dbVehicleID over to our grid control. We can see it shows up now here as a string. So I'll continue adding a few more.
Let me go with the VIN number and vehicle type. And I'll go with the make and model. And I'm using control click to
select multiple fields, so you don't necessarily have to drag them one by one. And then go ahead and add our year onto
the form. And we'll add that right after the make and model. And if we want to move this up, say we want the year field
to display on the grid before the make and model, we can simply highlight the field, we can hold the ALT key and press
the up arrow, and it shifts our field up. Each time we press up, it moves it higher in the order. So that's going to dictate
the display order on our grid, on our form. So that's an overview of how we add controls to satisfy our main design
requirement and then we can add fields to a grid control by dragging them from our data source once we specify the data
source property on our grid. So we've added some fields to hour grid control here on the DBVehicleListPage form. Now
we can go ahead and save all and then we can go preview how our form looks at this point in the development phase. So
I'll switch over from my pattern tab here to the preview tab and we can see now we have my caption, we have the caption
I specified for the specific group control, and then we have our fields here laid out in the order that we added them to our
grid. Just as they appear here. OK. So now, we can go ahead and kind of repeat these steps for the
dbVehicleMaintenance form. Now, this form uses a different form pattern so it's going to require different controls as we
can see here. So let's go ahead and right click and we'll choose new to begin adding the control for the application bar or
the action pane. OK. And if we want, we can go ahead and add different pieces below this action pane such as an action
pane tab and button groups. However, for this form pattern, it's not required so let's go ahead and meet the requirements
first and build out our form that way. So the next requirement is the details tab. And that is a tab control. So if I right
click the design node, choose new, I can go down till I find my tab. And I can choose that. Now you'll notice this tab
control has other requirements for this particular control. So you have to keep an eye out for the requirements not only for
the high level design pattern but also for each sub-control. OK. So we can see here it's now highlighted in yellow
because it has been added but there's still something that needs your attention. So we'll go click our tab control and see
that this tab control needs to have another tab page added beneath it. So we'll right click the tab control and we'll choose
new tab page. Now, this is the only thing that can be added beneath the tab control. And again, our tab page control has
the option to apply sub-pattern for that control. OK. So if I click up to my tab control, we can see that these requirements
have been satisfied with this checkmark and I can go back up to my root design node and see that the other requirements
have been satisfied. The custom filter group says none. That means it's OK for this pattern not to have one. And there's a
checkmark. However, we can add one if we wish. Same thing goes for the footer group control. So let's go ahead and do
a save-all again. And we can flip over to our preview tab here and we can see there's this tab right here. That's a clickable
tab page. And as we continue to add more tab pages below this tab control, we will see more tabs pop up here to the right.
So we would go ahead and repeat the process for adding fields onto these different controls. So for this pattern, we can
add a grid somewhere in here, on a certain tab page, and then we would go ahead and drag our fields from our data
sources onto the grid control that would allow us to display information on this form. So we've added our data sources to
our forms and we've got these form controls set up that go along with our patterns and we've even went ahead and added
some fields to our grid here on this VehicleListPage form. So the last thing we have to do when building our forms is our
sub-patterns. So you can see we have checkmarks next to our three main controls here that say this list page form pattern
is looking pretty good. However, if we go to build this project, we would get an error since this particular group control
here does not have a pattern designated. So what we would need to do is right click this group control and we'll apply a
sub-pattern to it and we can see our only option is the custom and quick filters because that is the sub-pattern required by
this particular main form pattern of list page. So once we go ahead and apply this custom and quick filters sub-pattern, we
can see down in our pattern tab it has updated with the requirements for this sub-pattern on this control. We need to add a
quick filter control. So I can right click my form group control one. And I'll say new. And I'll go down to quick filter.
We can see it adds this quick filter control beneath my main group control. And now if I click this group control node,
and we look in our pattern tab, everything looks like it's checking out. So we'll go ahead and save this. And now if we
were to go to our other form, the dbVehicleMaintenance form, we can see here that this group control already has these
sub-pattern applied. However, we added this tab page control and this one needs a sub-pattern as well. So in order to get
this to build correctly, we would have to come here, right click this control, and we'll choose apply pattern and this one
wants the tool bar and list sub-pattern. OK. Then we would continue adding these controls for this tool bar and list sub-
pattern. It looks it's missing this grid tree list view table. So we would go through and keep adding our controls to make
sure that our sub-patterns and patterns are having everything they need to build correctly and ultimately to get our form to
work.

Lesson 5: Best Practices


Now let's review some best practices to consider when developing forms. When naming forms, the form name should
match the main underlying table that is the data source. This makes it easier to know where the data is coming from and it
keeps thing uniform in the system. Whenever possible, we should keep the sizing properties to auto or default to ensure
consistent output. Using the form statistic add-in will help give us more information about the form and the form
controls. This also tells us how much of the form's controls are covered by the chosen pattern. Placing code on forms, a
forms method, should be avoided unless it is a last resort. Codes should typically be placed in a class or table. That way,
it can be more easily reused and customized.
Module Review
In this module, we created some different types of forms to use in our fleet management system. We discussed how forms
are designed and the different types of controls that are used in the creation process. We added data sources, controls, and
elements to the form. Then we chose a pattern to apply and used the pattern tab to help debug and guide the development
process.

MODULE 10 KEY TAKE AWAY


o Form Creation

▪ Form Controls

● Form Design Layout

● Form.Design

o Root of page

● Group

o General-purpose container control

● Tab

o Control that contains TabPage controls

● TabPage

o Appearance of each TabPage control depends on Tab.Style value

● ButtonGroup

o Special type of Group control that contains buttons

● Action Pane Hierarchy

● ActionpaneTab1

o ButtonGroup1

▪ Button1

▪ Button2

● Types of Buttons

● Button

● Command Button
● Men Item Button

● Drop Dialog Button

● Menu Button

● Toolbars

● Toolbar represented by Add, Edit, Map buttons

● Previously known as “Action Pane Strip”

● Grid Styles

● Tabular Style

● List Style

● Simple read only

▪ Add Elements

▪ Best Practices

● Name the form to coincide with the main data source table

● Use the “Auto” and “Default” properties for sizing

● Use the Form Statistics add-in for guidance

● Try to cover all controls with the applied pattern

● Avoid placing code on forms

Module 10: Your Notes


Module 11: Menus
Welcome to Module 11 on menus. We will be covering the creation and application of menus and menu items for use
within the user interface. The objectives for this module are to review how to create and use menu items. Then we will
create menus and attach menu items to them.

Lesson 1: Fleet Management Scenario


Now let's review how menus and menu items will be used for our fleet management scenario. For the fleet management
scenario, we will need to build menu items that point to the newly created forms. We would build a menu to contain the
top-level form, the VehicleListPage. Then we'll link all of the menus using the menu extension to the existing menu
structure of AX. Lastly, we will create menu item buttons for the vehicle and vehicle maintenance forms.

Lesson 2: Creating Menu Items


In this lesson, we'll review creating menu items. There are three main types of menu items that are used in AX. The first
one is called a display type menu item. This must be used for runnable application objects that primarily present forms or
dialogs to the user. We would attach the menu item type of display to a form for example. The second menu item type is
called output, and this must be used for runnable application objects whose primary function is to print a result. A good
example for using an output menu item type would be an SSRS report. The third type of menu item is called action. This
must be used for runnable application objects whose primary function is to do some kind of job such as creating or
updating transactions in the database, and this would be linked to a class. Let's review some key property values on
display menu items. The first one is the form view option property. And this specifies which form mode to use when a
form is opened from a menu item. For example, we can have the form opened in the view mode of details view or grid
view. There's also a property value called auto. Next is the normal image property. And this specifies which image will
be used when the menu item is associated with an enabled button control. The open mode property specifies the view
mode of the object. For example, a form can be opened in view only mode or edit mode using this property. The help
text property creates a help string for the menu item. This will be the text that appears in the status bar when you select
the object opened by the menu item such as a form. The label property is what's displayed in the user interface. For
example, it will be the name of the link that appears in the UI which would launch a formal report. Now let's look at the
key property values for the output menu items. The first one we're going to discuss is the enum parameter. This specifies
which enumerated type we want to use as a parameter for the object that our menu item is linked to. We would then select
an enum type parameter which would be the enum value for that property. These two properties are optional. These
properties are typically used when one form is used in several different situations. You can change the behavior of the
form depending on the enum parameter value. For example, the price disc group form is used by three different display
menu items. Each have a different enum parameter value and the forms in knit method, we would use a switch construct
in X++ which would check the value of the enum parameter and then construct the form accordingly. The linked
permission object property specifies another object such as a form or report whose permissions are to be applied to this
menu item. The linked permission type property then specifies the type of the object pointed to you by the linked
permission object property. Now let's look at the key property values for action menu item. The first one we're going to
discuss is called create permissions. And this property specifies whether the create permission will be available to select
when privileges are assigned to the menu item. The property values or choices are auto, which means the permission will
be available to select as a privilege on this menu item. If we choose the no property value, the permission will not be
available to select as a privilege on the menu item. The default value for this property is auto. The delete permissions
property specifies whether delete permissions will be available to select when privileges are assigned to the menu item.
The auto value means the permission will be available to select as a privilege on this menu item. The no value means the
permission will not be available to select as a privilege on this menu item. The default value again is auto. The extended
data security property specifies that the menu item appears under all companies instead of in the context of a single
company. The default value for this property is no. The configuration key property selects which configuration key is
required to enable the menu item. Use the key for the module that the object belongs to. So we've created two forms and
we've got our patterns and sub-patterns configured and our controls set up to get our basic form to display. Now we're
going to create two menu items to associate with each of our forms. Now, to do this, we right click our project, we choose
add and new item, and to display a form, we need the display menu item. And that is located in the user interface group.
So I'll choose display menu item. And the first one I'm going to create is called DBVehicleListPage. I'm going to name it
the same as the form that it's going to open. And when I choose add, again, we get a nice new folder here with our menu
item. It also opens up over here by default in the designer. So when I select it here, I can then begin editing the
properties. And the first property we want to set is the object type. There's a drop down with some different selections
here. For our purpose, we are going to use the form object type. And then the name of the form. We can use the drop
down here to see a list of all the forms. But since we know the name is just DBVehicleListPage, I'll go ahead and type
that and press enter to confirm that that is the string I want. And then we'll scroll up here under the appearance group and
set the label property. This is going to be what appears in the menu. When the user clicks the menu item and the link, this
is the text it's going to display. So I have this be all vehicles. And I'll choose enter. So now, we have this menu item. It's
a display menu item that's associated with our DBVehicleListPage form. And we can go ahead and repeat that process to
add a second display menu item and associate that with our dbVehicleMaintenance form.

Lesson 3: Creating Menus


In this lesson, we will cover the creation of menus. Menus are prebuilt to include all of the accessible items in AX from
the navigation pane. These are in context to each specific security role and can be modified. So for example, from our
navigation menu here in blue on the left, we can navigate to the cost management menu. And then we can navigate to the
manufacturing accounting submenu within the cost management menu. And then finally, we can click on one of these
menu items here at the end. For example, we can choose production order and then that would launch some type of form
or runnable object from that menu item. Let's take a look at some of the key property values for menus.

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.

MODULE 11 KEY TAKE AWAY


o Menus

▪ Creating menu items

● About menu items

● Display

o Used for presenting forms, dialogs and so on


● Output

o Used to print result (reporting)

● Action

o Used to do jobs such as creating or updating transactions

● Key Property Values on Display Menu Items

● Form View Option

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

o Specified view mode for object

● Help Text

o Create help string for menu item

● Label

o Displayed in user interface

● Key Property Values on Output Menu Items

● Enum parameter

● Enum type parameter

● Linked permission object

● Linked permission type

● Key Property Values on Action Menu Items

● Create permissions

● Delete permissions

● Extended data security

● Configuration key

▪ Creating Menus

● About Menus
● Prebuilt to include all accessible items

● Key Property Values on Menus

● Menu Item Type

● Menu Item Name

● Configuration Key

● Normal Image

● Label

Module 11: Your Notes

Module 12: X++ Overview


Welcome to Module 12. In this module, we'll give an overview of the X++ programming language within AX. The
objectives for this module are to explore the code editor, to review the controls of the compiler, to create a runnable class
to test code, to review the IntelliSense feature for coding, to introduce variable declaration, to review basic code syntax,
and to identify keywords and operators. Further objectives for this module include to review the comparison tools for
code comparison, to demonstrate how data types are used in code, to discuss the use of the debugger, and finally, to
review code best practices.

Lesson 1: Fleet Management Scenario


In this lesson, we'll review the fleet management scenario for the X++ module. For the fleet management scenario, we
will create a basic class using a static method in order to familiarize ourselves with the coding process. Special attention
in this module will need to be given to the code editor, IntelliSense, syntax, and code statements in order to complete the
future scenarios.

Lesson 2: Code Editor


In this lesson, we're going to review the code editor. X++ is an object-oriented programming language which consists of
three main components. Those are classes, methods, and objects. We will discuss these components as we go throughout
the course. X++ code for a Dynamics AX application is written in the code editor for Visual Studio. That's what we're
looking at here in our screen shot.
The standard features that a developer expects from the code editor are supported. For example, sections of codes are
collapsible using these plus and minuses here on the left-hand side of the code editor. IntelliSense is also a feature that
provides guidance as you write or modify code. It will possible up with suggestions of certain objects. You will also use
the code editor in Visual Studio to write X++ code for your applications. The X++ language is fully integrated into the
Visual Studio environment. You can navigate to methods and classes in the code editor window using the navigational
drop-down menus located at the top of the code editor window. X++ code runs as .NET CIL. And this comes with many
benefits. One of those benefits is that the CIL runs much faster in many cases. When there are many method calls or
algorithmic content, you can expect significant performance improvements. It's also easier to write application logic in
other managed language. AX assemblies can be consumed directly. The preferred way of consuming business logic in
AX is externally using services. CIL can efficiently reference classes that are available in other .NET assembly DLL
files. CIL can also be operated on by many of the excellent .NET tools available. For Dynamics AX, the X++ compiler
has been rewritten from scratch. No backward incompatible changes have been introduced. An X++ best practice tool
has also been implemented. It allows the addition of user-defined custom rules. The standard compilation unit for X++ is
the same as for other .NET languages like C#. If any method out on an AX model element like a class or form, fails to
compile, the whole compilation fails.

Lesson 3: Create a Runnable Class


In this lesson, we will demonstrate how to create a runnable class which is based on a static main method. To create a
runnable class, we'll need to add the runnable class element type to our project. To do this, we'll right click our project
from the Solution Explorer. We'll choose add, and choose new item. On the left pane under the artifact group type, we're
going to choose code. And the last choice here in the list is the runnable class element. So we'll select that and we'll give
it a name. We'll call it dbHelloWorld. And we'll choose add. Now, again, it creates a new folder for the new element
type of classes. And it opens up by default here in the code editor. So we have our class named hello world. And then
within that, we have this static main method. This is a method used to test code really quickly.

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.

Lesson 5: Data Types


In this lesson, we'll discuss composite data types used in X++ as well as extended data types. We discussed the different
primitive data types available for use within AX in Module 5. The table below is for review. Composite data types are
those that contain other data type constructs. Let's take a look at some of the X++ composite data types. The first is an
array. An array represents a list of items of the same data type. For example, you can have an array that contains ten
different strings. The only thing that changes is the index. So we have an array of index one that references the first
element of the array. Containers are a dynamic list of items containing primitive data types and/or some composite data
types. Containers may be a mix of different data types. A class is a type of definition that describes both variables and
methods for instance objects of the class. This is using classes as data types. Tables can also be used as data types. All
tables defined in the database can be handled as class definitions. We discussed the element extended data types in
Module 5. Extended data types are commonly abbreviated as EDTs. An EDT is a primitive data type or container with a
supplementary name and some additional properties set. For example, we can create a new EDT called name and base it
on not a string, and thereafter, we can then use that EDT and variable and field declarations in the development
environment. When you declare a variable in X++, we use the syntax shown in the following table. We'll review some of
the benefits of using EDTs. Code is easier to read because variables have a meaningful data type and referenceable name.
The properties you set for an ETD are used by all instances of that type which reduces work and promotes consistency.
You can create hierarchies of EDTs which inherit the properties that are appropriate from the parent and changing other
properties as needed. The following code snippet shows an example of declaring and using an EDT in X++.

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.

Lesson 6: Variable Declaration


In this lesson, we'll look at how variable declaration works in X++. Variables can be declared in small scopes. This
means you can declare a variable within a specific block of code that you're using. This makes things easier to read. And
this concept is known as inline variable declaration. We can also declare variables prior to using them in an executable
statement. They're scoped closer to their use, and therefore, they're easier to find. The var keyword is available for the
compiler to infer the data type. It can be used for declaration of local variables, but it must be clear for the inferred type
and the initialization process. We can assign a value to a field in line with the declaration. This reduces the amount of
code lines and improves the readability of assignment. In this demonstration, we're going to talk about variable
declaration and using the var keyword. So I have opened my dbHelloWorld class. This is a runnable class, and currently,
it's just outputting this message to the Infolog. So I'll go ahead and paste some new code in. And here, we're using the
var keyword up top at the beginning of our method to declare two variables.
The first one is gallons used and the second one is called miles driven. And you'll notice as I click each one, it highlights
them where they appear in the code below. The var keyword is used to declare a variable that the compiler infers the type.
So when I declare this gallons used variable, I have to instantiate it or give it a value when I'm using the var keyword. So
the compiler knows that this is probably going to be an integer since I'm assigning the initial value of zero to it. Likewise,
with the miles driven variable, I'm instantiating the value to 500. So with the compiler saying, hey, this looks like an
integer, and from then on out, we're going to be using that variable as an integer in our code. So I've initialized gallons
used to zero and miles driven to 500. Then I put a simple division, arithmetic operator here to divide the miles driven by
25. So essentially, we're dividing 500 by 25 miles per gallon to get me this gallons used variable. Now, in the Infolog, it
expects a string to be outputted within the parentheses. However, since the gallons used is being inferred by the compiler
as an integer, we use the INT2STR which is the integer to string conversion, and we wrap that in parentheses as well. So
it converts this integer value of gallons used into a string so that we can output it into the Infolog. So I'll go ahead and
press CTRL S first of all to make sure there are no errors. Once you perform a save, if there are any errors in your code,
they will be indicated with the red underline. So since there are no syntax errors or lodged errors, I can go ahead and
press CTRL F5 to perform a build and run this class. So we'll do that. All right. So our build has completed. We can go
check out the class runner. And we can see that the output now is 20, which is the value we would expect. I'll go back to
Visual Studio and I want to note that we can declare variables here at the beginning of our main method or any method,
and we can also declare them in line as we use them throughout the code. If I were to go down further in the code, I can
declare a variable as I type. And we'll look at examples of inline declaration when we cover while and for loops.

Lesson 7: Key Operators


In this lesson, we'll review the key operators in X++ code. The following table shows some of the different assignment
operators in X++. The first one is the equals sign. This assigns the expression on the right of the equal sign to the
variable on the left. The plus equals operator assigns the variable on the left the current value plus the expression on the
right. The double plus symbol increments the variable by one. The minus equal sign assigns the variable on the left the
current variable value minus the expression on the right. And the double minus symbol decrements the variable value by
one. The following table provides a list of arithmetic operators that can be used in X++. The first one is what's known as
a left shift. And it's represented by two less than signs in successive order. A left shift is simply a multiplication by two
on expression1. So if I had something like one followed by my left shift operator, and then a four, that means to perform
four left shifts on the value of one which is four multiplications of two. So one times two times two times two times two,
which would output a value of 16. A right shift is a similar concept, expect for it uses a division by two and it's
represented by two successive greater than symbols. The asterisk implies multiplication. So if we had 4*5, the output
would be 20. The forward slash is for division, so if we had 20 forward slash five, the output would be four. The DIV
operator is used for integer division. So it only returns whole numbers based on two expressions. For example, if I had
100 DIV 21, it would return a four since 21 only goes into a hundred 4 times. It would have a remainder of 16. However,
that value is not returned using the DIV operator. Now, if we use the MOD operator with the same expression, 100 MOD
21, it would return the value of 16. That's the remainder from the division. The tilde is a unary operator. And this
performs a binary not operation. That means if we had tilde one, it would give us an output of negative two since it's
using binary. The ampersand is a binary and. So that performs a binary and operation on two expressions. Likewise, the
caret represents the binary XOR operation. And the single bar represents the binary OR operation that performs a binary
OR between with two expressions. And the single bar is usually located under the back space key on most keyboards.
The plus and minus symbols represent themselves where the plus symbol adds expression1 to expression2. And the
minus symbol subtracts expression2 from expression1. The question mark is what's known as a ternary operator. It takes
three expressions. So we can have something like expression1, question mark, expression two, colon, expression three.
That means if expression1 is true, it will return expression2. However, if it's not, expression three will be returned. Now
let's look at a table of relational operators that can be used in X++. The first one is the like operator. This returns true if
expression1 is like expression2. The like operator can also use an asterisk as a wild card to represent zero or more
characters or a question mark as a wild card for one character only. For example, we can have something like if vehicle
ID like one asterisk, then perform some logic. That would return true if the vehicle ID simply began with the number one.
If we used if vehicle ID like one question mark, that would only return true if there were only like two characters. If there
was like 10 or 11 or 12, something that began with a one had another character after it. The exclamation mark is the not
operator. It's a negation operator that can be used in front of a field or table or a statement. The exclamation point equal
sign is the inequality operator and it means if expression1 is not equal to expression2. The hash tag or pound sign symbol
represents a prefix on macro names. So that indicates that a macro is being run and macros are found under the code node
in the Application Explorer. The double ampersand represents the logical and. If expression1 and expression2 are true,
we use the double ampersand. The logical or is represented by two bars. So we can have expression1, double bar,
expression2, and that simply means if either of those is true, go ahead and proceed with the rest of my if statement. The
less than sign is represented by the less than symbol. Likewise, the greater than symbol is represented by the greater than
symbol. To determine equality, we use the double equal sign, and that returns true if both expressions on either side are
equal. The greater than or equal to symbol is represented by a greater than sign followed by the equals sign. So we can
say if expression1 is greater than or equal to expression2, proceed with some other logic. The order of operator
precedence is very important when determining how things will be executed in your code and ultimately helping you
achieve the output that you want. The order is indicated by this table with the first one being the unary operators. Those
are things like negation. The second order is the multiplication, the left and right shifts, and the bit wise or binary and.
We also have the bit wise exclusive or. The third order of operation is additive which is subtraction and addition. Or the
bit wise binary inclusive or which is represented by the single bar here. The fourth thing to be executed is the relational or
equality operators. And those are things like greater than, less than, equal to, like, or the not equal to symbol. Fifth is the
logical operators and and or. The double ampersand representing the and, and the double bar representing the or. And
lastly is our conditional. This is the true unary operator of the question mark and the colon that's associated with those
expressions.

Lesson 8: Basic Syntax - Part 1


So now let's overview a little bit more on the basic syntax of using X++. In Visual Studio, the methods start with a one-
tab indentation. Everything within the method starts with a two-tab indentation. The starting parenthesis on method
declarations and calls should be the character just after the method name. If there are one or two parameters, the
parameters can be listed on the same line. However, if there are more than two parameters, we should move each
parameter onto a new line and indent by four spaces to keep things readable and clean. Some other considerations to
consider when using syntax are to only have one statement per line. You should break up complex expressions that are
more than one line just to make it visually clear and easier for people to read. You should use a single blank line to
separate entities. Do not use parenthesis around the case constants. And do not use parenthesis around where
expressions. Add one space between if, switch, for, while, and the expressions starting parentheses. Use braces around
all code blocks expect for around case clauses in a switch statement. Use braces even if there is only one statement in the
block. There are three main types of basic output that we can create from our code. The first one is what's known as a
box. Next, we have an Infolog, and finally, we have a dialog button. Let's take a look at some syntax for utilizing a box
type output as well as an Infolog type output. In the first example, we're using the box keyword followed by two colons
and then the word info. And then in parentheses, we have three different text or stream parameters we can enter. The first
one is what's going to be contained in the body of the message box followed by a comma and then the second string which
is going to be what text appears in the title of that message box. And finally, we have what we want to display as the help
text in that message box. Another type of box output is called the warning box. And again, this uses parentheses to
enclose three different types of streams separated by commas. Similar to the info box, we have this warning box and it
uses the first parameter as the body text for the warning box. Then we have the warning title, followed by the help text
for that box. Next we have the Infolog. This is the second output type we're going to discuss. To use an Infolog output,
we simply use the info keyword and then in parentheses, we enclose a certain sentence or string in quotations. We can
also pass through variables within the info keyword. We then have the warning Infolog message type. And again, it's a
similar syntax. It's just a sentence or variable. And if we use a textual sentence, we enclose that in quotation marks to
indicate the beginning and ending of that sentence. And finally, we have the error Infolog. This is using the error
keyword. And then again, we follow the same syntax with the parentheses and quotations around our string or sentence.
The third type of output syntax we're going to discuss is what's known as a dialog. And in the code here, we're
instantiating and creating a dialog button object and then we're setting the value to be a yesNoCancel box. And a
yesNoCancel box contains three buttons. The yes button, the no button, and the cancel button. And within parentheses
here, we're specifying what to contain in the body of the box and then how to handle the situation where the dialog button
yes is chosen. So let's take a look at some of the different types of conditional statements and loops in X++. You can
specify conditions under which a block of code must be executed or skipped. Each conditional test evaluates to either true
or false. The first type of conditional statement we're going to look at is called an if statement and an if else statement.
This evaluates a question or a condition and executes a statement or a set of statements if the condition is true. You can
provide an alternative statement or set of statements that are executed if those conditions are false. That would be handled
by the else statement. A switch statement is a multi-branch language construct. You can create more than two branches
by using the switch statement. This is in contrast to the if statement. You have to nest statements to create the same
effect when using an if statement. The next type of loops we're going to discuss are repetitive constructs in X++. X++
has three types of loops. The first one is called a while loop. This enables you to repeatedly execute one or more
statements as long as a condition is true. The statement is executed from zero to many times, depending on how many
times the condition is met. A do while loop is similar to the while loop in the way it loops over repetitively. However, it's
always executed at least one time, whereas a while loop does not have to be executed at all if the initial condition is not
met. Lastly, we have a for loop. This is similar to the while loop as well, only there's an initial value to control the
variable, and you can increment or decrement that value to handle the flow throughout the loop. Two types of conditional
statements that we're going to discuss are the if else statement and a switch statement. And these are both used to answer
a question or check a condition and then perform some logic depending if that condition is true or false.
So in the left pane, we're going to analyze an if else statement. And then in the right side, we're going to check out a
switch statement. So I'll go ahead and begin on the left with the if else statement. Now, here we're initializing an integer
variable called oil change and setting it to an initial value of three. Our if statement begins with the if keyword and then
in parentheses, directly next to it, the condition we want to check. So we're saying, if the oil change variable is bigger
than or equal to two, then go ahead and execute whatever is between these two brackets beneath the if statement which is
this Infolog message of a repeat customer. If this oil change greater than or equal to two is not true, then we'll go
immediately to our else statement and skip all this logic here. So then it executes what's between the brackets and the else
statement which is an Infolog message displaying new customer. For the switch statement, it's slightly different but uses a
similar kind of checking of conditions. So here, we're initializing again an oil change integer variable three and we're also
initializing a string variable called answer. And answer we're going to use to output ultimately at the end in our info box,
depending on which case is true in our switch statement. The switch statement begins with the switch keyword followed
by a variable or condition in parentheses, and we're simply sending through that oil change variable which has a value of
three. And then enclosed in all the brackets are case scenarios. So case where the variable being passed in is one
followed by the colon and then if that case is true, we execute this code. If case where it's two is true, we execute this
code. Otherwise we execute our default case which is this little block of code. So the default kind of switch here is
similar to an else statement which says if case 1 and case 2 are not true, execute the default statement. So we know that
an oil change variable is not one and it's not two. Therefore, it would execute the default statement which sets our string
variable answer to frequent customer. We then break from the code and output that to an Infolog. Two commonly used
types of loops in X++ include while loops and for loops.
On the left-hand side we have an example here of a while loop. On the right-hand side we have a code snippet for an
example of a for loop. So we'll begin in the left and discuss this while loop here. At the very beginning, we're initializing
an integer variable called counter1 to a value of zero. We then use the while keyword to initialize a while loop and a
parentheses is the condition to evaluate that loop under. So this while loop will continue going until the counter1 variable
does not equal -- will continue going while the counter1 variable is not equal to four. As long as counter1 is not equal to
four, the code within the brackets will be executed here. These two lines. And what they're doing is displaying an Infolog
with the variable of counter1 which has been converted from integer to string for the purposes of displaying it in the
Infolog message and then we're incrementing the counter1 variable by a value of one using the ++ operator. So this while
loop would go through several times until the counter1 reached four at which this condition is no longer true and it would
stop executing. So it would go through once with the counter1 variable zero, then it would go through again,
incrementing it by one, the counter1 value is now one, and it would keep going, and once it hit four, the while loop would
stop. So this Infolog would print each time in the loop until that counter1 variable hit a four. In the four loop example,
it's very similar exempt for we have three conditions in the parentheses, and we use a keyword four, and then within our
parentheses, we have three different pieces and the first piece is where we initialize our counter variable. So we're again
specifying an integer variable called counter2 and we're setting the value to zero. Then we have our semicolon, and the
second piece within a parentheses is the condition to evaluate the four loop under, which is the same as the condition here
for this while loop. We're continuing this loop while the value of counter2 is not equal to four. And then the third piece is
how we're incrementing our counter variable and we're using again the ++ operator which increments it by a value of one.
And then we go ahead and execute the code within the brackets here which are these two lines. So it's going to output an
Infolog that says counter2 is, and then this percent one is actually replaced by the variable counter2. So you'll notice we
have this quotation mark which is a string followed by a comma. And after the comma, that very first variable is
substituted in the percent one piece here in the output. So it would keep outputting this info message again multiple times
looping through the four loop until that counter2 does not equal the four condition has been met. At which point the loop
will stop executing.
Lesson 9: Basic Syntax - Part 2
Let's take a look at how the if else statement works in our runnable class.

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.

Lesson 10: Comparison Tools


In this lesson, we will discuss comparison tools which can be used to compare different pieces of X++ code. When using
comparison tools, you have the opportunity to have the original code in the left pane, the new code in the center pane, and
the merged code in the right pane. You can then interact with all three. To install the comparison tools, it is required to
have source control both configured and installed. In addition, there are Visual Studio extensions that can be installed for
comparison. If you are developing using overlayering, you can also use comparison tools to compare the code in different
layers. Refer to MSDN for the version of Visual Studio that you are operating for both the extensions and command line
options to compare code versions.

Lesson 11: Debugger


In this lesson, we will learn about how the debugger works in AX. To debug X++ code in AX, you will use the debugger
in Visual Studio. The debugging process is similar to debugging any other application created with Visual Studio. For
example, the standard tools for examining the application are available when your code is stopped at a breakpoint. To
debug X++ code, we would use the following procedure. In Visual Studio, we would open the X++ code that we want to
debug by right clicking any code element from our project and choosing open. We could then locate a line or lines where
you want execution to stop and set break points in those lines. And in the screen shot, a breakpoint is indicated by this red
dot here and we can simply click in this gray pane on any line, and it will insert a breakpoint at that line in code. We can
also press F9 when the cursor is on a specific line to insert a breakpoint. We would then save the code and right click the
code element again and choose set as startup object, and then we go ahead and press CTRL F5 to build and run the code
with the breakpoint set. On the debug menu, we can click start debugging. It's important that you run the application this
way. Otherwise, the program will not stop at your breakpoints. In the application, perform the action that causes the code
you are interested in to run. Typically, this would be an action like displaying a form. We can use the tools in Visual
Studio to examine the application. For example, we can hover the pointer over certain variables in our X++ code to see
their values. We can also use commands from the debug menu to step through the code. Tools like the autos window in
Visual Studio will show important information about the state of the application. Another tool specific to debugging is
called the Infolog. Frequently, info statements are added to code to log status messages as the application is running.
You can view these Infolog messages directly within Visual Studio as well. We can go to the view menu and choose
Infolog to bring up this Infolog box. After you have finished debugging the application, close Dynamics AX and Visual
Studio will exit debugging mode.

Lesson 12: Best Practices


In this lesson, we'll review some of the best practices to keep in mind when coding. The X++ compiler checks the code
for best practice issues. These issues can result in best practice errors, warnings, or informational messages. Best
practices involve understanding all of the things that you should do and distinguishing them from the things that you can
do. Best practices ensure consistency throughout the code which allows other developers to more easily read and
understand your code. They also make the code more secure and ensure there is no redundant code. Upgrading becomes
easier and quicker and has less risk of errors if best practices are properly followed. Naming conventions contribute to
consistency and to making the application easier to understand. Where possible, application object names should be
constructed hierarchically from three basic components: the business area name, the business area description, and the
action performed for classes or the type of contents for tables. All names shuck in U.S. English, and the default rule is to
use logical and descriptive names if no other specialized rules apply. Identifier names have a limit of 40 characters.
Names in the Application Explorer and X++ code must correspond to the names in the U.S. English user interface.
Names should always be spelled correctly and used consistently. Each path in the AOT must be unique so nodes cannot
have identical names. Do not begin a name with AAA or copy of. And do not begin a name with DEL underscore unless
it's a table, extended data type, or enum that is needed for data upgrade purposes. Placement of code is dependent on the
code you're writing. The preferred procedure in an object-oriented programming language is to place the code in a class
that can be reused and called whenever it's needed. Placing code in classes enables greater control over where the code is
executed. Performance considerations often dictate where code should run, and so having control over this is desirable.
Code placed in forms always runs on the client which may, therefore, cause a lot of client server communication. Always
place the code nearest to the source so it can be more easily manipulated. For instance, code that manipulates a table
should be placed in that table's methods. Best practice is to place as little code as possible on forms. A best practice for
all programming is the use of comments. It is important when developing X++ programs in AX to use comments and
document what the code does and how parameters are used. It's also good to know who made the changes, when and
why. When upgrading code, you need to decide whether to merge code and, if so, how to merge it. Therefore, comments
are very useful to help determine why the code change was made. You can insert comments directly into code lines.
Comments are ignored by the compiler and they turn green in the code editor. To insert a comment, we use two forward
slashes. We also have to-do comments which are indicated by the TO-DO keyword. That's T-O-D-O in all caps. We also
want to make sure our variable declaration are in scope and that the code is placed nearest to the source that we are using.
Finally, header comments are used by using three forward slashes usually at the beginning of a class or method to indicate
a general idea of what's going on within that class.

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.

MODULE 12 KEY TAKE AWAY


o X++ Overview

▪ Code Editor
● Visual Studio Environment

● Uses X++ code

● Benefits of X++ Code and .NET CIL

● CIL runs much faster in most scenarios

o Easier to rewrite application logic in other managed languages

o Dynamics AX assemblies can be consumed directly

o Preferred way of consuming business logic in Dynamics AX externally is by


using services

● CIL can efficiently reference classes that are available in other .NET assembly DLL files

● CIL can be operated on by .NET tools

● Compiler

● Has been rewritten from scratch

● No backward-incompatible changes introduced

● X++ best practice tool has been implemented

● Allows addition of user-defined custom rules

● Standard compilation unit for X++ is same as other .NET languages, i.e. C#.

▪ IntelliSense

● Predictive typing tool of the elements directly from the AOT

● Prompts the user for known methods and possible choices

● Ensures that items are consistently used

● Helps maintain consistent spelling of elements

● Varies with version of Visual Studio

▪ Data Types

● Primitive Data Types

● Anytype

o Placeholder for any data type

● Booleans
o Can only contain the values false and true

● Dates

o Contains day, month and year

● Enums

o Abbreviation for enumerated text – a set of literals

● GUIDs

o Global unique identifier

● Integers

o Number without decimal point.

o Use keyword int

● Reals

o Numbers with decimal point

● Strings

o Number of characters

o Use keyword str

● TimeOfDay

o Contains hours, minutes, and seconds

o Use system type timeOfDay

● Utcdatetime

o Contains year, month, day, hour, minute and second

● Composite Data Types

● Arrays

o List of items with same data type and name

● Containers

o Dynamic list of items containing primitive data types

● Classes as Data Types

o Type definition that describes both variables and methods


● Tables as Data Types

o All tables defined in the data base can be handled as class definitions

● Extended Data Types

● User defined types

● Additional name and properties

● Declaration and syntax to the left

● Benefits of EDTs

● Code is easier to read because variables have meaningful data type

● 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

● Declare in small scopes

● Easier readability

● Is within the block of code that you’re using

● Declare prior to using in executable statement

● Scoped closer to use

● Easier to find

● Var keyword is available to infer the type

● Used for declaration of local variables

● Must be clear for inferred type in initialization

● Assign value to field in line with the declaration

● Reduces code lines

● Improves readability of assignment

▪ Key Operators

● Assignment operators
● =

o Assigns expression right of equal sign to variable on left

● +=

o Assigns variable on left to the current variable value plus expression on the right

● ++

o Increments the variable by one

● -=

o Assigns the variable on left to the current variable value minus expression on the
right

● --

o Decrements the variable by one

● Arithmetic Operators

● <<

o Left Shift: performs expression2 left shift on expression1

● >>

o Right shift: performs expression2 right shift on expression1

● *

o Multiply: multiples expression1 by expression2

● /

o Divide: Dives expression1 by expression2

● DIV

o Integer divison: Performs an integer divison of expression1 by expression2

● MOD

o Integer remainder: Returns remainder of an integer divison of expression1 by


expression2

● ~

o Not: Unary operator. Performs a binary not-operation


● &

o Binary AND: performs binary and-operation

● ^

o Binary XOR: performs binary XOR-operation

● |

o Binary OR: Performs binary or-operation

● +

o Plus: adds expression1 to expression2

● -

o Minus: subtracts expression2 from expression1

● ?

o Ternary operator: Takes three expressions. If expression1 is true, expression2 is


returned; otherwise, expression3 is returned

● Relational Operators

● Like

o Returns true if expression1 is like expression2

● !

o Not

● !=

o Inequality operator (not equal to)

● #

o Prefix on macro names

● &&

o Logical AND.

● ||

o Logical OR

● <
o Less than

● ==

o Returns true if both expressions are equal

● >

o Greater than

● >=

o Greater than or equal

● Order of Operator Precedence

● Unary operators

o –

o ~

o !

● Multiplicative, shift, bitwise AND, bitwise exclusive OR

o *

o /

o %

o DIV

o <<

o >>

o &

o ^

● Additive, bitwise inclusive OR

o +

o –

o |

● Relational, equality

o <
o <=

o ==

o !=

o >

o >=

o Like

o As

o Is

● Logical operators (AND, OR)

o &&

o ||

● Conditional

o ?:

▪ Basic Syntax

● In Visual Studio methods start with one tab

● Everything within method starts at two tabs

● 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

● Only one statement per line

● Break up complex expressions that are more than one line – make it visually clear

● Use a single blank line to separate entities

● Do not use parentheses around the case constants

● Do not use parentheses around where expressions

● 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

● Create an Info log

● Create a dialog button

● Supported Statements and Loops

● If and if…else

● Switch

● While

● Do while

● For

▪ Comparison Tools

● Old code = Original

● New code = Import

● Merged code = Results

▪ Debugger

● Debugging in Dynamics ‘AX 7’ Preview requires Visual Studio.

● Infolog

● Autos window

● Shows important information

▪ Best Practices

● Naming Conventions

● Code Placement

● Comments

● Variable declaration within scope

● Header comments using ///


Module 12: Your Notes
Module 13: Classes
Welcome to Module 13 on classes. In this module, we will review the structure of classes as well as creating and using
classes. The objectives for the classes module are to review the structure of classes, to demonstrate the use of methods
within classes, to create a base class, and then to review the concepts behind class inheritance, to create an inherited class,
and finally, to review the best practices for classes.

Lesson 1: Fleet Management Scenario


In this lesson, we will review how we're going to use classes for our fleet management scenario. For the fleet
management scenario, we're going to create a class to insert vehicles in a quick entry process. In addition, we're going to
create a class that extends the base class and allows for the quick entry of trucks.

Lesson 2: Class Structure


In this lesson, we're going to review the basic structure of a class. A class is a software construct that defines the data and
methods or behavior of the specific concrete objects that are subsequently constructed from that class. It can be thought
as a blueprint or a set of instructions for different instances of an object. It is possible for multiple instances of the object
to exist and for each instance to hold different values in its variables and, therefore, to run differently. Instance methods
are embedded in each object that is created from the class and can perform some type of action such as a calculation and
then returning a value. Methods can be seen as a work order on these set of instructions. They help construct the house
from the blueprint which is the class. We then have usable code. Variables are the data for the class. Variables and X++
classes are specific to an object. That is, every object constructed from the class declaration has its own copy of the
variable. Such variables are known as instance variables.

Lesson 3: Create a Base Class


In this lesson, we're going to create a base class which can then be inherited by another class. In the last module, we
created a runnable class. And the runnable class, by default, includes this public static void main method for us where we
can put some code and run it. In this demonstration, we're going to create a normal class. And we're going to use this
class as a base class that can then be extended further as we develop our fleet management system. So to add a normal
class, we simply right click our project from the Solution Explorer. And we choose add and then we choose new item.
From the code element type, we have four options. Before we chose this runnable class, now we simply will choose the
class element. And we'll call this dbfmVehicleEntry. And then we can choose add. And now, we have a blank class. We
have a class name and then our brackets where we can begin adding different code and methods.

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.

Lesson 5: Class Inheritance


In this lesson, we will review how class inheritance works. Inheritance is a concept where one class can inherit all of the
methods and variables from another class. A child class inherits the methods of the parent class. Additional methods can
be applied to the child class, and inherited methods can be overridden, this means that the child class is not always
identical to the parent class. The advantage of inheritance in object-oriented programming is that code can be written one
time and then reused many times. To have a class inherit from another class, we modify the class declaration code of the
child class by appending the extends keyword and then the name of the parent class. So we can have something like class,
child class name extends parent class name. Objects created from the child have the same methods and variables as the
parent. Objects created from the child may have methods and variables that do not exist in the parent. And finally,
objects created from the child may have methods from the parent that are overridden or altered in some way within the
child class. Let's take a look at an example of class inheritance. Suppose we have a parent class called InventType. And
suppose we have a child class called InventTypeCustom. This parent class is what's known as the base class and the child
class would be inheriting from or extending that base class. Suppose we also have three methods within our parent class
called InventType. They are canInventBeReserved, palletTagging, and doScrap. Now, we can have two of these three
methods for example inherited from the parent class. That would be doScrap and palletTagging. We can also have them
overridden which means they inherit those methods but they somehow alter them in some particular way. Then the child
class can also have its own methods outside of the parent class. So in this example, we're inheriting the doScrap method
and the palletTagging method from our parent class InventType. And then the child class has this updateTruckList
method which is specific to the child class in some way. So I've created a new class now that we're going to use to
demonstrate the concept of class inheritance. Now, in the last example, we walked through this dbfmVehicleEntry class.
And let's recap real quick what this class did. It created this dialog box with three dialog fields that took in the user's input
for a vehicle's make, model, and VIN number. It then inserted those values into the vehicle table which we then saw on
our VehicleListPage form. This dbfmTruck VehicleEntry class is going to extend the functionality of the VehicleEntry
class. And we do that by using this extends keyword. So we have class, our class name, the keyword extends, and then
the class name that this class extends. So what we're going to do is borrow some functionality from that
dbfmVehicleEntry class. This TruckEntry class takes in some more dialog fields such as a FromNote, a FromNOD and a
FromGVR. And these fields represent different values in the table which are the note field in our vehicle table, the
number of doors in our vehicle table, and the gross vehicle weight in our vehicle table. And we're just calling them
dialogFromNOD, dialogFromGVR as a shorthand way to reference them. Now, again, this class is going to instantiate an
instance of itself here saying new dbfmVehicleEntry and then we call the truck VehicleEntry.run method. And it's going
to walk through the same process as the class we saw on the last example by creating our setupDialog and creating our
getFromDialog and getting the values from the user.
Now, you'll notice here in our setupDialog method, we have this other piece of code called super. And what the super
does is it goes out to the parent class or the class being extended, which is the VehicleEntry class, and it calls the code
from the same method name. So we have a method in our TruckEntry class here called setupDialog. That same exact
method with the same exact name exists right here in our parent class, the VehicleEntry class. And what the super does is
goes ahead and executes this code here in the parent class and then it executes the code we have here in our child class,
the TruckEntry class. So what it's doing is saving us from having to type out all those other dialog fields because we're
going to use the make, model, and VIN number fields from our VehicleEntry dialog on our TruckEntry dialog as well, and
there's no reason for us to specify all this code again to reinstantiate these dialog fields because we've already coded them
in this class. So we call the super to get those dialogs, and then when we create our three new dialog fields that are
specific to our TruckEntry form, which are the number of doors, the gross vehicle weight, and this note field. And again,
when we do the getFromDialog, we're creating three strings. We're setting these strings equal to the value that's retrieved
from those respective dialog fields. And then, we're setting those to our vehicle table buffer variable so that that's now
stored in the table, and then we go back and call our insert method again. So the logic and the flow is the same as our
entry class, our VehicleEntry parent class, expect for we're calling the super to borrow some of those dialog fields here
instead of recoding them. Again, we call the super down here in this getFromDialog method. Now, you notice again in
our VehicleEntry parent class, we do have a method called getFromDialog. The getFromDialog method here is retrieving
the values for the make, model, and VIN number. So again, we're borrowing that code. We're saying, hey, go out there
and get the values for the make, model, and VIN number from our parent class as well as the values here for our note, our
number of doors and gross vehicle weight field. So let's go ahead and run this class to see how it works with the concept
of inheriting from our DB VehicleEntry parent class. OK. So I'm going to use the shortcut key of CTRL ALT L to open
up my Solution Explorer window. And I'll go ahead and right click this TruckVehicleEntry class and set it as my startup
object. I can then press CTRL F5 to go ahead and build and run this class and see what the dialog window is going to
look like. So I'll go ahead and do that. All right. Our build has completed. We're getting a notification here from our
class runner window. I'll open it up and now we can see that we have this new quick entry dialog form. So we ran our
TruckVehicleEntry class, and that only had dialog fields for note, number of doors, and gross vehicle weight. However,
using the concept of class inheritance, we extended our VehicleEntry form which included these three dialogs for make,
model, and VIN number, and now, we have a new dialog window that encompasses all six of those fields without having
to rewrite a ton of code. And this is really the concept behind inheritance, to save us from rewriting code and extending
functionality of preexisting classes. So we can go ahead here and real quick, we'll type in another model, a make, and
we'll go ahead and just visualize how this is entered into our VehicleListPage form. All right. So I'll make up some
values and press OK. It's notifying me that that accepted my input. So I can go back to my VehicleListPage here. And
I'll press refresh. And now we can see that new line of Toyota Prius with a gross vehicle weight of 5,000 is entered here
on my VehicleListPage.

Lesson 6: Best Practices


In this lesson, we're going to review the best practices for classes. Some best practices to consider when using classes
include to have only one successful return point in the code which is typically the last statement with the exception of
switch cases or when checking for start conditions. We should keep our building blocks or methods small and clear. A
method should do a single well-defined job and, therefore, should be easy to name. You should put braces around every
block of statements, even if there is only one statement in that block. You should also put comments in your code which
tells others what the code is supposed to do and what the parameters are used for. Do not assign values to or manipulate
actual parameters that are supplied by value. You should always be able to trust that the value of such parameter is the
one initially supplied. You should treat such parameters as constants as well. And finally, you should clean up your code,
delete any unused variables, methods, or classes, to keep everything precise and correct. An important best practice for
variable and method declaration is to declare them as locally as possible. We have three different types of scopes that we
can use for methods and variables. The first one is what's called public. We can declare variables and methods for safe
reuse by making them public. It's important to ensure that they are explicitly declared and that there is no ambiguity as to
the intention of the programmer. The public methods can be accessed by other classes and methods. The private keyword
or scope is used to declare variables and methods as private. This means it keeps the context of the variables local or
within the scope of that particular method only. This prevents accidental misuse or unintentional variable reuse from
outside classes or methods. And finally, we have the keyword protected. This is a blend of the public and private scopes
and protected means to keep the variables public only for the subclasses that may extend or overlay. Yet it restricts access
to outside objects calls. This means a method with the protected keyword can be accessed by subclasses or child classes
that are used in an inheritance structure.

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.

MODULE 13 KEY TAKE AWAY


o Classes

▪ Class Structure

● Class Construct

● Blue print

● Defines construction of building

● Instance method

● Work order

● Constructs the house

● Useable code

● Can use the house

● When done, it goes away

▪ Methods

● Class declaration

● Specifies name of class and necessary variable

● Can specify inheritance

● Instance methods

● Objective methods

● Embedded in each object created from class


● Must instantiate object before using method

● Static methods

● Class methods

● Belong to class and created by keyword static

● Do not need to instantiate object before using

● Used to work with data stored in tables

● Main methods

● Class method that’s executed directly from menu option

● Should only create instance of object

● Calls necessary member methods

● _args parameter allows data transfer to method

▪ 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

● Only one successful return point in code

● Keep building blocks (methods) small and clear

● Put braces around every block of statements

o Even if just one statement

● Put comments in code

● Do not assign values to, or manipulate, actual parameters supplied by value

● Clean up code

o Delete unused variables, methods, classes

● Variable and Method Declaration

● Protected

● Private
● Public

Module 13: Your Notes


Module 14: Database Manipulation
Welcome to Module 14 on database manipulation. In this module, we'll cover how to use X++ code statements to
manipulate data in the database. The objectives for this module are to review the data retrieval process, to demonstrate
best practices to use when updating data, to explain the transaction integrity system, and finally, to review how to update
and delete data.

Lesson 1: Fleet Management Scenario


In this lesson, we'll review our fleet management scenario for database manipulation. Data manipulation in Dynamics AX
empowers the developer with the tools to view, insert, update and delete data from the database. For our fleet
management system, all of these factors need to occur. For example, we might need to retrieve data about our current
customers. We might need to insert a new customer or we may have to update an existing customer's details.

Lesson 2: Data Retrieval


In this lesson, we'll review the data retrieval process for viewing information from the database. Returning data for view
is a common feature. We can also use this for comparison. We will need to read records in from the database. Single
calls can be possible for uniquely indexed tables. And more effective searches iterate over the whole table to ensure no
item is missed. The select statement fetches or manipulates data from the database, or both fetches and manipulates data
from the database. All select statements use a table variable to fetch records. This variable must be declared before a
select statement can be executed. The select statement only fetches one record or field at a time. To fetch additional
records, you can use the next statement. The next statement fetches the next record in the table. If you use next without a
preceding select command, an error will occur. You should not use next with the first only find option. If you need to
traverse a number of records, it's more appropriate to use the while select statement. The results of a select statement are
returned in a table buffer variable. If you use a field list in the select statement, only those fields are available in the table
variable. If you use an aggregate function on a particular field in a select statement such as a sum or count, the results are
returned in the field that you perform the sum or count over. You can only count, average, or sum the integer in real
fields. Using the following table, we can see that there are many options available for using the select statement to
retrieve data. We can specify different find options such as find the first record only in a table or the first ten or the first
100 or even 1,000. We also have the option to select an individual field from a table, a list of particular fields, or all fields
which would be represented by the asterisk so we can have something like select asterisk from cust table to retrieve all of
the records in the cust table. We then have aggregate functions that we can use such as sum, average, the min of, max of,
and count. And we would say something like select sum and then in parentheses, we would have the name of the field we
want to sum directly next to that. For example, we could have select sum and then the field amount in parentheses from a
particular table.

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.

Lesson 3: Reading Records


In this demonstration, we're going to look at how to view records within a particular table or set of tables. So to do this,
we use a select statement, a query to go specify which data we want and how we want to view it.
Now, here, I have this BulkVehicle class which is doing a bit of the same thing as our VehicleEntry class at the
beginning here. We're declaring two tables to use. That's our vehicle table and our vehicle maint table, which is the
vehicle maintenance table, and we have our main method that's creating a new instance of our class, and we're calling it
BulkVehicle. And then we call the run method on our class which is right below it here. And our run method is going to
perform these different types of data manipulation. In this example, we're using the this.viewRecords, so we're calling it
the viewRecords method, which is right here. And we'll go through this method piece by piece. We also have the
insertRecords, updateRecords, and deleteRecords methods, which are further down in my code here. And we'll look at
those later on. But currently, these are commented out. You can see the text is green and we have these two forward
slashes. This indicates that the compiler is going to ignore these pieces of code. They're simply there for us to kind of flip
around on. So I can go ahead and put two slashes here to comment out the viewRecords method, remove these, and now I
can run it with the insertRecords method. OK. So let's go ahead and use our viewRecords method to retrieve some data
from our vehicle tables. Now, if we step down here to our viewRecords method, what we're doing is using a while select
statement on the vehicle maintenance table and we're joining in our vehicle table where the vehicle IDs in each table are
equal. So again, we're going through the vehicle maintenance table line by line. This is an iteration over this table where
this condition is met. And for each line where we have a matching vehicle ID in both tables, we're going to output an info
message that contains the vehicle ID followed by a comma and the vehicle make. OK. So let's go ahead and run this and
see how it outputs in our class runner. Now, before we run a project, again, we have to make sure that the class we are
running is set as our startup object. A quick way to determine that is to look over here in the Solution Explorer in our
project and we can see this dbfmBulkVehicle class is in bold. That's an indication that it is the current startup object.
And again, we can right click any object and choose set and startup object. So for now, we're good to go. I'll go ahead
and press CTRL S to do a save and ensure there are no syntax or logic errors in my code. So we're looking good. I'll go
ahead and build and run this by using the CTRL F5 shortcut key. And then we should be able to verify the output. OK.
So our build has completed here. We'll go ahead and open our class runner window to verify the Infolog message output.
And we can see here on the right we have two records. I'll use my drop down arrow and I have the vehicle ID of one with
the make Toyota and the vehicle ID of five with the make Dodge. Now, those are the only two records that exist in both
those tables with the same vehicle ID. So our statement worked. That's how we can go retrieve some data for output
really quickly. If I go over here to my VehicleListPage form, you can see that I kind of have this different demo data and
I have a vehicle ID of one here which is my Toyota and the vehicle ID of five is my Dodge. Now, if I click the vehicle
maintenance button up here from the top, that's going to launch my vehicle maintenance form that I have created. And we
can see in here that we'll only have two records. The one with the vehicle ID of one and the next maintenance record with
the vehicle ID of five. That's why we only received those two results in our output.

Lesson 4: Transaction Integrity Checking


In this lesson, we'll review the process for how AX performs transaction integrity checking. The transaction integrity
checking process is performed by the transaction tracking system which is commonly abbreviated as TTS. It's important
to ensure the integrity of all transactions within the system. When a transaction begins, we need to ensure data
consistency. It must finish completely with predictable results. If the transaction terminates in the middle, the system
should roll back to its state before the transaction began. Using the transaction tracking system, we have three main
keywords that we use to perform integrity checking. The first one is ttsbegin. This indicates the beginning of a
transaction. For example, if we're going to begin inserting records or updating records in a table, we want to have the
ttsbegin keyword before we begin that process. The ttscommit keyword indicates the successful end of a transaction.
This ensures the transaction finished and performed as intended. If anything occurs between the ttsbegin and commit, for
example, a particular record in a while loop did not insert correctly, the ttscommit will never be reached and, therefore,
nothing will ever be inserted into the database. It rolls back to the state before the ttsbegin. And the third keyword
associated with the transaction tracking system is called ttsabort. It's used as an exception to abort and roll back the
transaction to the state before the ttsbegin. Nested ttsbegin and ttscommit statements are ignored in the sense that the
database lock is held until the very last ttscommit is reached. However, the system does keep track of a TTS level. So
each time a ttsbegin is called, the TTS level in the background increases by one. And every time a ttscommit is reached, it
decreases this TTS level by one.

Lesson 5: Data Insert


In this lesson, we'll review the process for inserting data. When performing data inserts, only the specified columns of
those rows selected by the query are inserted into the named table. That means you want to make sure your query is
selecting the fields that you're going to end up inserting into your table. Secondly, the columns of the table being copied
from and those of the table being copied to must be of type compatible. For example, if we're inserting data into a field
that stores some type of decimal number like fuel tank capacity, we need to ensure that the table buffer variable is of the
same data type, which would be the data type of real in this case. Let's consider the following snippet of code. This is a
sample insert statement. At the very beginning, we are initializing a table buffer variable. We have a system table called
InventItemPriceToleranceGroup. And we're going to be using the InventItemPriceToleranceGroup here as our table
buffer variable. Then we're going to begin assigning data to certain fields in this table and then inserting it into the actual
table. Now, the first thing we do again is use our ttsbegin keyword. And then we can begin the process of inserting data
into this table. So we have a field here called itempricetolerancegroupid and we're explicitly assigning this field a value
of four percent. We then have a name field on this table and we're explicitly assigning that to the value of
TelevisionSeriesOne. And then we go ahead and call our insert command. This calls the insert method on the
InventItemPriceToleranceGroup table and inserts these two records. Likewise, in the second paragraph, we're also
assigning or inserting two new records. The itempricetolerancegroupid is going to be assigned a value of six percent and
the name is going to be assigned TelevisionSeriesTwo. And then again, we call our insert method at our table and finally,
our ttscommit keyword. This ensures that there were no problems during these inserts, that the fields are type compatible
and everything goes smoothly. Then the ttscommit is called and the data is inserted into the table. And finally, once our
ttscommit is reached, we create an Infolog output here with the words Yahoo to indicate a success transaction. So let's
review this sample insert statement. This is the same snippet of code we just reviewed in the slide. And here we have
again a runnable class. We have our static main method and then some code here that we want to test. And remember,
we have to set this class as a startup object for our project so that when we build and run it, it executes this class here.
And you can do that by right clicking the class and choosing set as startup object. So I've had this runnable class set as
my startup object for all of the demonstrations so far. Now, when he consider this code snippet, again, what we're doing
is inserting data into this InventItemPriceToleranceGroup table and we're inserting two records. So each time we call this
insert method here, it inserts a line or a row into the table. The first record is going to be this with the four percent
TelevisionSeriesOne set to the inventpricetolerancegroupid and name fields respectively and then we have six percent in
TelevisionSeriesTwo for the second record. Now, again, we are creating this table buffer variable based on the
InventItemPriceToleranceGroup table and we're assigning these variables, these fields different values in our code. We
have our ttsbegin and commit to ensure the integrity of the transaction, and then finally we're going to display an Infolog
message of Yahoo after the ttscommit has been reached to indicate that the inserts were completed. We can also verify
that on the InventItemPriceToleranceGroup form. So if I navigate to the AX client here in my Internet Explorer browser,
I'm open on the itempricetolerancegroup's form. And we can see this form has no records. There's no data yet for this
grid which is based on the underlying table that we're about to insertRecords into. So we can go ahead and run our project
and verify that we see records inserted here on this form and we get that Yahoo output message. So let's go ahead and do
that. I have the code snippet here. I'll press CTRL S to save and verify there are no syntax issues. And finally, I'll go
ahead and do a build and run by pressing CTRL F5. So our build has completed here. I'm getting a notification window
from the class runner. So I'll open it up here. And we can see we have the info message Yahoo displayed, which means
our data was indeed inserted into the table. So let's go check the table now. Or the form rather, which is based on the
table. So I'll go ahead and refresh this form. And we should expect to see those two records in the form now. And there
they are. The four percent with TelevisionSeriesOne as the name and six percent with TelevisionSeriesTwo as the name.
In this demonstration, we're going to insert records into our vehicle tables for our fleet management system. In the last
demonstration, we called this viewRecords method to retrieve and output some information, some records from our
vehicle maintenance and vehicle tables. And we did that using a while select statement and a join statement and then our
Infolog output. So now, what we're going to do is comment out this call to the viewRecords method by using two forward
slashes, then I'll uncomment, so I'll remove these forward slashes from the call to the insertRecords method. And the
insertRecords method is right here. And again, we're wrapping all of this insertion and data assignment in our ttsbegin
and commit. So in the first block of code here, we're simply assigning different values for these variables in our table.
For example, the vehicle ID, we're making a call to a method called getLastVehicleID within this class and then we're
incrementing that by one. So it's kind of a way to keep our vehicle IDs incrementing and adding as we call this insert
method. So let's go to the getLastVehicleID method so we can see what's going on there. And the getLastVehicleID is
here. It's a private method and it returns a dbVehicleID value. You'll notice the other methods have this void keyword
which means they do not return a value. So the getLastVehicleID, what it's doing, it's saying return, and then in
parentheses, we're creating a query. We're saying select max of, and then the field name we want, dbVehicleID from the
table we want, which is dbVehicle, and then we specify the field name .vehicleID. So what we're doing is we're returning
the maximum value of the vehicle ID which would be the highest one. So I believe now we have a vehicle ID of six, for
example. So when we go here and assign a new value to the vehicle ID during this insert process, it's going to increment
the most recent or highest vehicle ID value by one so that we don't have any duplicate entries. OK. Then we continue to
assign different values for these variables. We're just assigning .75 for our fuel level because that data type is a real -- it's
a decimal data type. We need to make sure we're adhering to those. Our year is a data field so we're using this make date
function, which is the MK date and then parenthesis, and we're specifying the month, day, and year. And that's a way to
make a date field. Then we continue to just type in some string tags for these make and models. We're going to use
Toyota Corolla for an example. And we're kind of just fabricating some numbers here and some inspection dates just to
populate these fields. So once we have all the fields we want, we call the insert method on our table buffer, FMVehicle,
which is linked to the actual dbVehicle table. And then again, we do some more insertions. We kind of repeat those same
steps with some different values, and then we call the insert again. And remember, each time we call the insert method on
a table, it's inserting a new line or a new record. And then we do one more block of code for a third record and call our
insert method once more followed by the ttscommit and then an Infolog to display that the insertion of records has
completed. So when I go ahead and run this code, we should expect to see three new records in our VehicleListPage
which is based on our vehicle table that we're updating. And we should see a Toyota Corolla, a Ford Explorer, and a
Dodge Charger. So let's go ahead and build and run this. And again, we're calling the insertRecords method now so we're
going to observe this process. I'll press CTRL F5 to build and run. And once the build completes, we can verify the
results. OK. Our build has completed. We'll go ahead here and open up my class runner window. And we'll see we have
our output insertRecords complete. That means the code completed successfully. So let's see if we can verify those in our
list page here on our VehicleListPage form. I'll go ahead and refresh this. And we should expect to see those three
records inserted into the table. All right. And here we are. We have our incremented vehicle ID so that the highest one
before in this table was five. So you can see that getLastVehicleID method incrementing the value by one assigned it to 6,
7, and 8 respectively. We have our make and model, Toyota Corolla, Ford Explorer, and Dodge Charger. So those values
all inserted properly into our table as we expected.

Lesson 6: Data Updates


In this lesson, we will review how to update data. The update command modifies existing data in a table with the contents
of a table buffer. The record is first retrieved from the database using a select statement. The data is then modified by
assigning the new values to the fields in the table buffer. The new values are then committed to the database using the
update method. Before records can be updated, use the select for update keyword to exclusively set a record for update.
This tells SQL that the record is to be updated and allows the database to lock the record so that another user cannot
modify it at the same time. Let's consider the following code snippet that demonstrates a sample update statement. In this
code, we have two tables. The inventTable and the inventItemGroupItem table. We're performing a while select for
update command over the inventTable which means we're going through row by row and selecting certain rows for
update. We then perform an exist join between the inventItemGroupItem table and the inventTable where the ItemID
fields in both tables are equivalent. We're then using our and operator to specify an additional where condition where our
ItemGroupID in the inventItemGroupItem table is explicitly equal to TV and video. So we're performing this update for
the records in the inventTable that match these where conditions. So we're only iterating over the rows where this join
exists and where the ItemGroupID is equal to TV and video. Once we enter the loop here within our brackets, this is the
code we're executing onto each record that meets our criteria. We're setting the itempricetolerancegroupid to seven
percent in the inventTable and then we're saying to call the update method, which will then update our inventTable.
Finally, we display a this works message from our Infolog and then we go ahead and use our ttscommit to ensure the
integrity of the transaction and that everything went smoothly during the update process. In this demonstration, we're
going to look at how to update records that already exist in our vehicle table. Again, we're here in our class called the
BulkVehicle class where we're updating and manipulating data. We have a run method that calls out to viewRecords
method and insertRecords method as well as an updateRecords and deleteRecords method. So we've already seen
examples of how the viewRecords method works with retrieving data, and then we just looked at the process for inserting
records in our insertRecords method. So now, we're going to comment out that call to the insertRecord method and
uncomment out this call to our updateRecords method. The updateRecords method is down here in our code. And what
this method is doing is calling a while select for update on the vehicle table. And we're specifying a condition where the
vehicle ID in that table is equal to six. Then we go in our brackets here inside of our loop and we're saying set the model
to Camry, and then we call the update method on the vehicle table. So it's going to go through line by line the vehicle
table, and any line that has a vehicle ID of six, the model for that line will be changed to Camry. Now, we should only
have one record with a vehicle ID of six since that's our unique kind of numbering system for our fleet management
system of vehicles. Now, I'll go into my VehicleListPage real quick and we can verify that this record here with the
vehicle ID of six is currently a Toyota Corolla. So what our code is saying is to update this model, this Corolla field, and
change it to Camry now. OK. So we'll go ahead and run this and then we should observe that change. We should also
get an Infolog message that says updateRecords complete so that we know everything went through and our ttscommit
was performed successfully. So I'll go ahead and press CTRL S to save this. And then I'll use the CTRL F5 shortcut key
to build and run the project. We can now verify that our build has completed. And we'll go ahead and check out our class
runner window. And we can see the output update records complete so everything should have gone through
successfully. Now we'll switch over to our VehicleListPage form, and we'll go ahead and do a refresh to see if that
Corolla value will indeed change to Camry. And there it is. So our vehicle ID of six. The Toyota Corolla is now a
Toyota Camry. So that's a quick overview of how the update method works. We can specify conditions on a certain field
and then update another field. We can also update multiple fields at once, just like when we insertRecords, we can insert
into multiple fields with one insert call.

Lesson 7: Data Deletion


In this lesson, we will cover data deletion using X++ code. The last piece of data manipulation we're going to discuss is
the delete method. The delete method in a table can quickly delete one record, dozens, or even millions of records. It's
very important to test this procedure in a non-production database with a small amount of data to ensure the results are
what you expect. Using the delete method on a table will delete the current record from the database. However, if we use
a WhereClause, we can specify multiple rows to be deleted that meet our conditions. Records are then removed one at a
time from the specified table. The delete method can also be overridden. For example, we can add extra validation before
records are deleted from the table. Let's take a look at a sample delete statement. This code snippet is similar to what we
saw in our sample update statement. We have these two tables, the inventTable and the inventItemGroupItem table. And
we're performing a while select for update on the inventTable. We're then performing an exist join between the invent
item group item table and the inventTable. And that exist join is being performed where the ItemIDs are equivalent. And
then we're using our and operator to specify an additional piece of criteria, and that is where the ItemGroupID field is TV
and video within the inventItemGroupItem table. So what we're doing is we're going through line by line the inventTable
and we're saying where this criteria is met, where there is a record in the inventTable that relates to a record in the invent
item group item table, that has an ItemGroupID of TV and video, we're going to delete all the instances of those records
one by one using this while loop. So we're calling the delete method on the inventTable for all of these records that meet
our criteria in our where statements. And finally, we're calling the Infolog to display a message that says this works as a
confirmation and ultimately using our ttscommit to ensure that everything went well. In this demonstration, we're going
to delete some records from our vehicle table. And again, we have this run method and it's making calls to different
methods that either update, insert, delete, or allow us to view and retrieve records. Now, we've seen examples of these
first three here. So now we're going to focus on calling the deleteRecords method. So I've commented out the other three
so that we only execute the deleteRecords method. And we'll scroll down here and take a look at the code. Now, on the
deleteRecords method, we're calling a while select statement for update on the vehicle table. And then we're specifying a
condition where the vehicle ID is equal to zero. Now, again, typically our vehicle ID field is going to be a unique kind of
numbering system so this would only delete one record. However, let's go check out our VehicleListPage and see what
data we have in that data right now. Now, you can see I have all this kind of demo data I had keyed in and they all have a
vehicle ID of zero. So I'm going to specify that in my where clause so I can kind of clean up this table a bit with all these
anomalies and I'll just leave my vehicle IDs of 1, 4, 5, 6, 7 and 8. So let's go ahead and try to execute that code. So what
we're going to do now is call the delete method on our vehicle table for all the records that have a vehicle ID of zero. And
finally, we're going to display this delete records complete in our Infolog output to confirm that the code has run
successfully. So again, I'm going to press CTRL S to save and ensure there are no errors in the code. And then I'll kick
off a build and run the project by pressing CTRL F5. So our build has completed. I'll go ahead and open up my class
runner window in AX. And we'll verify our info message has been outputted that says deleteRecords complete. So I'll
flip over to my VehicleListPage and I'll go ahead and refresh this and we should expect to see all these records with a
vehicle ID of zero disappear. And there we are. So all those records are gone and now my form and my table here are
looking nice and clean.

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.

MODULE 14 KEY TAKE AWAY


o Database Manipulation

▪ Database Retrieval

● Returning data for view is a common feature

● You will need to read records from the database

● Single calls can be possible for unique index tables

● More effective searches iterate a whole table to ensure no item is missed

● Select statement

● Using the select statement

● Using a table variable with a select statement

● Fetching additional records with the “next” and “while select” statements

● Results of select statement are returned in a table buffer variable

● While Select Statement

● 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

▪ Transaction Integrity Checking


● Ttsbegin

● Indicates beginning of transaction

● Ttscommit

● Indicates successful end of transaction.

● Ensures transaction is performed as intended upon completion

● 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

● New values are then committed to database using update() method

● Before records can be updated, use “select forUpdate” to exclusively set record for update

▪ Data Deletion

● Deletes current record from database

● Use this method, specify which rows are to be deleted by using a where clause.

● Records are then removed one at a time from specified table

● 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.

Lesson 1: Fleet Management Scenario


In this lesson, we will review the fleet management scenario for exception handling. For the fleet management scenario,
we're going to explore error handling. In a previous example, we built the VehicleEntry class, which took user input
values from dialog fields and quickly inserted that data into our vehicle table. Now, we have created a copy of this class
and added a try/catch statement for validation. When the user keys in a value, we would like to verify that they have the
correct vehicle identification number or VIN. VINs are 17 digits in length and our company using 18 digits with a special
check digit to ensure that we have the correct vehicle type.

Lesson 2: Exception Types


During this lesson, we will discuss the different exception types in AX. There are many different exception types, and the
type differs depending on what caused the error. A majority of exception types are determined by the kernel and are not
normally thrown by application code. All exception types, however, can be caught, and it is the developer's responsibility
to decide which exceptions need to be handled. The exception type is identified using the system-based enumeration
called exception. Because it is a system enum, it cannot be modified and users cannot add new exception types. The first
exception type we're going to discuss is called info. And this displays informational exceptions. For example, a record
has been updated. The warning exception type indicates the user has performed an illegal but non-fatal operation.
Deadlock informs the user that the system encountered a deadlock situation in the database. The error exception type
indicates a fatal error has occurred and the transaction has been stopped. Internal displays Microsoft AX internal
development errors. The break indicates that the user has pressed the break button or shortcut key. A dderror exception
indicates that an error occurred in the DDKernel class. The numeric exception type indicates that some error has occurred
during the conversion of converting a string to integer, string to integer 64, or string to numeric functions. The CLRError
indicates that an error has occurred during the use of a CLR functionality. The CodeAccessSecurity exception type
indicates that an error has occurred during the use of CodeAccessPermission.demand. The UpdateConflict exception type
indicates that an error has occurred in a transaction using optimistic concurrency control and that the transaction will be
retried. The UpdateConflictNotRecovered exception type indicates that an error has occurred in a transaction using
optimistic concurrency control and that the code will not be retried.
Lesson 3: Key Commands
Let's review some of the key commands in X++ that we will use with exception handling. We're going to discuss four
main key commands that are used in code to use with exception handling. The first one is called a try statement . The try
command signifies the start of a block of code that you want to control with the X++ exception handling system. Any
exceptions that are thrown in that block of code can be caught and handled accordingly. The block of code inside the try
statement must be contained between brackets. Catch statements come after the block of code and define what code is
executed when each exception is thrown. You do not have to define a catch statement for every possible exception.
However, each try statement must have at least one catch statement. A retry command tells the system to go back to the
try statement and attempt to execute the code again. Any data that was loaded before the try command will remain as it
was but any data retrieved or modified after the try statement will be refreshed. When a deadlock exception is thrown, all
locks on tables that this process holds are released which may allow the other process or processes that are also
deadlocked to continue. By calling it a retry, the process can attempt to update the record again and may now be able to
complete. It's a best practice that a retry uses a counter so that the number of retries can be controlled and a user does not
become stuck in a loop. Lastly, we have the finally keyword. This is used to follow the try and catch keywords. The
semantics are identical to its use in C#. The statements provided in the finally clause are executed irrespective of whether
the try block threw any exceptions or not.

Lesson 4: Code Statements


In this lesson, we will review some sample code statements that use exception handling. Let's consider this following
code sample for exception handling.
The current code snippet spans three different slides so we'll walk through each slide and discuss each piece of the code.
Now, here in the first slide, we have a class called custCreateCustomer. Then we have a static main method. Inside this
main method, we are instantiating a new instance of our class calling it custCreateCustomer using our new keyword. And
then we're calling the run method on our custCreateCustomer class. The run method is on the next slide here.

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

● Displays informational exceptions

● Warning

● Indicates user has performed and illegal, yet nonfatal operation

● Deadlock

● Informs user that the system encountered a deadlock situation the database

● Error

● Indicates fatal error has occurred and transaction has stopped

● Numeric

● Indicates an error has occurred during the use of str2int, str2int64 or str2num functions

● Dderror

● Indicates an error accured in the DDkernal class

● Break

● Indicates user has pressed Break.

● Internal

● Displays AX internal development errors

● CLRError

● Indicates error has occurred during use of CLR functionality

● CodeAccessSecurity

● Indicates error has occurred during use of CodeAccessPermision.demand

● UpdateConflict

● Indicates error has occurred in transaction in a transaction using Optimistic Concurrency


Control, and that the transaction will be retired

● UpdateConflictNotRecovered
● Indicates error has occurred in a transaction using Optimistic Concurrency control, and
that the code will not be retired

▪ Key Commands

● Try

● Signifies start of block of code

● Catch

● Come after block of code

● Define what code is executed when exception is thrown

● Retry

● Tells system to go back to Try statement and reattempt

● Finally

● Follows try and catch keywords


MODULE 15: YOUR NOTES
Module 16: Security Basics
Welcome to the security basics module. In this module, we will look at the architecture for security and review some
security elements and properties. The objectives for the security module are to review the security architecture, to explain
role-based security, to describe security elements in the development environment, to modify and create security in the
development environment, and to describe the extensible data security framework and how to use XDS policies.

Lesson 1: Security Architecture Overview


Let's begin by reviewing security architecture. Let's see how authentication for the user interface works.

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.

Lesson 2: Create a Role


Roles can be created by a developer in Visual Studio or by a system administrator in the AX client. In this course, we're
going to focus on the process for a developer to create a new role from Visual Studio. In this demonstration, we'll look at
creating a security role to add to our development basics fleet management scenario project. And to do that, we'll right
click our project and we'll choose add and new item. In the left pane under AX artifacts, there's a security group. And
this contains the different elements related to security. So we'll choose security role and we'll give this new role a name
such as DBDataEntryClerk and choose add. A new folder will be created in our project for this new element type of
security role and you'll notice in the designer, we have this role opened. And we have four different sub-nodes here
within our role. We can add privileges, duties, permissions, as well as sub-roles within this role. In this example, we're
going to add a privilege as well as a duty. To add those, we simply click the node we wish to add, and we right click and
choose new. So I'm going to right click privilege and choose new privilege. And in the properties pane, there's a property
called name. And from here, we can use a drop down to select from the list of populated privileges in the system. We can
also go ahead and key it in. Since there can be a few in that list, I'll go ahead and just type one in. This privilege is going
to be called sysDataAreaMaintain. And that is a privilege that exists in the system. And I'll repeat a similar process to
add a duty. This time I'll right click the duties node and choose new duty. And for the name property, I'll specify the
name of my duty. This one I'm going to call data management maintain. And I'll press enter. And now we have created
this new role. We've added a privilege and a duty and we specified which system, duty, and privilege we want to be
associated with those. So I'll go ahead and save this object. And now we're ready to begin using our role.

Lesson 3: Create a Duty


Just like roles, a duty can be created both in the UI by a system administrator and in the development environment by a
developer. In this course, we'll walk through the process for creating a duty in the development environment. In the
previous demonstration, we created the DBDataEntryClerk role in our development basics fleet management scenario
project. We then added a privilege to this role and a duty to this role. In this demonstration, we're going to create a new
duty and we'll assign a privilege to that duty and then ultimately we will add our newly created duty to our
DBDataEntryClerk role right here. So to add a new duty, we right click our project, we'll go to add and new item, and
from the security artifacts group, we'll choose security duty. We'll go ahead and call this dbVehicleDuty. And we'll
choose add. And again, it's going to create this new folder for the duties and it will open up in our element designer. And
we can see the dbVehicleDuty only has one node and that is the privileges node. So we can go ahead and right click this
and choose new privilege. And then in the name property, I'll specify value. It's InventADJInventonHand. And this
relates to a system privilege that is to approve purchase orders. So once I have assigned this privilege to my
dbVehicleDuty, I will go ahead and save. Then I'll flip over to my DBDataEntryClerk role, and I will add my new
dbVehicleDuty to this role. So again, so again, on my DB data clerk entry role, I'll right click the duties node and choose
new duty. And this time in the name dialog box, I'm going to specify the name of the duty we just created which is
dbVehicleDuty. And I'll press enter. And we'll see it appear here. Now, by adding this duty, we also add the privilege to
approve purchase orders that is associated with this duty.

Lesson 4: Security Properties on Key Elements


Certain elements in the system have properties that affect or control how security will work. Let's take a closer look at
some of those. There are three main security permission properties for buttons that we're going to discuss. The first one
is called needed access level. This can have values like no access, edit, create, delete, or view. If we set the needed
access level property to no access, then every user will have full access to this button. The next property is called needed
permission. And this specifies the minimum permission level needed to allow access to that button. This property
represents a hierarchy where read is the weakest permission in the hierarchy and delete is the strongest. Above the read
hierarchy level, we have the update permission which is one level higher than read. Therefore, the update permission also
includes the read permission below it in the hierarchy. The create permission is higher than the update and read
permissions. Therefore the update and read permissions are also included in the create permission. The third property for
buttons is called needs records. This specifies whether the button will be enabled when no records are present. The
available values for this property are yes or no. Let's review some of the security permission properties for table fields.
The first one we're going to discuss is the allow edit property. And this specifies whether a user is allowed to modify data
in an existing record in a form when a table field exists on a form. The allow edit on create property determines whether
the users are allowed to enter data in the field when a new record is created in a form. The mandatory table field property
indicates whether a user must add data to a field in a form. If it's set to yes, that indicates that the default or initialization
value for each data type is not acceptable and another value must be supplied. The minimum read access property can be
set to yes or no. If it's set to know, then no access will be granted to that field. If the minimum read access is set to yes,
then view access will be granted to that field. Otherwise, view access will be granted if it's part of the natural key auto
identification field group. Or if it's a title field or system field. Let's review some of the security permissions properties
on form fields. The first one we're going to discuss is the allow edit property. And this specifies whether you can modify
data in the control. When this property is set on a container control, modifications are either disabled or enabled for all
controls within that container. The mandatory property determines whether users must enter data into the control. If the
mandatory property is set to yes, a red wavy line will be displayed on empty fields. A warning sign will also be displayed
if the user tries to navigate away from the field without completing it. The needed permissions property specifies the
minimum permission level needed to allow access to the form control. The values for the needed permission property
represent a hierarchy, read being the weakest permission and delete being the strongest. Read is included by the update
permission which is one level higher in the hierarchy. Then we have the create permission which is above both the read
and update permissions and, therefore, includes the read and update permissions with it. Now let's review some of the
security permissions properties for menu items. And the first one we're going to discuss is the correct permissions
property. This specifies whether correct permission will be available to select when privileges are assigned to this menu
item. The options can be set to auto or no. Auto means the permission will be available to select as a privilege on this
menu item. No means the permission will not be available to select as a privilege on the menu item. The default value is
auto. Create permissions is a similar property, except it specifies whether the create permission will be available to select
when privileges are assigned to the menu item. The options again are auto and no where the default value is auto, and that
means the permission will be available to select as a privilege on this menu item. No means the permission will not be
available to select as a privilege on the menu item. The delete permissions again specifies whether the delete permission
will be available to select when privileges are assigned to the menu item. The options also are auto and no with a default
value being auto and auto says the permission will be available to select as a privilege on this menu item. And no means
the permission will not be available to select as a privilege on this menu item. We then have the linked permission object
property. This specifies the name of another object or element, for example a form or report, whose permissions are to be
applied to this menu item. This is typically used with action menu items. We then have the linked permission object
child, and this specifies if there is some object, child object associated with the main linked permission object whose
permissions should be applied to this menu item. We then have the linked permission type. This specifies the type of
object pointed to by the linked permission object property. For example, the linked permission type could be form or it
could be report. We then have the read permissions property. And this specifies whether the read permission will be
available to select when privileges are assigned to this menu item. The values again are auto and no, where the default
value is auto and the permission for auto means it will be available to select as a privilege on this menu item. And no
means it will not be available to select as a privilege. And finally, we have the update permissions. This specifies
whether the update permission will be available to select when privileges are assigned to this menu item. Again, we have
two possible values with auto and no. When the default value is auto, auto means the permission will be available to
select as a privilege on this menu item, and no means the permission will not be available to select on this menu item.

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

● Authentication for the user interface

● Sign in via AAD

● AAD redirects to AX

● AX start page displayed

● Authentication for services

● Apps consume AX web services

● AX web services (OAuth)

● Apps granted delegated access

● Security Authorization and Access Control

● Security roles

o All users must be assigned a security role

o Determines duties user can perform and what they can view on interface

● Process cycles

o Coordinated set of activities in which participants consume, produce, and use


economic resources to achieve organizational goals.

● Duties

o Correspond to parts of business process

o Admin assigns duties to security roles

o Can be assigned to more than one role

● Privileges

o Specifies level of access required to perform a job, solve a problem or complete


an assignment

o Can be assigned directly to rules

o Recommended only assign duties to roles


o Contains permissions to individual app objects

● Permissions

o Grants access to logical units of data and functionality

o Only developers can create/modify permissions

● Extensible Data Security Framework

● Query

● Security policy

● Context

● Constrained tables

● Role Design Principles

● Roles represent common access rights required for job positions

● Roles account for organization size, culture, industry focus

● Users are assigned to roles according to their job

● Role types

o Functional role

o Organizational role

o Application role

● Role segregation categories

▪ Security Properties on Key Elements

● Button Properties

● Needed access level

● Needed permission

● Needs record

● Table Fields

● Allow edit

● Allow edit on create

● Mandatory
● Minimum read access

● Forms Fields

● Allow edit

● Needed permission

● Mandatory

● Menu items

● Correct permissions

o Specifies whether correct permission will be available to select when privileges


are assigned to the menu item

● Create permissions

o Specifies whether create permission will be available to select when privileges


are assigned

● Delete permissions

o Specifies whether delete permission will be available

● Linked permission object

o Specifies type of object to by the LinkedPermissionObject property

● Linked permission object child

● Linked permission type

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.

Lesson 1: Business Intelligence


In this lesson, we'll walk through the BI features that are available in AX. Some of the new BI features in AX include in-
memory aggregate models. These aggregate models have replaced SSAS cubes. There's also the concept of aggregate
data entities. These are read-only entities that are used for reporting purposes. When you're building charts or other client
controls, you can add aggregate data entities to a form as a data source. You can then consume these data entities
programatically. The aggregate programming model enables a developer to consume this data programatically using X++
or C# code. Method expressions also enable a developer to build rich expressions using aggregate data. Method
expressions are written in X++ and KPIs can be modeled using them which eliminates the need for complex MDX
queries. An aggregate measurement is a model that contains a collection of measures together with their corresponding
dimensions. So measures are aggregate numbers like total sales or number of orders, and dimensions are slicers to slice
those measures by, such as product or vendor. So a total sales number is really kind of useless unless we can slice it by
total sales by customer or by product. So these aggregate measurements help you analyze data in a new way. These are
the evolution of cubes. Aggregate dimensions are another concept which are shared across an AX implementation.
Aggregate measurements associate themselves with relevant aggregate dimensions. For example, total sales can be
associated with a customer, a product, or a sales region. However, total sales can't be associated with a vendor.
Aggregate dimensions and measurements are modeled using AX in Visual Studio tools. In AX, users can use a rich client
form to modify a KPI definition. Users can also define new KPIs by using the aggregate data that is contained in the
aggregate measurements. After a KPI is defined, users can customize it at runtime. There are three main types of BI in
terms of AX. The first is contextual BI. This refers to providing required insights as part of the user experience such that
the user has relevant insights to not only achieve the task at hand but to be highly productive during the course of the day.
Embedded BI refers to analytic content being embedded within AX within the user experience on a form for example.
Contextual BI and embedded BI teams are closely related. Contextual BI implies the added notion that the context of
analytic content resolves around the data or the task at hand. And finally, self-service BI refers to enabling the user to
tweak existing reports or create their own new analytic content such dashboards and KPIs. Microsoft PowerBI is a
collection of tools and services that enable interactive visualizations and dashboards. You can access PowerBI
visualizations from PowerBI.com with a free account. Dynamics AX integrates with PowerBI by being a first-class data
source of PowerBI authoring tools such as Microsoft Excel. After reports are authored, they can be published at
PowerBI.com for collaboration and mobile access. Although dashboards and reports can be used on PowerBI.com, they
can also be pinned to the Dynamics AX client to provide interactive visuals that are related to business processes. Prebuilt
AX content packs from Microsoft and their partners offer ready-made analytical dashboards and reports for industry
verticals. Users can deploy these content packs directly from PowerBI.com. Tiles and charts created in PowerBI can be
pinned in the AX client as well. As users view reports and visuals in PowerBI.com, they can drill back into the Dynamics
AX client to take action on trends and exceptions and data. Users see only data that is relevant to them and that they have
access to.

Lesson 2: Reporting Services


Now let's take a look at SQL Server reporting services in AX. In Dynamics AX, reporting services are hosted in the
Microsoft Azure compute service. If you're developing in a one-box environment, this service is also run locally in the
Azure compute emulator. In a one-box environment, developers can easily modify, create, and preview reports from end-
to-end, all within Visual Studio 2013. A separate process is not required to add reports to the application object tree on
the application server. Changes to reports that are packaged together with other solution updates are uploaded and
deployed to the cloud only after development is completed in the local environment. The enhanced report viewing
experience for end users in Dynamics AX is the same as the report preview in Microsoft Visual Studio. By pressing
CTRL F5 in the development environment, you can build and preview the report in an Internet Explorer window. The
report will appear exactly as it would in the client. You do not have to set up or administer a local report server for
development because the reporting services run in the Azure compute emulator together with the application server. After
reports have been deployed to the local reporting services, they can be accessed from the client. The process of
developing a report is easy in Dynamics AX because you can create and validate a reporting solution entirely within
Visual Studio. Let's take a look at the high-level steps for the report development process. We would first create a
reporting project in Visual Studio. We would then edit the report in Visual Studio. Next, we would add the report to a
menu item and set the menu item as the startup object for our project. We would then use the AOT to deploy the report to
the report server. Finally, we would press CTRL F5 to verify the report design in the Dynamics AX client. When the
whole solution is completed, you can deploy it to the cloud in one package. Some of the advantages of SSRS reports
include the built-in back-office document management capabilities. This includes things such as e-mail support or
scheduled executions via batch. We also have parameterized views and drill-through navigations so we can click on
particular items in the report and be taken to other AX pages and reports. We also have precision documents to comply
with local regulatory business practices. The financial reporting area is where users can access 22 default financial
reports. These reports were previously accessed using an integrated reporting tool called management reporter. This
feature allows users to run financial statements such as a balance sheet or an income statement directly from the AX web
client in the browser. The 22 default reports that come with AX can be edited and new ones can also be created. The
financial reporting menu can be found in the following places in Dynamics AX. We can navigate to the general ledger,
inquiries and reports and then choose financial reports. The financial reporting functions are available to users who have
the appropriate privileges and duties assigned to them in order to run the reports. Users with the security administrator
role assigned to them can view, edit, and manage the financial reports. In order to create and generate financial reports for
a legal entity, the following needs to be set up for that particular entity. They must have a fiscal calendar set up, a ledger
set up, the chart of accounts need to be set up, and they have to have a currency established.

Lesson 3: Services and Integration


During this lesson, we'll explore some of the services and integrations available in Dynamics AX. All of service groups
under the AOT service group node are automatically deployed. All services that must be deployed must be part of a
service group. This diagram lists all of the service endpoints that are available in Dynamics AX. Data entities can be
used for importing and exporting data. They can also be consumed via an OData protocol and then used on reports or
integrated into PowerBI, and X++ classes can be consumed via the SOAP and REST services which use HTTP/XML,
HTTP and the JSON protocol respectively. Consuming external web services is also supported by creating a class library
project in Visual Studio. Open data protocol or OData is a standard protocol for creating and consuming data. OData
applies web technologies such as HTTP and JavaScript object notation, which is JSON, to provide access to information
from various programs. It supports a uniform URL convention for features like filtering and sorting data. More
information on OData URL syntax can be found at OData.org. OData entities in Dynamics AX are based on the concept
of an updatable view. When the is public property for an updatable view is set to true, that view is exposed as a top-level
OData entity. Dynamics AX introduces a public OData service endpoint that enable access to Dynamics AX data in a
consistent way across a broad range of clients. Dynamics AX also introduces the Version 4 of OData which supports
consumption and PowerBI as a refreshable data source as well. Dynamics AX integrates with Microsoft Office. One of
the featured integrations is the Excel data connector app. This app interacts with Excel workbooks in Dynamics AX
OData services that are created for publicly exposed entities. The Excel data connector app enables Excel to become a
seamless part of the Dynamics AX user experience. The data connector app is built by using the apps for Office
framework. It runs in a task pane that contains all app-related actions and information. Office applications are web
applications that run inside an embedded Internet Explorer browser window. The Excel data connector app supports data
refresh and publishing back to AX. The export to Excel feature is a static export of grid data directly to an Excel
spreadsheet. This is useful for quick analysis of data. Another integrated feature of AX is the workflow editor. A
workflow represents a business process. It defines how a document flows or moves through the system by showing who
must complete a task, make a decision, or prove a document. For example, the following figure shows a workflow for
expense reports. The workflow editor is a program that you click one time to download. The editor communicates with
Dynamics AX by using services. Therefore, Dynamics AX can carry a rich graphical workflow design experience.
Workflow development wizards have imported into Microsoft Visual Studio. Three components of workflows include
consistent processes. You can define how specific documents such as purchase requisitions and expense reports are
processed. Process visibility allows you to track the status history and performance metrics of workflow instances. This
helps you determine whether changes should be made to the workflow to improve efficiency. A centralized work list
allows users to view a central list of work that displays the workflow tasks and approvals that are assigned to them.

Lesson 4: Data Entities


In this lesson, we will discuss the use and application of data entities in AX. A data entity is an abstraction from the
physical implementation of database tables. For example, in normalized tables, a lot of the data for each customer might
be stored in a customer table and then the rest might be spread across a small set of other related tables such as an address
table, for example. In this case, the data entity for the customer concept appears as one denormalized view in which each
row contains all of the data for the customer table and its related tables. Data entities also provide a single stack to
capture business logic. They provide a primary mechanism to insert and extract data sets. And this can be used to replace
the diverging concepts of the DIXF entities or the data import/export framework entities. The following diagram
illustrates the concept of a denormalized view. The current normalized model contains a customer table with some
information about a customer such as their account number. It then relates out to another table called a party table where
we have a party number and name. And that table reaches out further to an electronic address and an address table that
contain more information about the customer such as their city, their phone number, e-mail address, and all this
information about our customer entity is split up into these four different tables. This can complicate processes such as
data importing and exporting. The concept of the denormalized views depicted on the right. We have a customer entity
and a single denormalized customer entity view. And all of these fields that are in different tables here are now stored
into one larger table. Let's take a look at the different data entity categories. The first one is the parameter category. And
this has functional or behavioral parameters. This is required to set up a deployment or a module for a specific build or
customer. It can include data that is specific to an industry or business and the data can also apply to a broader set of
customers. We then have the reference data entity category. This includes simple reference data of small quantity that is
required to operate a business process. Examples of this include units, dimensions, and tax codes. Next, we have the
master data entity category. And this is the data assets of the business. Generally, these are nouns such as people, places,
and concepts. Complex reference data of large quantity is included in this category. Some examples are customers,
vendors, and projects. The next data entity category is called document. This is worksheet data that is converted into
transactions later. Documents that have complex structures such as several line items for each header record are a good
example of a document data entity. Other examples are sales orders, purchase orders, open balances, and journals. The
last data entity category we're going to discuss is the transaction category. This is the operational transaction data of the
business such as posted transactions. Typically, these items are excluded during a full data set copy. An example would
be pending invoices. Let's review some use cases for data entities. The first one is synchronous services. Data entities
enable public application programming interfaces known as APIs on entities to be exposed which enables synchronous
services. Synchronous services are used for Office integration as well as third-party mobile apps. Data entities also
support asynchronous integration through a data management pipeline. This enables asynchronous and high-performing
data insertion and extraction scenarios such as interactive file-based import/export or recurring integrations. Data
migration is streamlined by using data entities in denormalized views. Data entities also enable BI features by creating
aggregate data entities which can then be used for reports, data sources on forms, as well as be accessed
programmatically. Data entities can be added to a project in Visual Studio just like any element. When you initially add
it, a data entity wizard will guide you through the process of adding and configuring it. At completion, it will create a
data entity along with an optional staging table. You can also right click a table in the table designer in Visual Studio and
choose add-ins, create data entity.

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.

MODULE 17 KEY TAKE AWAY


o Introduction to Advanced Topics

▪ Business Intelligence

● BI Features

● In-memory aggregate models

● Aggregate data entities

● Aggregate programming model

● Aggregate measurements and dimensions

● New KPI modeling

● 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

● Services hosted in Microsoft Azure Compute service

● Simplified development

● Simplified administration

● Enhanced report viewing

● Development Process

● Create reporting project in Visual Studio

● Edit report in Visual Studio

● Add report to menu item


● Set menu item as start up object

● Deploy report to server

● Use CTRL + F5 to verify the report

● Advantages of SSRS Reports

● Built-in back-office document management capabilities

● Precision documents to comply with local regulatory business practices

● Parameterized views and drill-through navigations to other AX pages and other reports

● Financial Reporting

● 22 default financial reports

● Users can edit or create new reports

● Requires proper privileges and duties

▪ Services and Integrations

● Overview

● All service groups under AOTService group are automatically deployed

● All services that must be deployed must be part of a service group

● Consuming external web services is supported

● Open Data Protocol (Odata) V4

● Provides a simple and uniform way to share data in a discoverable fashion

o Uniform URL conventions

● Enables broad integration across products

● Supports consumption in PowerBI.com as a refreshable data source

● Office Integration

● Excel Data Connector app

● Export to Excel

● Workflows

● Consistent processes

● Process visibility
● Centralized work list

▪ Data Entities

● About

● Replace diverging concepts of DIXF entities

● Provide primary mechanism to extract/insert data sets

● Provides single stack to capture business logic

● De-normalized view of database tables

● 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 postal address

o Primary email

o Primary fax

● Data Entity Categories

● Parameter

● Reference

● Master

● Document

● Transaction

● Data Entity Use Cases

● Synchronous services

● Asynchronous integration

● Data migration

● Business intelligence

● Creating Data Entities

● Add new data entity to a project and follow the wizard

● Build entity directly from a table


MODULE 17: YOUR NOTES

You might also like