In my previous post I used a callable action list along with Xml Update Actions to read all of the database connection strings identified in an app.config file, then iterate and update each one of the databases during an application update. The approach I took to accomplish the goal only used built-in Update Actions that are available to me in the Actions Palette. I purposefully chose not to use dynamic code actions (custom update actions) to make a point of what we can accomplish without resorting to writing our own code. However, what can be accomplished with a little custom code is extremely powerful, so now I’m going to revisit the objective, removing the intent of relying only on built-in actions.
Identifying the Databases to Update
In this scenario, the local databases that need to be updated during our application update are listed in the application configuration file. This is very convenient, especially when I want to use built-in actions to find the information. But what if the databases were not so conveniently discoverable? What if you first had to connect to a database server and search through all of the databases on the server for a specific naming convention? What if the databases were passed into the update process from the host application? Using a dynamic code action, scenarios like this can be easily handled.
Custom Update Actions and Shared Properties
The feature duo that makes what might initially sound difficult to accomplish during an application update magically easy using AppLife Update are Custom Actions and Shared Properties. Custom Actions are simply classes that inherit from an UpdateAction base class and implements at a minimum, an Execute method and a Rollback method. Shared Properties are a collection of objects that are scoped to the context of the update and can be accessed from any update action.
For our purposes, we want a custom update action that will read the list of databases from an application configuration file. The C#/VB.NET Code action lets me write this custom action directly within the update creation software.
Note: Custom Actions can also be created in Visual Studio and compiled to an assembly. Custom Action assemblies can be added to an update project through the Project..Settings dialog, or added the Custom Actions folder located within the AppLife Update install directory.
Here is the code:
Code Snippet
1: using System;
2: using System.Collections.Generic;
3: using System.Text;
4: using Kjs.AppLife.Update.Engine.Core;
5: using System.Xml;
6: using System.IO;
7: namespace DynamicCodeActions {
8: public class DynamicAction1 : UpdateAction {
9: public override void Execute(UpdateContext context) {
10: //Read connection strings from app.config
11: XmlDocument configDoc = new XmlDocument();
12: configDoc.Load(Path.Combine(context.ApplicationDirectory, "CallActionListExample.exe.config"));
13: XmlNodeList connStrings = configDoc.SelectNodes("/configuration/connectionStrings/*");
14: List<string> connectionStrings = new List<string>();
15: foreach(XmlNode node in connStrings) {
16: connectionStrings.Add(node.Attributes["connectionString"].Value);
17: context.Log.WriteLine(string.Format("Added connStr: {0}", node.Attributes["connectionString"].Value));
18: }
19: if(connectionStrings.Count > 0) {
20: context.SharedProperties.Add("ConnectionStrings", connectionStrings);
21: context.SharedProperties.Add("ExecuteDBUpdate", true);
22: context.SharedProperties.Add("CurrentConnectionString", "");
23: } else {
24: context.SharedProperties.Add("ExecuteDBUpdate", false);
25: }
26: }
27: public override void RollbackExecute(UpdateContext context) {
28: //Add code here to undo work that was performed in the Execute
29: //method. The method is not performed if the Execute method
30: //is not completed.
31: context.SharedProperties.Remove("ConnectionStrings");
32: context.SharedProperties.Remove("ExecuteDBUpdate");
33: }
34: }
35: }
Notice that through the context parameter, the code can access the Shared Properties collection as well as other properties, such as the physical path to the host application. This code simply opens the application configuration file and reads the database connection strings. These strings are then added to a generic List of strings, and that List is added to the Shared Properties collection. If the list is not empty, another Shared Property is added that will be used in a conditional statement.
Manipulating the List from other Actions
With the list of database connection strings in the Shared Properties collection, we can call the recursive callable update action list to update the databases. This in-memory list takes the place of the copied app.config file used in the original post. From within the Update Databases action list, we can read and manipulate the Shared Properties collection with other custom update actions.
Read the Next Connection String
Remove the Item after the Database is Updated
Conclusion
Using Update Actions and Shared Properties during an application update allows you to very easily accomplish complicated processing on deployed clients. The C# / VB.NET update action lets you add your own code logic to your update, and using Shared Properties, your code can easily interact with built-in actions as well as other custom actions.