How to generically iterate through associated SmartObjects
I was asked recently how one can load associated SmartObjects for a given SmO (SmartObject). I worked up the attached Console app as a quick example to provide guidance around this.
In my environment I have an the following SmartObjects:
- Order
o OrderID
o CustomerID
o ProductID
o Qty
o Price
- Customer
o CustomerID
o CustomerName
o Address
- Product
o ProductID
o ProductionName
I have setup the following associations within the Order Smo:
1. Customer SmO : Order.CustomerID -> Customer.CustomerID and
2. Product SmO : Order.ProductID -> Product.ProductID
I then created a simple console app that utilizes our API, to open up a specific Order, then determine what it’s associated with then open up those associated SmO. This is all done generically…. By that I mean nowhere in my code do you see me hard coding in knowledge that an Order is linked to a Customer or Product. My console app then simply spits all the data for each SmO back to console window in order to prove it’s working. NOTE: my code makes a few assumptions (like only one property makes up the primary key as well as the default Load method). With a little work it could be made flexible enough to be more robust.
Below is the majority of the code in case you don't feel like downloading the attachment:
private void GetSmartObject(string strSmoName, string strSmoID)
{
string _serverName = "localhost";
string _domain = "k2demo";
string _user = "administrator";
string _password = "k2pass";
SmartObjectClientServer serverName = new SmartObjectClientServer();
SourceCode.Hosting.Client.BaseAPI.SCConnectionStringBuilder connectionString = new SourceCode.Hosting.Client.BaseAPI.SCConnectionStringBuilder();
// build a connection string
connectionString.Authenticate = true;
connectionString.Host = _serverName;
connectionString.Integrated = true;
connectionString.IsPrimaryLogin = true;
connectionString.Port = 5555;
connectionString.UserID = _user;
connectionString.WindowsDomain = _domain;
connectionString.Password = _password;
connectionString.SecurityLabelName = "K2"; //the default label
// open a K2 Server connection
serverName.CreateConnection();
serverName.Connection.Open(connectionString.ToString());
try
{
// get a handle to the 'Employee' SmartObject
SmartObject smartObject = serverName.GetSmartObject(strSmoName);
// specify which method will be called
smartObject.MethodToExecute = "Load";
// specify input parameters for the method
smartObject.Properties[0].Value = strSmoID;
// call the method
smartObject = serverName.ExecuteScalar(smartObject);
// create a string to hold the data
string strRecord = "(*** " + strSmoName + " ***) ";
// iterate all the properties in the SmO and build out the string (which will eventually be displayed in console)
foreach(SmartProperty oProp in smartObject.Properties)
{
string strPropName = oProp.Name;
string strPropVal = oProp.Value;
strRecord += ", " + strPropName + ":" + strPropVal;
}
// write it to the console
Console.WriteLine(strRecord);
// now iterate any associated smartobjects we may have
foreach (Association oAssoc in smartObject.Associations)
{
// grab the name of the association
string strAssociationName = oAssoc.Name;
// grabe the name
string strAssociatedSmartObjectName = oAssoc.SoName;
// create an array to store all the properties that make the association
// (e.g. the keys of each SmO that make up the join)
ArrayList arAssociatedProperties = new ArrayList();
foreach(AssociatedProperty oAsPr in oAssoc.AssociatedProperties)
{
arAssociatedProperties.Add(oAsPr.Name);
}
// recursively call this same method to run through the association SmO
// NOTE: for this example i am assuming only one property in the key and association
// a real project handle an unknown number of properties
GetSmartObject(strAssociatedSmartObjectName, smartObject.Properties[arAssociatedProperties[0].ToString()].Value);
}
}
catch (Exception ex)
{
}
finally
{
// close the connection
serverName.Connection.Close();
}
}
Attachment(s): SmartObject Associations.zip