In my last post I discussed how key-value pair data can be used to store configuration-related items in Microsoft Dynamics CRM, and I also showed a design for an entity to store key-value pair data. In today's post I will show how to retrieve and consume the data inside a workflow using a custom workflow activity.
The Key-Value Pair entity
As I mentioned previously, I have a custom entity called Key-Value Pair (new_keyvaluepair) that stores the key in the name field (new_name), and it has the following custom fields to store value data:
- String value (new_stringvalue)
- Decimal value (new_decimalvalue)
- Integer value (new_integervalue)
- Date value (new_datevalue)
The custom workflow activity
I’ve created a custom workflow called GetKeyValue that takes the key name as an input parameter, and it returns all four value fields as output parameters. I would prefer to not have to return all the value fields, but because Dynamics CRM doesn't have a way to consume an output parameter with an object data type, that won't work.
Here are how the parameters are set up in code:
[Input("Key name")]
public InArgument<string> KeyName { get; set; }
[Output("String value")]
public OutArgument<string> StringValue { get; set; }
[Output("Integer value")]
public OutArgument<Int32> IntegerValue { get; set; }
[Output("Decimal value")]
public OutArgument<decimal> DecimalValue { get; set; }
[Output("Date value")]
public OutArgument<DateTime> DateValue { get; set; }
Because we're just doing a simple lookup on the entity name, I've chosen to use a CRM QueryExpression, but you could just as easily use FetchXML or Linq instead if you'd prefer. Here's the code that retrieves the key-value record:
try
{
string keyName = KeyName.Get(executionContext);
//look up team template by name
QueryByAttribute querybyexpression = new QueryByAttribute("new\_keyvaluepair");
querybyexpression.ColumnSet = new ColumnSet("new\_name",
"new\_stringvalue",
"new\_decimalvalue",
"new\_integervalue",
"new\_datevalue",
"new\_valuetype"
);
querybyexpression.Attributes.AddRange("new\_name");
querybyexpression.Values.AddRange(keyName);
EntityCollection retrieved = service.RetrieveMultiple(querybyexpression);
//if we find something, we're set
if (retrieved.Entities.Count > 0)
{
Entity kvp = retrieved.Entities[0];
StringValue.Set(executionContext, (string)kvp["new\_stringvalue"]);
IntegerValue.Set(executionContext, (int)kvp["new\_integervalue"]);
DecimalValue.Set(executionContext, (decimal)kvp["new\_decimalvalue"]);
DateValue.Set(executionContext, (DateTime)kvp["new\_datevalue"]);
}
else
{
//throw exception if unable to find a matching template
throw new Exception("could not find key-value pair for: " + keyName);
}
}
Although this example is focused on use in a workflow, you could use this custom workflow activity in a Dynamics CRM action process, or you could use the same business logic inside a plug-in. Full code for this post is available here.
How do you manage and consume data like this in your Dynamics CRM deployments? Does this approach look like it would be something worth using? Please share your thoughts in the comments!
A version of this post was originally published on the HP Enterprise Services Application Services blog.