What are some of the things you would want to think about before you query and retrieve objects from the CMDB? Here are some of them,
a. How many objects are you expecting in the database for your criteria? How will the count affect your read performance?
b. Do you want your results sorted?
c. Do you want your results filtered by the source that created it?
d. Do you want all your objects returned or only the TOP N results?
e. Do you want all object properties returned or only some of them?
All Service Manager V1 APIs used for retrieving objects from the database take a parameter of type Microsoft.EnterpriseManagement.Common.ObjectQueryOptions. This class exposes several APIs that can be used to configure all of the above and more.
This is the first in a series of posts that I will be writing to go over each of the points above and see how we can use ObjectQueryOptions to achieve what we want.
Scenario 1: Large number of instances in the database; how to improve read performance
Suppose you have a large number of objects(1000+) in the CMDB that match your criteria; you may not want to or more importantly need to read the objects from the CMDB all at once, but instead retrieve only the first N objects and have the remaining objects load in the background (load on demand).
ObjectQueryOptions exposes a public property called ObjectRetrievalMode which is an enum that you can set. This property indicates whether you want the objects returned all at once (in a single batch) or in several small sized batches (aka pages)
/// specifies whether the object retrieval from
/// server should be buffered or not
public enum ObjectRetrievalOptions
/// does not buffer the data
/// buffers the data
NonBuffered – you get all your objects returned in one batch.
Buffered – you’ll get your objects returned in batches ( you can specify the size of the batches as well). The default batch size is 250
Lets take a look at an example of how we can actually get back objects from the CMDB in batches. In the example below I am querying for all of the objects of class Microsoft.Windows.Computer but accessing only the first object.
EnterpriseManagementGroup emg = new EnterpriseManagementGroup("sm-server");
ManagementPack mp = emg.ManagementPacks.GetManagementPack("Microsoft.Windows.Library", keyToken, new Version("7.5.1049.1");
ManagementPackClass computer = emg.EntityTypes.GetClass("Microsoft.Windows.Computer", mp);
ObjectQueryOptions queryOpt = new ObjectQueryOptions();
queryOpt.ObjectRetrievalMode = ObjectRetrievalOptions.Buffered;
IObjectReader<EnterpriseManagementObject> instanceReader = emg.EntityObjects.GetObjectReader<EnterpriseManagementObject>( computer, queryOpt);
// get the first object that matches the criteria
NOTE: In the above example, even though I am accessing only the first object, the reader internally retrieves a the first page of instances from the CMDB.i.e the reader always retrieves enough instances from the CMDB to fulfill a client request, but at a minimum it gets back a page of instances from the CMDB.
In SMv1, the buffered/ non-buffered mode of retrieval can be used for retrieving objects and projections. The APIs return either IObjectReader<EnterpriseManagementObject> or IObjectProjectionReader<EnterpriseManagementObject> depending on whether instances or projection were queried for.
The batch or page size is the number of objects retrieved from the database at a given time. It can be set using the property on IObjectReader<T> or IObjectProjectionReader<T>. The default page size is set to 250. It can be set to any acceptable value for an unsigned integer. If it is set to number greater than the actual number of instances matching a query, then only the available matching instances are brought back.
The instance and projection readers have many more powerful features that can be used to do a wide range of things to query for instances from the CMDB. I will cover all the remaining features in a separate blogpost.