locked
CRM 2013 - C# Plugin RRS feed

  • Question

  • Hi

    I was wondering if it was possible to access another entity and their fields while the plugin is working on another.

    I am working on a Entity called 'Orders'

    In orders the user can create an address, I want to be able to get the data that's in a field called 'Address Code' which is in the Entity 'Address'

    The Entity address is a out of the box entity which I understand has many limitations

    Will it be possible to do what I want?

    Thanks, Shaun


    S.Harrison

    Wednesday, June 18, 2014 10:57 AM

Answers

  • Hi Shaun,

    The following code would do the job:

    ConditionExpression condition1 = new ConditionExpression(); condition1.AttributeName = "parentid"; condition1.Operator = ConditionOperator.Equal; condition1.Values.Add("A99D25C4-AFD5-E311-946F-D89D6765B134"); //have your account/contact id here FilterExpression filter1 = new FilterExpression(); filter1.Conditions.Add(condition1); filter1.FilterOperator = LogicalOperator.And; QueryExpression query = new QueryExpression("customeraddress"); query.ColumnSet.AddColumns("addressnumber"); query.Criteria.AddFilter(filter1);

    EntityCollection result1 = _serviceProxy.RetrieveMultiple(query);



    Admin QuikView Solution for CRM 2013


    Wednesday, June 18, 2014 12:37 PM
  • I have resolved the issue

    My code was as follows

    IPluginExecutionContext context = (IPluginExecutionContext)
                    serviceProvider.GetService(typeof(IPluginExecutionContext));
                          
                           
                IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
                IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
    

    I needed to declare service not context in the line

     EntityCollection result1 = context.RetrieveMultiple(query);

    It needed to be

     EntityCollection result1 = service.RetrieveMultiple(query);

    Thanks for all your help

    Shaun


    S.Harrison

    Thursday, June 19, 2014 8:36 AM
  • Another change for anyone who is wanting to do something similar was

    condition1.Values.Add(accountCode);

    This gave errors as the query was looking for an id and accountCode was providing a EntityReference

    the line was changed to

    condition1.Values.Add(accountID.Id);

    Everything now works as I wanted

    Thanks to everyone for their help


    S.Harrison

    Thursday, June 19, 2014 8:48 AM

All replies

  • Hi Shaun,

    Of course that is possible. You can create a query any entity irrespective of the entity against which the Plugin is executing. All you need is to create a query in Plugin which can be done by different methods like QueryExpression or FetchXML or LinQ and fire that query using RetrieveMultiple method and retrieve data.

    Have a look at these links :

    http://msdn.microsoft.com/en-us/library/gg334607.aspx

    http://msdn.microsoft.com/en-us/library/gg328149.aspx


    Admin QuikView Solution for CRM 2013



    Wednesday, June 18, 2014 11:03 AM
  • As said you can write your query based on your condition and define which attribute you want to fetch, refer this to see diffent options if you want to use queryexpression

    You can see here methods supported by address entity


    Our Website| Our Blog | Follow US | My Facebook Page | Microsoft Dynamics CRM 2011 Application Design
    Make sure to "Vote as Helpful" and "Mark As Answer",if you get answer of your question.

    Wednesday, June 18, 2014 11:42 AM
    Moderator
  • Thanks both

    So from reading the links provided I feel that QueryExpression would be the best option

    Address Entity can have multiple retrieve method which is what I need

    From the example code given I have customized the following to suit what I want

    (I realized that I need address number not Address Code)

    ConditionExpression condition1 = new ConditionExpression();
    condition1.AttributeName = "addressnumber";

    //Can the two lines below be removed as I'm not looking for a certain address number

    condition1.Operator = ConditionOperator.Equal;
    condition1.Values.Add("Brown");     

    //      

    FilterExpression filter1 = new FilterExpression();
    filter1.Conditions.Add(condition1);

    QueryExpression query = new QueryExpression("address");
    query.ColumnSet.AddColumns("addressnumber");
    query.Criteria.AddFilter(filter1);

    EntityCollection result1 = _serviceProxy.RetrieveMultiple(query);

    From here the example code used a loop to print out each result in a console application

    however im using a class library therefore I don't need to print out all the information

    I do however need to be able to use it

    Would putting the data into a array be best?

    Thanks, Shaun


    S.Harrison


    Wednesday, June 18, 2014 12:02 PM
  • ConditionExpression condition1 = new ConditionExpression();
    condition1.AttributeName = "ConditionalAttributename"; // you need to provide field which you want to compare to get address code

    condition1.Operator = ConditionOperator.Equal;

    condition1.Values.Add("Conditionalattributevalue");     //corresponding value

    FilterExpression filter1 = new FilterExpression();

    filter1.Conditions.Add(condition1);

    QueryExpression query = new QueryExpression("address");
    query.ColumnSet.AddColumns("addressnumber");
    query.Criteria.AddFilter(filter1);


    Our Website| Our Blog | Follow US | My Facebook Page | Microsoft Dynamics CRM 2011 Application Design
    Make sure to "Vote as Helpful" and "Mark As Answer",if you get answer of your question.

    Wednesday, June 18, 2014 12:08 PM
    Moderator
  • Hi

    I realized that I need account number not account code, therefore in the code I posted I had

         condition1.AttributeName = "addressnumber";

    Also as I'm not looking for a certain value, I want to get all of the addresses do I need the two lines that follow which are

         condition1.Operator = ConditionOperator.Equal;
         condition1.Values.Add("Brown");     

    The reason I don't want a certain value is because I'm going to be creating a new address, for each address they have to have a unique account code

    From the account number I can retrieve the highest number in the Addresses and simply add 1 to it.

    Thanks, Shaun


    S.Harrison

    Wednesday, June 18, 2014 12:15 PM
  • Hi Shaun,

    If your objective is to retrieve all CustomerAddress records in Dynamics CRM, you may as well omit the Filter part. So your query would look like:

    QueryExpression query = new QueryExpression("customeraddress");
    query.ColumnSet.AddColumns("addressnumber");
    
    EntityCollection result1 = _serviceProxy.RetrieveMultiple(query);

    Once you get the data, if I were you, I would add them to a List. You can add them to an array as well, but I prefer to use a List<string> as adding is easier.

    But remember, you'll get multiple records having the same "addressnumber" as they are unique only for a specific account/record. This means say Account1 can have 1,2,3 as address numbers; but this won't prevent another account say Account2 to have 1,2 and 3 as well.


    Admin QuikView Solution for CRM 2013


    Wednesday, June 18, 2014 12:16 PM
  • Hi

    That makes more sense, Thank you

    As you mentioned on the last bit of your post, is it possible to only retrieve Addresses that are linked to the account I'm working on?

    I have access to the account code which is unique to each account therefore is there a way to filter using that?

    Thanks, Shaun


    S.Harrison

    Wednesday, June 18, 2014 12:26 PM
  • Hi Shaun,

    The following code would do the job:

    ConditionExpression condition1 = new ConditionExpression(); condition1.AttributeName = "parentid"; condition1.Operator = ConditionOperator.Equal; condition1.Values.Add("A99D25C4-AFD5-E311-946F-D89D6765B134"); //have your account/contact id here FilterExpression filter1 = new FilterExpression(); filter1.Conditions.Add(condition1); filter1.FilterOperator = LogicalOperator.And; QueryExpression query = new QueryExpression("customeraddress"); query.ColumnSet.AddColumns("addressnumber"); query.Criteria.AddFilter(filter1);

    EntityCollection result1 = _serviceProxy.RetrieveMultiple(query);



    Admin QuikView Solution for CRM 2013


    Wednesday, June 18, 2014 12:37 PM
  • Hi

    Thanks!

    So to add to a list I would have the query the length of the returns so that I could create a loop to insert all results into the list?

    Thanks, Shaun


    S.Harrison

    Wednesday, June 18, 2014 12:47 PM
  • Hi

    I've just noticed that you have inputted a certain account/contact id in the query

    I need it to be able to work for every account/contact not just one

    Thanks, Shaun


    S.Harrison

    Wednesday, June 18, 2014 1:01 PM
  • Hi Shaun,

    You're right. You can iterate as follows:

    if (result1 !=null && result1.Entities.Count > 0)
    {
    	List<string> _addresses = new List<string>();
    	foreach (Entity _entity in result1.Entities)
    	{
    		_addresses.Add(_entity.Attributes["addressnumber"].ToString());
    	}
    }


    Admin QuikView Solution for CRM 2013

    Wednesday, June 18, 2014 1:03 PM
  • Hi Shaun,

    You can provide any contact/account Id and the code will fetch all addresses related to that contact/account. Now if you want to iterate through all contacts/accounts addresses; you'll need to first fetch all contact/account Ids and then fetch their addresses. Or if you want to fetch all addresses that existed for any contact/account, remove the filter criteria.


    Admin QuikView Solution for CRM 2013


    Wednesday, June 18, 2014 1:04 PM
  • Hi

    I'll try explaining again, I want any account/contact that is being worked on be able to retrieve their relate addresses

    I have already have access to a account code via the following

        varaccountCode = ((Microsoft.Xrm.Sdk.EntityReference)(accountCodePostImage.Attributes["accountid"]));

                

        varaccountID = service.Retrieve(accountCode.LogicalName, accountCode.Id, newColumnSet(true));

                   

        varactualID = accountID["new_accountcode"].ToString();

    Could I use instead of the following;

    condition1.Values.Add("A99D25C4-AFD5-E311-946F-D89D6765B134");

    Use;

    condition1.Values.Add(accountCode);

    Thanks, Shaun


    S.Harrison

    Wednesday, June 18, 2014 1:17 PM
  • Hi,

    Yes, you could directly query it using the account id you're retrieving using

    var accountCode = ((Microsoft.Xrm.Sdk.EntityReference)(accountCodePostImage.Attributes["accountid"]));
    
    condition1.Values.Add(accountCode);


    Admin QuikView Solution for CRM 2013


    Wednesday, June 18, 2014 1:27 PM
  • Hi,

    No, new_accountcode is only used in Accounts Entity, I have done the changes and all seems well so far

    However, the issue I have is that Visual Studio is saying that

    _serviceProxy does not exist in the current context

    And I'm struggling to find a solution

    Thanks, Shaun


    S.Harrison

    Wednesday, June 18, 2014 1:33 PM
  • Hi Shaun,

    Are you using the following line to create the service proxy?

    IPluginExecutionContext _serviceProxy = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));


    Admin QuikView Solution for CRM 2013

    Wednesday, June 18, 2014 1:43 PM
  • Hi,

    Ah right, yes I'm using that line however instead of _serviceProxy I have context.

    I have done the change, however now I have a error stating that

    Microsoft.Xrm.Sdk.IPluginExecutionContext does not contain a definition for 'RetrieveMultiple' and no extention method 'RetrieveMultiple' accepting a first argument of type  'Microsoft.Xrm.Sdk.IPluginExecutionContext  could not be found

    Thanks Shaun


    S.Harrison

    Wednesday, June 18, 2014 1:55 PM
  • Make sure you add the Microsoft.Xrm.Sdk.dll as reference to your project and have the following usings:

    using Microsoft.Xrm.Sdk;
    using Microsoft.Xrm.Sdk.Query;
    


    Admin QuikView Solution for CRM 2013

    Wednesday, June 18, 2014 2:03 PM
  • Hi

    Those are both also there

    Thanks, Shaun


    S.Harrison

    Wednesday, June 18, 2014 2:10 PM
  • Hi,

    Just to be clear the error is still there

    Thanks, Shaun


    S.Harrison

    Wednesday, June 18, 2014 2:58 PM
  • Hi,

    Try adding the "using Microsoft.Xrm.Sdk.Client;". Also did you double click on the RetrieveMultiple method? It generally adds the necessary using. Also make sure you've actually added the Microsoft.Xrm.Sdk.dll to your project reference by Right Click on Project > Add Reference > Browse for Microsoft.Xrm.Sdk.dll from the CRM SDK > OK


    Admin QuikView Solution for CRM 2013

    Wednesday, June 18, 2014 4:41 PM
  • Hi

    Client is already there, tried double clicking and nothing, and the .dll is already there

    Still error message showing

    Thanks, Shaun


    S.Harrison

    Thursday, June 19, 2014 7:46 AM
  • I have resolved the issue

    My code was as follows

    IPluginExecutionContext context = (IPluginExecutionContext)
                    serviceProvider.GetService(typeof(IPluginExecutionContext));
                          
                           
                IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
                IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
    

    I needed to declare service not context in the line

     EntityCollection result1 = context.RetrieveMultiple(query);

    It needed to be

     EntityCollection result1 = service.RetrieveMultiple(query);

    Thanks for all your help

    Shaun


    S.Harrison

    Thursday, June 19, 2014 8:36 AM
  • Another change for anyone who is wanting to do something similar was

    condition1.Values.Add(accountCode);

    This gave errors as the query was looking for an id and accountCode was providing a EntityReference

    the line was changed to

    condition1.Values.Add(accountID.Id);

    Everything now works as I wanted

    Thanks to everyone for their help


    S.Harrison

    Thursday, June 19, 2014 8:48 AM