Sunday, February 8, 2009

Dynamic Entity and Entity query helper methods

If you do much MS CRM development you will find that you are constantly querying for things. These are a couple helper methods that I have found come in handy.

There are some subtle differences between them.

Querying for Collections

The following 2 methods retrieve any entity, filtering on any attribute(s), ordering on any attribute(s), and returning any number of specified attributes. The only real restraint is that they are hard coded to anding the filters together and only comparing filters with an Equal condition operator.

BusinessEntityCollection opportunityCollection = webservicehelper.GetAllEntitieswithFiltersOrdered(
EntityName.opportunity.ToString(),
new[]  "opportunityid", "name", "statecode" }, 
new[] { "customerid","statecode" },
new[] { thisAccount.accountid.Value.ToString(),"Open" },
new[] {"createdon"},
new[] {false});

BusinessEntityCollection opportunityCollection
= PluginHelper.GetDynamicEntitiesWithFiltersOrdered( EntityName.opportunity.ToString(),
new[] { "opportunityid", "name", "statecode" },
new[] { "customerid" },
new[] { accountId.ToString() },
new[] {"createdon"},
new[] {false}, 
service);

The following Helper methods do the exact same thing for strongly typed entities and then dynamic entities. They both return a BusinessEntityCollection but notice the differences in how they are implemented.

The first is for the strongly typed Entity.

public BusinessEntityCollection GetAllEntitieswithFiltersOrdered(string entity, string[] attributes, string[] fields, string[] values, string[] orderfields, bool[] orderAscending)
{

    var cols = new ColumnSet { Attributes = attributes };

    var conditions = new ConditionExpression[fields.Length];

    for (int i = 0; i < fields.Length; i++)
    {
        var condition = new ConditionExpression
        {
            AttributeName = fields[i],
            Operator = ConditionOperator.Equal,
            Values = new[] { values[i] }
        };

        conditions[i] = condition;
    }

    var filter = new FilterExpression
    {
        FilterOperator = LogicalOperator.And,
        Conditions = conditions
    };

    var orderArray = new OrderExpression[orderfields.Length];

    for (int i = 0; i < orderfields.Length; i++)
    {
        var thisOrder = new OrderExpression
        {
            AttributeName = orderfields[i],
            OrderType = (orderAscending[i] ? OrderType.Ascending : OrderType.Descending)
        };

        orderArray[i] = thisOrder;
    }


    var query = new QueryExpression
    {
        EntityName = entity,
        ColumnSet = cols,
        Criteria = filter,
        Orders = orderArray
    };

    try
    {
        return service.RetrieveMultiple(query);
    }

    catch (SoapException ex)
        var thisOrder = new OrderExpression
        {
            AttributeName = orderfields[i],
            OrderType = (orderAscending[i] ? OrderType.Ascending : OrderType.Descending)
        };

        orderArray[i] = thisOrder;
    }


    var query = new QueryExpression
    {
        EntityName = entity,
        ColumnSet = cols,
        Criteria = filter,
        Orders = orderArray
    };

    try
    {
        return service.RetrieveMultiple(query);
    }

    catch (SoapException ex)
    {
        emailNotifications.sendExceptionMessage(service.Url, " - GetAllEntitieswithFiltersOrdered FAILED:", errorEmails, ex,
            "<br/><br/>Entity: " + query.EntityName);
        throw;
    }
}
    {
        emailNotifications.sendExceptionMessage(service.Url, " - GetAllEntitieswithFiltersOrdered FAILED:", errorEmails, ex,
            "<br/><br/>Entity: " + query.EntityName);
        throw;
    }
}

The second is for a Dynamic Entity in a Plug-in.

public static BusinessEntityCollection GetDynamicEntitiesWithFiltersOrdered(string entityName, string[] attributes, string[] fields, string[] values, string[] orderfields, bool[] orderAscending, ICrmService serv)
{
    try
    {
        var filters = new FilterExpression { FilterOperator = LogicalOperator.And };

        for (int i = 0; i < fields.Length; i++)
        {
            var condition = new ConditionExpression
            {
                AttributeName = fields[i],
                Operator = ConditionOperator.Equal,
                Values = new[] { values[i] }
            };

            filters.Conditions.Add(condition);
        }
        
        var query = new QueryExpression
        {
            EntityName = entityName,
            ColumnSet = new ColumnSet(attributes),
            Criteria = filters
        };

        for (int i = 0; i < fields.Length; i++)
        {
            var oneExpression = new OrderExpression
                 {
                     AttributeName = orderfields[i],
                     OrderType = (orderAscending[i] ? OrderType.Ascending : OrderType.Descending)
                 };

            query.Orders.Add(oneExpression);
        }

        var retrieve = new RetrieveMultipleRequest { Query = query, ReturnDynamicEntities = true };

        var retrieved = (RetrieveMultipleResponse)serv.Execute(retrieve);

        return retrieved.BusinessEntityCollection;
    }

    catch (SoapException ex)
    {
        throw new InvalidPluginExecutionException(
             String.Format("An error occurred in GetDynamicEntitiesWithFilters plug-in. {0}", ex.Detail.InnerText), ex);
    }

    catch (Exception ex)
    {
        throw new InvalidPluginExecutionException(
           String.Format("An error occurred in GetDynamicEntitiesWithFilters plug-in. {0} - trace - {1} -  source - {2}", ex.Message, ex.StackTrace, ex.Source), ex);
    }
}

One of the largest differences between querying for these two types of collections is that you are assigning a complete arrays in one and adding to the other.

No comments: