By Wayne Brill
When using the Vault API to access the server you can improve performance by not having server calls inside a loop. Below is a code snippet that is using GetPropertyValue and GetFoldersByIds in a loop. (highlighted lines). In this example if there are 1,000 files in myResults, there will be 1,000 server calls. With network latency, there is just not a good way to make 1,000 server calls very quickly.
foreach (File myFile in myResults)
{
VDF.Vault.Currency.Entities.FileIteration fileIter = new VDF.Vault.Currency.Entities.FileIteration(base.VaultConnection, myFile);
EntityStatusImageInfo statusInfo = base.VaultConnection.PropertyManager.GetPropertyValue(fileIter, statusProp, null) as EntityStatusImageInfo;
MYVaultFileStatus myVltFileStatus = new MYVaultFileStatus(myFile.Name);
myVltFileStatus.VaultStatusText = statusInfo.Description;
myVltFileStatus.VaultStatusImage = statusInfo.GetImage();
long folderID = myFile.FolderId;
var folderFoundIn = base.VaultConnection.FolderManager.GetFoldersByIds(new long[] { folderID });
VDF.Vault.Currency.Entities.Folder folderOfFile;
folderFoundIn.TryGetValue(folderID, out folderOfFile);
myVltFileStatus.VaultPath = folderOfFile.FolderPath;
myVltFileStatus.VaultFileID = myFile.Id;
listDocumentStatus.Add(myVltFileStatus);
}
A better approach is to use web service calls that allow you to retrieve properties for a group or batch of files with a single call to the server. These methods typically accept an array of IDs or proxy objects so that you can retrieve a large collection of values with a single call.
The PropertyManager GetPropertyValues is nearly identical to GetPropertyValue except that it takes an array of entities and property definitions and retrieves all the property values at once with a single server call. This is what “using batch API methods as a best practice” means.
Here is an update to the example code with just two calls to the server:
// batch up entities to retrieve properties for
List<VDF.Vault.Currency.Entities.FileIteration> fileIterations =
new List<VDF.Vault.Currency.Entities.FileIteration>(myResults.Select(result => new VDF.Vault.Currency.Entities.FileIteration(base.VaultConnection, result)));
// make a single call to get property values
VDF.Vault.Currency.Properties.PropertyValues propValues = base.VaultConnection.PropertyManager.GetPropertyValues(fileIterations, new VDF.Vault.Currency.Properties.PropertyDefinition[] { statusProp }, null);
// make a single call to get parent folders
IDictionary<long, VDF.Vault.Currency.Entities.Folder> folderIdsToFolderEntities = base.VaultConnection.FolderManager.GetFoldersByIds(fileIterations.Select(file => myFile.FolderId));
// individually process results returned from the server
foreach (VDF.Vault.Currency.Entities.IEntity fileIteration in fileIterations)
{
VDF.Vault.Currency.Properties.EntityStatusImageInfo statusInfo = propValues.GetValue(fileIteration, statusProp) as VDF.Vault.Currency.Properties.EntityStatusImageInfo;
MYVaultFileStatus myVltFileStatus = new MYVaultFileStatus(fileIteration.EntityName);
stVltFileStatus.VaultStatusText = statusInfo.Description;
stVltFileStatus.VaultStatusImage = statusInfo.GetImage();
VDF.Vault.Currency.Entities.Folder folderOfFile;
if (folderIdsToFolderEntities.TryGetValue(fileIteration.FolderId, out folderOfFile))
{
stVltFileStatus.VaultPath = folderOfFile.FolderPath;
}
stVltFileStatus.VaultFileID = fileIteration.EntityIterationId;
listDocumentStatus.Add(stVltFileStatus);
}
The key is that the calls to the server have been moved outside the loop.