I'm attempting to write a script that will check a number of tables within a service for a match to the service's filter (Only ever 1 filter per table, but filters may contain wildcards).
As of now I iterate through each child element (Finding the related Protocol), then iterate through each filter within the child element, then for each filter I lookup the table using Protocol.FindAssociatedTableParameter, then lookup the DisplayKey (or PrimaryKey) using Protocol.FindAssociatedDisplayKeyColumn (or ...PrimaryKeyColumn), then I use Column.Lookup() to lookup the filter on the Display or Primary Key column for one or more matches.
This is not working because most of the filters are for DisplayKeys and I cannot figure out how to find a DisplayKey when given a table. I see the general rule is Table ID + 2, but this is not always the case (Specifically with Cisco DCM which is one of the elements this is intended to be used with).
After digging I've noticed that protocol.FindAssociatedDisplayKeyColumn(tableID), will typically return the Primary Key and not the Display Key (Except in the case of Cisco DCM). Digging into the Protocols, it seems that most Display Keys are not marked as Display Keys (Specifically I checked are TAG Media Control System and TechEx MWCore).
Is there any way to consistently return the Display Key?
Here is the function in its current state (Which incorrectly fails to find DisplayKeys in 99% of situations):
private string CheckService(IDmsService dmsService)
{
List<string> missing = new List<string>();Service service = engine.FindService(dmsService.AgentId, dmsService.Id);
ServiceInfoParams[] elements = service.ServiceInfo.ServiceParams;if (elements == null)
{
return "No children";
}
foreach (var childElement in elements)
{
// Connect to child Element & Protocol
IDmsElement element = dms.GetElement(new DmsElementId(childElement.DataMinerID, childElement.ElementID));
var protocol = engine.FindElement(childElement.DataMinerID, childElement.ElementID).Protocol;HashSet<int> seenTables = new HashSet<int>();
ServiceParamFilter[] filters = childElement.ParameterFilters;foreach (ServiceParamFilter filter in filters)
{
// Get info about filter Parameter from Protocol
var paramInfo = protocol.FindParameter(filter.ParameterID);
var tableInfo = protocol.FindAssociatedTableParameter(filter.ParameterID);
if (tableInfo == null || seenTables.Contains(tableInfo.ID))
{
// Is not a table OR already seen
continue;
}seenTables.Add(tableInfo.ID);
if (string.IsNullOrEmpty(filter.FilterValue))
{
// Table has no filter
missing.Add($"{childElement.Alias}.{tableInfo.Name}");
continue;
}// Get Index column based on FilterType (Display Key vs Primary Key)
var indexKey = (int)filter.FilterType == DisplayFilter ? protocol.FindAssociatedDisplayKeyColumn(tableInfo) : protocol.FindAssociatedPrimaryKeyColumn(tableInfo);
var column = element.GetTable(tableInfo.ID).GetColumn<string>(indexKey.ID);// Lookup rows matching the given filter
string[] rows = column.Lookup(filter.FilterValue);
//engine.GenerateInformation($"FOUND {rows.Length} ROWS for {childElement.Alias}.{tableInfo.Name} ({paramInfo.Name}) [{tableInfo.ID}/{indexKey.ID}/{indexKey.Name}] = {filter.FilterValue}");
if (rows.Length < 1)
{
// No rows found
missing.Add($"{childElement.Alias}.{tableInfo.Name}");
}
// Otherwise this table is good to go!
}
}return missing.Count != 0 ? $"Missing...\n - {string.Join("\n - ", missing)}" : "OK";
}
Also any advice on how to improve the performance is recommended, such as where bottlenecks are so I can implement caching.