1
votes

For some reason, the following function works:

public EntityCollection RetrieveMultipleByIds(IOrganizationService service, string entityLogicalName, string[] columnSet, string idFieldName, string[] guids)
{
    QueryExpression query = new QueryExpression(entityLogicalName);
    query.ColumnSet = new ColumnSet(columnSet);
    query.Criteria = new FilterExpression();
    query.Criteria.AddCondition(idFieldName, ConditionOperator.In, guids);
    EntityCollection entityCollection = service.RetrieveMultiple(query);
    return entityCollection;
}

But this one - using type parameter - doesn't work:

public EntityCollection RetrieveMultipleByIds<T>(IOrganizationService service, string entityLogicalName, string[] columnSet, string idFieldName, T[] guids)
{
     QueryExpression query = new QueryExpression(entityLogicalName);
     query.ColumnSet = new ColumnSet(columnSet);
     query.Criteria = new FilterExpression();
     query.Criteria.AddCondition(idFieldName, ConditionOperator.In, guids);
     EntityCollection entityCollection = service.RetrieveMultiple(query);
     return entityCollection;
}

Both are called in the same way (Note that the literal-string guid is just for this example, and you can be assured the id i'm passing exists):

EntityCollection entityCollection =  
RetrieveMultipleByIds("org_session", new string[] { "org_sessionname" }, "org_sessionid", new string[] {"73A5794E-1662-E711-80FF-005056B74623"});

And the exception thrown is:

The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter http://schemas.microsoft.com/xrm/2011/Contracts/Services:query. The InnerException message was 'Error in line 1 position 2826. Element 'http://schemas.microsoft.com/2003/10/Serialization/Arrays:anyType' contains data from a type that maps to the name 'System:String[]'. The deserializer has no knowledge of any type that maps to this name. Consider changing the implementation of the ResolveName method on your DataContractResolver to return a non-null value for name 'String[]' and namespace 'System'.'. Please see InnerException for more details.

I know there are similiar questions asking about this kind of exception, but none is related to using type parameters. If someone stumbled into the same issue and managed to find the problem and solve it, I'd be glad to hear about it.

2

2 Answers

3
votes

In query.Criteria.AddCondition(idFieldName, ConditionOperator.In, guids); argument guids cannot be a generic type. It's just a serialization issue. To go safe only arrays of type string or object should be allowed in the ConditionExpression.

1
votes

It is unclear what you are trying to accomplish by making the method generic.You are still passing an array of strings into your T[].

Since you are returning EntityCollection you can query any entity for a set of GUID's with the first version, just by passing a different entity logical name and id field.

If you want to use early bound with proxy classes, you could do something like this (please note this is untested this code):

public List<T> RetrieveMultipleByIds<T>(IOrganizationService service, string entityLogicalName, string[] columnSet, string idFieldName, string[] guids)
{
     QueryExpression query = new QueryExpression(entityLogicalName);
     query.ColumnSet = new ColumnSet(columnSet);
     query.Criteria = new FilterExpression();
     query.Criteria.AddCondition(idFieldName, ConditionOperator.In, guids);
     var entityCollection = service.RetrieveMultiple(query);
     return entityCollection.Select(e => e.ToEntity<T>()).ToList();
}

Then call it with:

List<Account> accounts = RetrieveMultipleByIds<Account>(svc, "account", new string[] { "name" }, "accountid", new string[] {"73A5794E-1662-E711-80FF-005056B74623"});