A fast way to access an object is to use its object identifier. This kind of retrieval is only possible for well-known objects that your application expects to find, such as a container (that is, folder or package) object that is the root of a container hierarchy.
Using Relationships to Fetch Objects
If a given set of objects is usually loaded together, it is helpful to have a relationship collection that points to those objects. If you access the objects through that collection, the engine will load them in one round trip.
Think twice before navigating to a collection that contains only one or two objects of interest. Navigating to the collection loads the entire collection. Instead, try to find another way to navigate to those objects. ExecuteQuery to fetch objects provides one such alternative.
Collection Loading Hints
When loading or exporting objects, specify the maximum number of objects in each collection. This is an effective way to allow the repository engine to preload all the object collections for each repository object.
You can also set the IReposOptions OPT_PRELOAD_COL_MODE and OPT_EXPORT_MODE options to preload objects in a collection. For more information about option values and descriptions, see IReposOptions Options Table.
Using ExecuteQuery to Fetch Objects
When you know the exact set of objects you want, IRepositoryODBC::ExecuteQuery is often a faster way to find the objects than navigating to them by way of collections, because it usually requires many fewer round trips. For convenience, consider writing some view definitions to insulate application programmers from the complexity of the relationship table (RTblRelationships) and type definitions (for example, those stored in RTblClassDefs and RTblIfaceDefs). If the query-update ratio warrants it, consider adding indexes to the repository SQL interface tables (the ones to which the properties associated with that interface are mapped).
ExecuteQuery can be run asynchronously, in which case the call returns immediately. Later, you use IObjectCol2 to determine whether the collection that is being loaded is ready to read.
You can use ExecuteQuery to explicitly tell the repository engine to prefetch certain objects. However, in addition to calling ExecuteQuery for at least one object in the ObjectCollection that the query returns, you must access a property on each interface you want to access. This tells the engine to prefetch the properties on those interfaces for all the objects in the collection. As an aside, the engine flushes all updates to the database before running ExecuteQuery, so the query is reading exactly the current database state.
Using Named Relationships to Fetch Objects
If an object has the same name in all contexts, make sure its class supports INamedObject. This makes it more efficient to fetch the name. That is, the engine fetches the name from INamedObject::Name instead of a name from any of the incoming relationships. Note that an update of the name causes an update to all naming relationships pointing to the name.
If an object supports INamedObject, the most efficient way to set the Name property on the object only (and not on any of its incoming relationships) is to explicitly QueryInterface for INamedObject and set its Name property. For example:
Dim oReposObj as RepositoryObject Set oReposObj.Interface("INamedObject").Name = "Any Name"
Note that since the names of the relationships to the object are not updated here, you cannot later fetch by name from the collection. Rather, you have to enumerate the collection and check each object's name. Also note that the property Name corresponds to the dispatch ID DISPID_ObjName (not DISPID_Name).
It is more efficient to follow a relationship in the origin-to-destination direction than vice versa. This is because the physical representation of relationships in the relationship table is biased in this direction. So, traverse relationships in this direction whenever you have a choice.