Customer Engagement & Dynamics CRM Forum

How to create a Note through a Console App

By Gerry Yurko posted Apr 25, 2019 10:58 AM

  
Recently I had a request to create a Note for 168 Records under an Order.  It was the same note for each instance, so I decided to create a quick Console App to do this.  There were a couple of things that needed to be resolved before creating a Note.  I needed the Record's unique Id but I also needed the Record's Object Type Code.  Fortunately I am "On-Prem" so it is pretty easy to get.  However, I wanted to make this program more generic than that and able to work On-Line.  So I needed to get the Object Type Code through a Query.

In searching through the Internet, it took me looking at over 10 different Web Pages to get enough information to create my Query.  Hence this Blog, which will make it easier for others to simply get an Object Type Code by providing the Table's Logical name.

I'm not sure which of the References are being used, since this NameSpace has over 15 separate Methods, but here are the References I am Using.  Anything that is Grayed out for you is not necessary for this little Routine

using System;
using System.Linq;
using System.Configuration;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Data.OleDb;
using System.ServiceModel.Description;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Sdk.Client;
using Microsoft.Xrm.Sdk.Messages;
using Microsoft.Xrm.Sdk.Metadata.Query;

I am setting up some formatting to make it easier to read.  I will be using the OrganizationServiceProxy to query CRM.

private static void CreatePDNote(ref OrganizationServiceProxy service) {
string EntityName = "new_provisioning";

// Build the Query to get the Object Type Code
MetadataFilterExpression entityFilter = new MetadataFilterExpression(LogicalOperator.And);

// the "IsVisibleInMobile" value was used in the example I found on the Internet.  This worked and gave me over 80 Entities.  I needed one Entity Name, though...
//entityFilter.Conditions.Add(new MetadataConditionExpression("IsVisibleInMobile", MetadataConditionOperator.Equals, true));

entityFilter.Conditions.Add(new MetadataConditionExpression("LogicalName", MetadataConditionOperator.Equals, EntityName));
EntityQueryExpression entityQueryExpression = new EntityQueryExpression() { Criteria = entityFilter };
RetrieveMetadataChangesRequest retrieveMetadataChangesRequest = new RetrieveMetadataChangesRequest() { Query = entityQueryExpression, ClientVersionStamp = null };

// Query the MetaData for the Entity
RetrieveMetadataChangesResponse response = (RetrieveMetadataChangesResponse)service.Execute(retrieveMetadataChangesRequest);

// Grab the Object Type Code from the Response
int ObjectTypeCode = (int)response.EntityMetadata[0].ObjectTypeCode;

// Build the Query to the CRM Database to get the Records we desire
QueryByAttribute query = new QueryByAttribute(EntityName);
query.ColumnSet = new ColumnSet("new_provisioningnumber");
query.Attributes.AddRange("statecode", "new_orderid");
query.Values.AddRange(0, "0000000-5E51-E911-80D4-000000000000"); // Order number O111111.  The Guid is obviously made up

// Initialize a few Fields
String PDNumber = String.Empty;
String Note = string.Empty;
Guid ProvisioningId = Guid.Empty;
EntityCollection GetPDs = service.RetrieveMultiple(query);

// Build the Note Text. Use the "@" sign for easier creation of the Note
Note = @"Some kind of long Note.
  More of the Note.

SE Notes as follows:

  Finished portiuon of Note * *

  * *see Xtra Notes tab for proposed Design**";

Console.WriteLine("Create Notes for PD records " + GetPDs.Entities.Count.ToString());

// Iterate through the retrieved Records to begin creating the Notes
for (int i = 0; i < GetPDs.Entities.Count; i++) {
ProvisioningId = GetPDs[i].Id;
PDNumber = (string)GetPDs[i].Attributes["new_provisioningnumber"];

// In certain instances the Note has already been created and we may want to skip creating 2 Notes,  The numbers are made up
if (PDNumber == "P112345" || PDNumber == "P112346" || PDNumber == "P112347")
    continue;

// 3 things are needed to create a Note.  The Object Id, The Object Type Code and the Note text
Entity CreateEntity = new Entity("annotation");
CreateEntity["objectid"] = new EntityReference(EntityName, ProvisioningId);
CreateEntity["objecttypecode"] = ObjectTypeCode;
CreateEntity["notetext"] = Note;

if (CreateEntity.Attributes.Count > 0) {  // This "If" is a fail-safe to make sure we are not creating blank records.
try {
Console.WriteLine("Create Note for PD: " + PDNumber);
Guid guidNewNote = service.Create(CreateEntity);
Console.WriteLine(" New Note = " + guidNewNote.ToString());
} catch (Exception ex) {
string msg = "Error encountered: " + ex.Message + ": " + ex.InnerException;
Console.WriteLine(ex.Message);
Console.WriteLine(ex.InnerException);
}
}
}
Console.WriteLine();
Console.WriteLine("Done");
        Console.ReadLine();
}
1 comment
10 views

Permalink

Comments

Apr 30, 2019 10:43 AM

You might also want to look into batch updates using ExecuteMultiple. It isn't as critical in an on-premise installation but does have benefits when it comes to improving performance. It reduces the number of calls to the API which is beneficial in online scenarios.

ExecuteMultiple: https://docs.microsoft.com/en-us/dynamics365/customer-engagement/developer/org-service/use-executemultiple-improve-performance-bulk-data-load
API Limits: https://docs.microsoft.com/en-us/dynamics365/customer-engagement/developer/api-limits