locked
Correct way to follow relationships in plugin using strongly typed objects RRS feed

  • Question

  • Hi, I am new to plugins and have been following tutorials, etc.

    I have a plugin that I am playing with. I have got strongly typed objects and understand that the target can be an entity depending on the message, etc. I also understand about preimages and postimages.

    What I am looking at in simple terms is this:

    when a user updates an account, I want to get the data fort eh account and it's primary account entity and send this to a web service.

    I can get a strongly typed Account object and understand that casting the target to Account will only have the data that is being updated. I have also cast the preImage to a strongly typed Account object. With the preImage object, even though the record has a primary contact set (this was saved previously), when I try preImage.account_primary_contact I get a null reference error.

    Am I doing soemthing wrong here? My other thought was to manually load the Account object to test the data that way. How do I retrieve a full Account record using the guid to a strongly typed object? should I use service.retrieve?

    One I have a full Account object, will the properties for relationships be populated - ie will theAccount.account_primary_contact have a populated Contact object? or do I need to do something else? it seems that following the relationships using dot notation should work?

    thanks in advance for the help!

    james



    Friday, December 4, 2015 8:10 AM

Answers

  • Hi Chris - thanks for the reply. Yes I have used crmsvcutil to generate the class file for the entities.

    When I am accessing the properties of the primary entity this is fine, but it's when accessing the related entities that I always seem to have null references. I kept playing and finally got a valid reference using the below - the last object primaryAccount is populated.

    My next issue is getting a set of related entities - for example iterate all contacts for an account. I cannot see how to do this? should I be querying Contacts for an account ID?

    Entity entity = (Entity)context.InputParameters["Target"];
    
                Account createdAccount = entity.ToEntity<Account>();
                string entityDescription = DateTime.Now.ToString() + " main contact (from post image): " + newVals.Telephone1 + " updated tel:" + createdAccount.Telephone1 + createdAccount.PrimaryContactId;
       
    
                createdAccount.Description = entityDescription;
               
    Account thisAccount = (Account)service.Retrieve(Account.EntityLogicalName, createdAccount.Id, new Microsoft.Xrm.Sdk.Query.ColumnSet(true ));
               
    
                Contact primaryContact =(Contact)service.Retrieve(Contact.EntityLogicalName, thisAccount.PrimaryContactId.Id, new Microsoft.Xrm.Sdk.Query.ColumnSet(true));

    • Marked as answer by jamesdawson1 Tuesday, December 8, 2015 1:05 PM
    Monday, December 7, 2015 8:59 AM
  • Hi,

    You really shouldn't have to retrieve the account you are currently working on, on create all fields should be present in the property bag and on update it's better to use the pre-image in conjunction with the update context.

    As for working on all related Contacts for example, you need to do a retrievemultiple looking something along these lines

    QueryByAttribute qba = new QueryByAttribute("contact") {
       ColumnSet = new ColumnSet(true),
       Attributes.AddRange("parentaccountid"),
       Values.AddRange(createdAccount.id)
    };
    EntityCollection ents = service.RetrieveMultiple(qba);
    

    This is just of the top of my head so there are probably some typos there, I'm a bit unsure if the field is called parentaccountid for example since I haven't a CRM where I can double check this...

    You can iterate through that entity Collection to be able to see all the relatet Contact to the account.

    Regards


    Rickard Norström Developer CRM-Konsulterna
    http://www.crmkonsulterna.se
    Swedish Dynamics CRM Forum: http://www.crmforum.se
    My Blog: http://rickardnorstrom.blogspot.se

    • Marked as answer by jamesdawson1 Tuesday, December 8, 2015 1:05 PM
    Tuesday, December 8, 2015 7:51 AM

All replies

  • For example - is this the correct way of retrieving the primary contact details....?

    AccountthisAccount = (Account)service.Retrieve(Account.EntityLogicalName, createdAccount.Id, newMicrosoft.Xrm.Sdk.Query.ColumnSet(true));

    ContactprimaryContact =(Contact)service.Retrieve(Contact.EntityLogicalName, thisAccount.PrimaryContactId.Id, newMicrosoft.Xrm.Sdk.Query.ColumnSet(true));

    //dirty way to get feedback

    thrownewInvalidPluginExecutionException("Primary Contact:"+ primaryContact.FirstName + " "+ primaryContact.LastName);

    Friday, December 4, 2015 10:31 AM
  • When you say you have 'strongly typed objects', did you run the CRMSVCUTIL to generate the class file with all your entities in it?

    If so, there are a couple of options within a plugin to get the data from the record. At the beginning of your code you can put a reference like this to get to all the fields on the current record.

    Account _postRecord = postImageEntity.ToEntity<Account>();

    Then use _postRecord.xxxx to get to the strongly typed fields on the Account.

    I too have noticed some inconsistency with the usage of the linked entity reference like:

    _postRecord.account_primary_contact

    Seems like sometimes it's there, and sometimes it's not and I haven't narrowed down why.  You should be able to get the ID from:

    _postRecord.PrimaryContactId

    Then do a LINQ query on the contact entity to get the related contact record.

    Contact c = xrm.ContactSet.Where(x => x.ContactId == _postRecord.PrimaryContactId).FirstOrDefault();


    Friday, December 4, 2015 9:32 PM
  • Hi Chris - thanks for the reply. Yes I have used crmsvcutil to generate the class file for the entities.

    When I am accessing the properties of the primary entity this is fine, but it's when accessing the related entities that I always seem to have null references. I kept playing and finally got a valid reference using the below - the last object primaryAccount is populated.

    My next issue is getting a set of related entities - for example iterate all contacts for an account. I cannot see how to do this? should I be querying Contacts for an account ID?

    Entity entity = (Entity)context.InputParameters["Target"];
    
                Account createdAccount = entity.ToEntity<Account>();
                string entityDescription = DateTime.Now.ToString() + " main contact (from post image): " + newVals.Telephone1 + " updated tel:" + createdAccount.Telephone1 + createdAccount.PrimaryContactId;
       
    
                createdAccount.Description = entityDescription;
               
    Account thisAccount = (Account)service.Retrieve(Account.EntityLogicalName, createdAccount.Id, new Microsoft.Xrm.Sdk.Query.ColumnSet(true ));
               
    
                Contact primaryContact =(Contact)service.Retrieve(Contact.EntityLogicalName, thisAccount.PrimaryContactId.Id, new Microsoft.Xrm.Sdk.Query.ColumnSet(true));

    • Marked as answer by jamesdawson1 Tuesday, December 8, 2015 1:05 PM
    Monday, December 7, 2015 8:59 AM
  • Hi,

    You really shouldn't have to retrieve the account you are currently working on, on create all fields should be present in the property bag and on update it's better to use the pre-image in conjunction with the update context.

    As for working on all related Contacts for example, you need to do a retrievemultiple looking something along these lines

    QueryByAttribute qba = new QueryByAttribute("contact") {
       ColumnSet = new ColumnSet(true),
       Attributes.AddRange("parentaccountid"),
       Values.AddRange(createdAccount.id)
    };
    EntityCollection ents = service.RetrieveMultiple(qba);
    

    This is just of the top of my head so there are probably some typos there, I'm a bit unsure if the field is called parentaccountid for example since I haven't a CRM where I can double check this...

    You can iterate through that entity Collection to be able to see all the relatet Contact to the account.

    Regards


    Rickard Norström Developer CRM-Konsulterna
    http://www.crmkonsulterna.se
    Swedish Dynamics CRM Forum: http://www.crmforum.se
    My Blog: http://rickardnorstrom.blogspot.se

    • Marked as answer by jamesdawson1 Tuesday, December 8, 2015 1:05 PM
    Tuesday, December 8, 2015 7:51 AM
  • thanks for the info Rickard!
    Tuesday, December 8, 2015 1:05 PM