5

I've made code to check if a record in CRM exists. Problem is that the IOrganisationService.Retrieve returns an error instead of a null when no record is found. I expect multiple records not to be found and I do not want to have to use a try catch then use the error from the catch.

using (OrganizationServiceProxy serviceProxy = new OrganizationServiceProxy(OrganizationUri, HomeRealmUri, credentials, null))
            {
                IOrganizationService service = (IOrganizationService)serviceProxy;
                //Get record

                var record = service.Retrieve(entryId, guid, new ColumnSet(true)); //switch to var if no work
                //Check if record is not null/empty
                recordExists = !String.IsNullOrWhiteSpace(record.Id.ToString()); //<- does the record exist
            }

Suggestions?

Zain
  • 1,246
  • 4
  • 15
  • 26

2 Answers2

3

Method Retrieve presumes that the record with the given ID actually exists in the system. In general it fails in only two scenarios:

  1. The record was deleted by another user or process.
  2. The user does not have sufficient read privileges.

When you need to query for data that may not exist or when a query can yield zero, one or more records, use QueryExpression queries; you can issue these queries using the RetrieveMultiple method. If you like, you can also use LINQ for CRM, which basically wraps the QueryExpression functionality.

Henk van Boeijen
  • 7,357
  • 6
  • 32
  • 42
2

Use RetrieveMultiple to retrieve users with the ID you're interested in:

// Create and cache the plugin context
this.context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
var serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
this.service = serviceFactory.CreateOrganizationService(this.context.UserId);

// Retrieve users with certain ID
Guid userId = Guid.NewGuid();
var query = new QueryExpression("systemuser");
query.Criteria.AddCondition(new ConditionExpression("systemuserid", ConditionOperator.Equal, userId));

EntityCollection users;
try
{
    users = this.service.RetrieveMultiple(query);
}
catch (FaultException<OrganizationServiceFault> faultException)
{
    throw new InvalidPluginExecutionException($"Failed to retrieve system users that have an ID of '{userId}'", faultException);
}

if (users.Entities.Length == 0) // (or !users.Entities.Any() using Linq)
{
    // Do something
}
Phil
  • 563
  • 4
  • 6
  • 16
  • The code works, maybe my explanation was a bit bad. The Retrieve method errors if no result is found; I want to know which CRM records do not exist without having to use the catch to say that the record doesn't exist. – Zain Oct 10 '16 at 09:29
  • I don't think that is possible using the `Retrieve` method. The CRM service will throw an exception of type `FaultException` if the record does not exist. What you could do however is use `RetrieveMultiple` to retrieve a list of records that have the ID you are interested in - if the length is 0, an exception will not be thrown. I've updated my answer. – Phil Oct 10 '16 at 10:02
  • The `Retrieve` method is supposed to return the specified record and a call to it will only fail in rare cases. Hence, error handling should preferrably be handled at the highest level possible. – Henk van Boeijen Oct 10 '16 at 10:04
  • @Phil Thanks for the help, your solution worked for me. – Zain Oct 10 '16 at 15:55