We will use Visual Studio 2017 to create our data import utility for importing Make and Models data. Follow these steps to create this utility:
- Start Visual Studio, go to New Project, and select Console App, as shown in the following screenshot:
- Next, let's add a Dynamics 365 Core SDK reference to our sample console application. Right-click on the project, select Manage NuGet Packages, and follow the steps shown here:
- Let's add our configuration data in App.config so that we can make changes if and when required. First, we need to get the Organization Service using the following steps. Navigate to Settings | Customizations | Developer Resources as shown in the following screenshot, and copy the Endpoint Address from the Organization Service, as follows:
We also need to get the path of our CSV files, so we can store all these details in our App.config file, as follows:
We will be using all the preceding keys to get configuration data in our utility code.
- Next, right-click on the project name from the Solution Explorer and select Add | Class, and let's name it Dynamics365Utility.
- Next, we need to add a reference for the Dynamics 365 CE assemblies and other assemblies that we will be using, like so:
using System.Configuration;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Client;
using Microsoft.Xrm.Sdk.Query;
using System.IO;
using System.Data;
The Dynamics 365 CE SDK helps us to work with entities and classes. System.IO is used to work with StreamReader, which will help us to process data available in CSV files. System.Data is used to work with data tables and rows.
- Let's first add a constructor to our class, as follows, to create a connection with the Dynamics 365 CE organization:
public Dynamics365Utility()
{
ClientCredentials credentials = new ClientCredentials();
credentials.UserName.UserName = ConfigurationManager
.AppSettings["UserName"];
credentials.UserName.Password = ConfigurationManager
.AppSettings["Password"];
Uri serviceUri = new Uri(ConfigurationManager.AppSettings["OrgURL"]);
OrganizationServiceProxy proxy = new OrganizationServiceProxy(serviceUri, null, credentials, null);
proxy.EnableProxyTypes();
service = (IOrganizationService)proxy;
}
In the preceding code, you can see that we are getting our configuration data from the App.configfile by passing a key. Once we have an Organization Service URL and credentials, we can pass them to the OrganizationServiceProxy class. We can get an Organization service object from the OrganizationServiceProxy.
- Next, let's add a method to read our CSV files, as follows:
private DataTable GetCSVFile(string keyname) {
string path = ConfigurationManager.AppSettings[keyname];
string fileText = string.Empty;
DataTable source = new DataTable();
try {
using(StreamReader sr = new StreamReader(path)) {
while (!sr.EndOfStream) {
fileText = sr.ReadToEnd().ToString();
string[] rows = fileText.Split(' ');
for (int i = 0; i < rows.Count() - 1; i++) {
string[] rowValues = rows[i].Split(','); {
if (i == 0) {
for (int j = 0; j < rowValues.Count(); j++) {
source.Columns.Add(rowValues[j]);
}
} else {
DataRow dr = source.NewRow();
for (int k = 0; k < rowValues.Count(); k++) {
dr[k] = rowValues[k].ToString();
}
source.Rows.Add(dr);
}
}
}
}
}
} catch (Exception e) {
throw e;
}
return source;
}
The preceding method takes a key name as a parameter that is used to get the value from the App.config file, based on this key. Once we have a file path, we get the StreamReader class to read all the data available in the CSV file. In our code, we first get row data to store the data table's column name, and all the other data is stored in rows. Sometimes, when working with CSV, we may get the or character next to a column name or a data name, so let's add a method to remove these characters, as follows:
public static string GetRowValue(string value)
//check for
if (value.Contains(' ') || value.Contains(' ')) {
//remove or
value = value.Substring(0, value.Length - 1);
}
return value; }
In our next method, let's use the GetCSVFile method and process it to import make entity data, as follows:
public void AddMakers() {
//get csv file data into data table
DataTable makers = GetCSVFile("Makers");
//loop all rows and get their data
foreach(DataRow row in makers.Rows) {
if (row["Name "].ToString() != "") {
//Create Make record
Entity make = new Entity("him_make");
make["him_name"] = GetRowValue(row["Name "].ToString());
service.Create(make);
} }}
In the preceding code, we are using the Create method of the Organization service to create make entity record data. In the make entity, we have just one field, which is the primary field of the make entity, so we are only setting the name field of make while creating its record.
To import the model record, we need to import a make record first because a model entity has a lookup for the make entity. While importing model data, we need to get the globally unique identifier(GUID) of the make record to set the lookup field value. Let's add the following method to query the make record ID based on its name:
private Guid GetMake(string make) {
EntityCollection results = null;
Guid Id = Guid.Empty;
QueryExpression query = new QueryExpression() {
EntityName = "him_make",
ColumnSet = new ColumnSet(new string[] {
"him_name"
}),
Criteria = {
Filters = {
new FilterExpression {
FilterOperator = LogicalOperator.And,
Conditions = {
new ConditionExpression("him_name", ConditionOperator.Equal, make)
},
}
}
}
};
results = service.RetrieveMultiple(query);
if (results.Entities.Count > 0)
Id = results.Entities.FirstOrDefault().Id;
return Id;
}
In the preceding code, we are using the QueryExpression class, where we have added a filter expression that has one condition to compare the Make record name based on the string parameter. Here, we are using the RetrieveMultiple method, as we are querying data based on the non-primary key field. This method will check whether we have a Make record available in Dynamics 365 CE. If we have, it will return the record's GUID; otherwise, it will return an empty GUID.
- Next, we can use the following method to add model data, where we will also incorporate the GetMakemethod:
public void AddModel() {
//get model file path
DataTable models = GetCSVFile("Model");
//process medle file records
foreach(DataRow row in models.Rows) {
if (row["Make"].ToString() != "" && row["Model "].ToString() !=
"") {
//create model
Entity model = new Entity("him_model");
model["him_name"] = row["Model "].ToString();
//get make record id
Guid makeId = GetMake(row["Make"].ToString());
if (makeId != Guid.Empty) {
model["him_make"] = new EntityReference("him_make", GetMake(row["Make"].ToString()));
}
service.Create(model);
}
}
}
The preceding method first calls the GetCSVFile method by passing the model key name and then processes model data row by row. This method also uses the GetMake method to get a Make record ID based on its name.
- Finally, we can call our public methods from the main method of our sample console application. We will use the following code:
static void Main(string[] args) {
Dynamics365Utility utility = new Dynamics365Utility();
Console.WriteLine("Importing HIMBAP Auto Service Make and Models
Data.....");
utility.AddMakers();
Console.WriteLine("Maker data imported correctly");
utility.AddModel();
Console.WriteLine("Models data imported correctly");
Console.ReadLine();
}
In the preceding code, first, we are creating an object of our Dynamics365Utility class, and then importing its Make and Models data into Dynamics 365 CE. When we run this application, we should see details on the screen like the following:
We should see our data in Dynamics 365 CE. This is how we can create our own utility to interact with Dynamics 365 CE data. In the next section, we are going to discuss how we can use Power Automate to integrate Dynamics 365 CE with other applications.