Coding Tips
- Last UpdatedJun 10, 2024
- 4 minute read
Close the Client Object
-
The below code is used for executing a workflow.
string xmlcontent = "<Expense><Amount>2000</Amount></Expense>";
Client objClient = new Client("MyApps","MyWF");
try
{
int ExecutionID = objClient.Execute(Convert.ToInt32(Session["UserID"]), xmlcontent);
}
catch
{
//.....
}
finally
{
if (objClient != null)
{
objClient.Close();
}
}
It is mandatory to call the Close () method after the execute () method.
Dispose the Context object to avoid memory leaks
The Workflow.NET.Engine.Context class encapsulates all the information about the executing workflow. Usage of this class within other objects during workflow execution is required to access the executing workflow details. The Context object uses the Dispose (implementation of IDisposable interface) method to free up all the unmanaged resources. It is mandatory to call the Dispose method after usage of Context Object.
The sample codes shown below describes different scenarios for usage of Context object and the best practice of ensuring Disposal of context object by calling Dispose method. In some scenarios, calling Dispose on a different object takes care of Disposal of Context object used within that object as well.
The sample code below is used for disposing the context object:
Workflow.NET.Engine.Context workflowContext = Workflow.NET.Engine.Context.GetContext(17, "Spill Repo");
using (workflowContext)
{
Workflow.NET.VariablesCollection workflowVariables = workflowContext.Variables;
}
//Context gets disposed automatically since we use using block
or
Workflow.NET.Engine.Context workflowContext = Workflow.NET.Engine.Context.GetContext(17, "Spill Repo");
try
{
Workflow.NET.VariablesCollection workflowVariables = workflowContext.Variables;
//Do something
}
catch (Exception exception)
{
//Handle Exception.
}
finally
{
workflowContext.Dispose();
}
//Context is disposed explicitly
Mandatory to call Dispose of HWSActivity object
In HWSActivity object the Dispose method has to be called mandatorily as follows:
ApplicationObject appObject = new ApplicationObject("Telematics");
WorkflowObject workflowObject = new WorkflowObject("LeaveWF", appObject);
// Creating HWSActivity Object
HWSActivity hwsActivity = new HWSActivity(workflowObject, new
Guid("49e411e3-7487-4ad3-a4c7-40d88f5f75cf"));
try
{
String actionName = hwsActivity.CurrentActivity.ActionDisplayName;//do something
}
catch (Exception exception)
{
//Handle exception
Console.WriteLine("Error:" + exception.Message);
}
finally
{
hwsActivity.Dispose();
}
// HWSActivity object is disposed explicitly.
The Work Item object (Skelta.HWS.WorkItem) also uses the context object which has to be released; now we have the Dispose method exposed in the Work Item object.Mandatory to call Dispose of Work Item object
AVEVA Work Tasks Work Item List control is used to display all the activities for a user and from which the user can perform the tasks. User can also use the Work Item control in their custom application and load their Work Items. The Work Item object is largely used while building the Work Item detailed view, submitting or processing the Work Item etc.
Ensure that the Dispose method is called in the following format while using Work Item object in your code
ApplicationObject appObject = new ApplicationObject("Telematics");
WorkflowObject workflowObject = new WorkflowObject("LeaveWF", appObject);
//Creating Workitem object
WorkItem workItem = new WorkItem(workflowObject, new
Guid("dca38d4d-0c5d-4e3c-af98-77c5f2990709"));
try
{
Console.WriteLine("HWSActivity Name: " + workItem.HWSActivity.ActivityName);
//Do something
}
catch (Exception exception)
{
//Handle Exception
}
finally
{
workitem.Dispose();
}
//WorkItem object is disposed explicitly.
References to the WorkItem object through the WebWorkitemAdapter class may be present, where the Dispose method has been exposed.
Mandatory to call Dispose of WebWorkitemAdapter object
While using the WebWorkitemAdapter object (Skelta.HWS.WorkListChannel.Web. WebWorkitemAdapter), please ensure that the following format is followed to dispose the adapter object:
public WebWorkItemAdapter adapter;
try
{
adapter = new WebWorkItemAdapter();
adapter.ProcessWebChannelRequest();
_workitemSubject = adapter.CurrentWorkItem.Subject;
//Do something
}
catch(Exception exception)
{
//Handle Exception
}
finally
{
adapter.Dispose();
}
Note: If both HWSActivity and the Work Item object are used, disposing the HWSActivity object will dispose the current context object.
For example:
ApplicationObject appObject = new ApplicationObject("Telematics");
WorkflowObject workflowObject = new WorkflowObject("LeaveWF", appObject);
HWSActivity hwsActivity = new HWSActivity(workflowObject, new Guid("49e411e3-7487-4ad3-a4c7-40d88f5f75cf"));
Skelta.HWS.WorkItem workItem = new Skelta.HWS.WorkItem(hwsActivity);
try
{
workItem.Status = "Approved";
workItem.Save();
workItem.Submit("WebWorkList", "Approved", "","Approved @"+ DateTime.Now);
}
catch(Exception exception)
{
//Handle Exception
}
finally
{
hwsActivity.Dispose();
}
-
The below changes are required for culture compatibility
"".ToUpper() or "".ToLower() should not be used. Use "".ToUpperInvariant() or "".ToLowerInvariant() for string comparison.
Wrong :
string str = "windows";
if(str.ToUpper() == "WINDOWS"){ }
Correct:
string str = "windows";
if(str.ToUpperInvariant() == "WINDOWS"){ }
-
Script Activity should not be used for complicated tasks. Performance issues can occur if external DLLs are loaded and used. We recommend using custom activity in place of script activity, as there might be some memory related issues using script activity whenever a reference to an external dll is required.
-
Only use the common methods defined in common functions to get the transaction scope.
-
Workflow.NET.CommonFunctions.GetNewTransactionScope() [Joins a parent transaction if available, else executes in a new transaction].
-
Workflow.NET.CommonFunctions.GetRequiredNewTransactionScope() [Starts a new transaction]
-
Workflow.NET.CommonFunctions.GetSuppressedTransactionScope() [Suppresses the transaction for execution within the scope. Parent transaction is till valid.]
-
Skelta.Core.DS.SingleTableObject.GetTransactionScope()[Joins a transaction if available, else suppresses the transaction. Combination of GetNewTransactionScope && GetSuppressedTransactionScope]
-
-
To implement an impersonated database connection, implement the DB connection pooling at the AVEVA Work Tasks Level. Due to this change, you are required to follow a few standards while using data handlers inside transaction scope in a custom activity.
Keep the following points in mind:
-
Connection has to be disposed of in the transaction after use.
-
Make sure the data reader is closed after use.
-
Always complete the transaction.
Wrong:
Data handler is disposed of outside the transaction. A transaction which is initialized in the transaction should be disposed within the transaction scope.
try
{
using (TransactionScope TScope = Skelta.Core.DS.SingleTableObject.GetTransactionScope())
{
DBHandler = Workflow.NET.Storage.DataHandlerFactory.GetDataHandler(new Workflow.NET.Config(this.ApplicationName));
IDataParameter idp1 = DBHandler.GetParameter("@PreferredChannelName", preferredChannelName);
IDataParameter idp2 = DBHandler.GetParameter("@Id", this.Id);
IDataParameter idp3 = DBHandler.GetParameter("@LastUpdatedDateTime",DateTime.UtcNow);
DBHandler.ExecuteUpdate(sql, idp1, idp2, idp3);
TScope.Complete();
}
}
catch (Exception e)
{
throw e;
}
finally
{
if (DBHandler != null)
DBHandler.Dispose();
}
Correct:
try
{
using (TransactionScope TScope = Skelta.Core.DS.SingleTableObject.GetTransactionScope())
{
DBHandler = Workflow.NET.Storage.DataHandlerFactory.GetDataHandler(new Workflow.NET.Config(this.ApplicationName));
using (DBHandler)
{
IDataParameter idp1 = DBHandler.GetParameter("@PreferredChannelName", preferredChannelName);
IDataParameter idp2 = DBHandler.GetParameter("@Id", this.Id);
IDataParameter idp3 = DBHandler.GetParameter("@LastUpdatedDateTime", DateTime.UtcNow);
DBHandler.ExecuteUpdate(sql, idp1, idp2, idp3);
}
TScope.Complete();
}
}
catch (Exception e)
{
throw e;
}