Retrieving Tag Metadata
- Last UpdatedAug 21, 2026
- 5 minute read
If some tag name is already known, its tag metadata instance can be retrieved from the Historian server by the GetTagInfoByName() method of the HistorianAccess class. See Reusing Existing Historian Server Tags for details.
In other cases, it might be necessary to find out which tag names and associated metadata are already known to the server.
To retrieve tag metadata for multiple tags from the server, it is necessary to have a physical connection to it. You can ensure that by checking the ConnectedToServer property of the HistorianConnectionStatus.
To retrieve tag name and metadata
- Create an instance of the TagQuery class.
- Create an instance of the TagQueryArgs class and provide the tag filter. If all tags are required to be returned, then the tag filter string should remain empty.
- Start the tag query using the TagQuery.StartQuery() method, which will return the number of tags passed the filter into its second argument.
- If you need just the tag names, then call the TagQuery.GetTagNames() to fetch tag names from the tags passed the filter. You must provide a zero-based index of the first passed tag, and then the number of tag names to be returned. You can call GetTagNames() multiple times within the same tag query to get different intervals of tag names
If you need full tag metadata, then instead of TagQuery.GetTagNames(), use TagQuery.GetTagInfo(). This will return a required portion of HistorianTag instances from the tags passed the filter. You can call GetTagInfo() multiple times within the same tag query to get different intervals of tag metadata. - End the tag query by calling the TagQuery.EndQuery() method to release immediately all resources allocated by the tag query object.
The following example shows retrieving all tag names of the Historian server. To do that, the GetTagNames() call in the example requests tagCount tag names starting from index 0. The tag names will be returned in the lexicographical order. This approach allows just a subsequence of the whole lexicographically ordered tag list to be returned, which can be useful for display in some user interface element of limited capacity.
Example
HistorianAccessError error;
TagQueryArgs tagQueryArgs = new TagQueryArgs();
TagQuery tagQuery = historian.CreateTagQuery();
uint tagCount;
if (!tagQuery.StartQuery(tagQueryArgs, out tagCount, out error))
{
Console.WriteLine(“Failed to start tag query: {0}”, error.ErrorDescription);
}
else
{
StringCollection tagNames;
if (!tagQuery.GetTagNames(0, tagCount, out tagNames, out error))
{
Console.WriteLine(“Failed to get tag names: {0}”, error.ErrorDescription);
}
else
{
foreach (string tagName in tagNames)
Console.WriteLine(“TagName = {0}”, tagName);
}
if (!tagQuery.EndQuery(out error))
{
Console.WriteLine(“Failed to end query: {0}”, error.ErrorDescription);
}
}
The next example shows retrieval of tag metadata instances for the first 10 tags:
Example
HistorianTagList tagInfoList;
if (!tagQuery.GetTagInfo(0, 10, out tagInfoList, out error))
{
Console.WriteLine(“Failed to get tag info: {0}”, error.ErrorDescription);
}
else
{
foreach (HistorianTag tag in tagInfoList)
Console.WriteLine(“TagName = {0}, TagType = {1}”, tag.TagName, tag.TagDataType);
}
Transferring large numbers of tag metadata instances may take some time, so it is recommended to perform several calls to GetTagInfo() will smaller tag counts to improve the responsiveness of your application.
TagQueryArgs Class
The TagQueryArgs class has two public properties:
- TagFilter of type string, empty by default
- CacheTagInfo of type bool, false by default
TagFilter Propertry
The TagQueryArgs.TagFilter property can be contain an ODATA-compliant filter on any of tag properties. That filter will be applied on the server side to transfer only tag names or tag metadata instances which have passed the filter.
For example the following filter limits the tag retrieval to onlu those tags with names that start with "Sys":
Example
tagQueryArgs.TagFilter = ″startswith(TagName, ′Sys′)″;
The filter string can include logical and arithmetic operations such as in the next example. This example returns all system tags having descriptions shorter than 20 characters. See the ODATA filter specification for details.
Example
tagQueryArgs.TagFilter = ″startswith(TagName, ′Sys′) and (length(Description) lt (19 add 1))″;
Note that the standard ODATA string functions are case-sensistive, so you might need to use toupper() or tolower() functions in your filters if you need case-insensitive retrieval, such as in the following example:
Example
tagQueryArgs.TagFilter = ″substringof('ITEM', toupper(TagName))″;
Instead of calling toupper(), you can use the following case-insensitive custom versions of ODATA string functions: cistartwith(), ciendswith(), and cisubstringof(). Those case-insensitive functions are not the part of the ODATA standard and cannot be used outside of the TagFilter property.
The tag query reflects the state of the Tag table at the moment of the StartQuery() call. If there were any new tags created after that call, those new tags will remain invisible for the query. In that case, you need to call TagQuery.EndQuery() and start another query to include those newly created tags.
It is important to always call TagQuery.EndQuery() when the tag query is no longer needed. This releases the resources allocated by the server for the query.
CacheTagInfo Property
The TagQueryArgs.CacheTagInfo property can be set to true to request all TagQuery.GetTagInfo() calls within that tag query to cache transmitted tag metadata in the internal HCAL cache and create a valid tag key for every tag metadata instance.
If the TagQueryArgs.CacheTagInfo property is false, then all tag metadata instances returned by the TagQuery.GetTagInfo() will have zero tag keys.
Keeping TagQueryArgs.CacheTagInfo set to false is recommended if the SDK application just needs to examine tags and their properties without any intent to store any data for those tags. It makes sense if the Historian server has so many tags that all that tag metadata would require too much memory to be consumed by the SDK application.
Setting TagQueryArgs.CacheTagInfo to true can be used when the SDK application intends to store data for those tags. That way the TagQuery.GetTagInfo() call will produce the result identical to multiple calls of the HistorianAccess.GetTagInfoByName() method
Tag Ownership
Methods HistorianAccess.GetTagInfoByName() and TagQuery.GetTagInfo() called for tag query of CacheTagInfo = true do not transfer the tag ownership to the SDK application. For example, if it there is a tag receiving data from a remote IDAS, then that tag is an IDAS tag and it is owned by the Historian. Only the Historian-controlled IDAS is allowed[1] to send streamed data to that tag. The SDK application can get tag metadata using those methods and use the returned tag key to store original non-streamed and revision data for that tag being owned by the Historian. In that case the tag will remain in the Historian’s ownership.
If, however, the SDK application calls HistorianAccess.AddTag() for that tag metadata object it will transfer the tag ownership to itself and receive another tag key to be used instead of the original one. The tag will be reconfigured to become a manual tag and original streamed data will not be collected from the IDAS for that tag anymore.
To sum up, we can say that:
- HistorianAccess.GetTagInfoByName() and TagQuery.GetTagInfo() with CacheTagInfo = true return tag keys, which you can use to store data, but the tag ownership does not get transferred to the SDK application.
- HistorianAccess.AddTag() returns the tag key and transfers the tag ownership to the SDK application.
[1]The SDK application can ignore that rule and send original streamed data to an IDAS tag, but the users of the application must be aware that the live data, replication, and subsequent retrieval may produce a result mixed from multiple data sources.