Please ensure Javascript is enabled for purposes of website accessibility
Powered by Zoomin Software. For more details please contactZoomin

AF SDK Reference

AFDataCache Class

  • Last UpdatedNov 18, 2025
  • 13 minute read
AFDataCache Class
An AFDataCache manages a collection of AFAttributes via cache enabled AFData objects and will can automatically monitor for new data changes.

Inheritance Hierarchy

SystemObject
  OSIsoft.AF.DataAFDataCache

Namespace:  OSIsoft.AF.Data
Assembly:  OSIsoft.AFSDK (in OSIsoft.AFSDK.dll) Version: 3.1.1.1182

Syntax

public sealed class AFDataCache : IDisposable, 
	IAFDataProvider
Public NotInheritable Class AFDataCache
	Implements IDisposable, IAFDataProvider

Dim instance As AFDataCache
public ref class AFDataCache sealed : IDisposable, 
	IAFDataProvider
[<SealedAttribute>]
type AFDataCache =  
    class
        interface IDisposable
        interface IAFDataProvider
    end

The AFDataCache type exposes the following members.

Constructors

  NameDescription
Public method
AFDataCache
Create new instance of AFDataCache.
Public method
AFDataCache(Int32)
Create new instance of AFDataCache with a initial capacity set.

Properties

  NameDescription
Public property
Attributes
The list of AFAttribute items being cached.c
Public property
CacheHitCount
Returns the total number of data calls that retrieved data from the cache since the counter was reset.
Public property
CacheTimeSpan
The minimum amount of time series data to be kept for each AFAttribute in the cache, as measured by time span.
Public property
DataPipeStatistics
Contains statistics for the most recent signup or event scan for attributes updated by data pipe.
Public property
EventHorizonMode
EventHorizonMode specifies what events are returned by the datapipe at the GetUpdateEvent call based on the timestamp of the events.
Public property
EventHorizonOffset
EventHorizonOffset allows the pipe to return events in the future. The pipe would fetch events with timestamps up to current time + EventHorizonOffset when calling the GetUpdateEvents/GetObserverEvents methods
Public property
EventsCached
The total number of events currently in the cache.
Public property
EventsProcessed
The total number of events that have passed through the cache since the counter was reset.
Public property
IsSuspendedSignupEnabled
If IsSuspendedSignupEnabled is set, the data pipe will suspend signups that are currently invalid but might become valid with changes outside of AF.
Public property
MaxCacheEventsPerAttribute
The maximum number of cache events to be kept for each AFAttribute in the cache.
Public property
MinCacheEventsPerAttribute
The minimum number of cache events to be kept for each AFAttribute in the cache.
Public property
MissedHitCount
The total number of data calls that did not get data from the cache.
Public property
PIServers
Get the list of PIServer that could provide data update for the attributes in the cache via DataPipe option.

Methods

  NameDescription
Public method
Add
Adds a list of AFAttribute objects to be managed by AFDataCache. The AFAttributes are reference counted. Adding AFAttribute that is already in the AFDataCache will increment the reference count and not generate error. Adding the same AFAttribute multiple times will require the same number of Remove call to actually remove the AFAttribute from the AFDataCache.
Public method
Dispose
Release all the resources associated with this AFDataCache, including the AFDataPipe used to populate the cached data.
Public method
Equals
Determines whether the specified object is equal to the current object.
(Inherited from Object.)
Public method
GetDataPipeItemsByPIServer
Get the list of the AFAttribute objects managed by AFDataCache with DataPipe that get data from the passed PIServer.
Public method
GetHashCode
Serves as the default hash function.
(Inherited from Object.)
Public method
GetItemUpdateOption
Returns the AFDataCacheUpdateOption for an AFAttribute managed by this AFDataCache
Public method
GetRelatedAttributes
For each AFChangeInfo, finds the subscribed AFAttributes that might be impacted by the change.
Public method
GetType
Gets the Type of the current instance.
(Inherited from Object.)
Public method
ObservePendingChanges
Observes a set of changes from the server and prepares to update the AFDataPipe to reflect them.
Public method
ProcessAppliedChanges
Updates the AFDataPipe to reflect previously observed changes.
Public method
Remove
Remove a list of AFAttribute objects from the data cache.
Public method
ResetCounters
Reset AFDataCache statistic counters.
Public method
Subscribe
Register an IObserver to receive AFDataPipeEvents that are a result of the internal AFDataPipe used within the data cache for auto-monitored attributes.
Public method
ToString
Returns a string that represents the current object.
(Inherited from Object.)
Public method
TrimData(AFAttribute, AFTime)
Trims any cached data for the AFAttribute at or before the specified AFTime.
Public method
TrimData(AFAttribute, AFTime, Int32)
Trims cached data for the AFAttribute while maintaining coverage for events from a specified time.
Public method
TryGetItem
Returns the cache enabled AFData object for a given AFAttribute.
Public method
UpdateData
Update the time series cache for the attributes managed by this AFDataCache.
Public method
UpdateData(Boolean)
Update the time series cache for the attributes managed by this AFDataCache.
Public method
UpdateData(AFTime)
Update the time series cache for the attributes managed by this AFDataCache.
Public method
UpdateData(AFTime, Boolean)
Update the time series cache for the attributes managed by this AFDataCache.
Public method
WriteToCache(AFAttribute, IListAFValue)
Initialize the data cache of the AFAttribute with passed values. The AFAttribute must already be added to the AFDataCache with Manual or ManualRange.
Public method
WriteToCache(AFValue, AFUpdateOption)
Writes value to the data cache. The AFAttribute property of the passed AFValue is the key to lookup the data cache. This AFAttribute must already be added to the AFDataCache with Manual or ManualRange.

Remarks

An AFDataCache manages a collection of AFAttributes via cache enabled AFData objects. To enable run time event caching for a list of AFAttributes, call the Add method and passed the list of AFAttributes. AFDataCache will generate and return the corresponding list of cached enabled AFData. Be default, AFDataCache uses AFDataPipe to populate the run time events in the cache. As a result, AFAttributes monitored by the AFDataCache must support AFDataPipe. The use of AFDataPipe to populate the cache can be turned off at the time of adding the AFAttribute using Manual or ManualRange. See the Add(IListAFAttribute, AFDataCacheUpdateOption) method for details.

AFDataCache will trim the cached events based on both event count and timespan. Trimming is done when the application calls the UpdateData Overload method to update the cache. Just like AFDataPipe, AFDataCache does not poll the data automatically in the background. This allows an application to have complete control over when and which thread will be used, making synchronization across threads simpler.

Single event data access queries made with the cache enabled AFData are much faster. For data access queries not supporting data cache or if the requested range exceeds the amount on data in cache, the data cache will make the normal data access query so no functionality is lost. Hence, AFDataCache is ideal for high performance applications working with streaming data while maintaining the functionality of the Rich Data Access through AFData.

Note that only data access queries made against the cached enabled AFData objects get the benefit of the cache. The cached enabled AFData objects are returned when application calls the Add(IListAFAttribute, AFDataCacheUpdateOption) or TryGetItem(AFAttribute, AFData)method of the AFDataCache. The AFData object obtained from Data is not cached enabled.

For data sources such as the PI Data Archive, where data could be compressed, it is possible for the AFDataCache to have higher resolution data (more events within the same time range) than a direct data access call to the source.

Examples

// This example demonstrates how to create an AFDataPipe
// and how to use it to get new events for an attribute

// Get the Database
PISystems myPISystems = new PISystems();
PISystem myPISystem = myPISystems.DefaultPISystem;
AFDatabase myDB = myPISystem.Databases.DefaultDatabase;
AFValue inputValue1;
AFValue inputValue2;
long numEventsCached0 = 0;
long numEventsProcessed0 = 0;
long numEventsCached1 = 0;
long numEventsProcessed1 = 0;
long numEventsCached2 = 0;
long numEventsProcessed2 = 0;
long numHitCount = 0;
long numMissedHitCount = 0;

// Create an Element with some attributes
AFElement myElement = myDB.Elements.Add("MyElement*");
AFAttribute myAttribute1 = myElement.Attributes.Add("MyAttribute1");
AFAttribute myAttribute2 = myElement.Attributes.Add("MyAttribute2");

// Create PIPoints to Update
PIServer piServer = PIServers.GetPIServers().DefaultPIServer;
PIPoint point;
if (!PIPoint.TryFindPIPoint(piServer, "testfloat1", out point))
{
    point = piServer.CreatePIPoint("testfloat1", null);
}

if (!PIPoint.TryFindPIPoint(piServer, "testfloat2", out point))
{
    point = piServer.CreatePIPoint("testfloat2", null);
}

myAttribute1.DefaultUOM = myPISystem.UOMDatabase.UOMs["kelvin"];
myAttribute1.DataReferencePlugIn = AFDataReference.GetPIPointDataReference(myPISystem);
myAttribute1.ConfigString = @"\\%Server%\testfloat1;ReadOnly=false";

myAttribute2.DefaultUOM = myPISystem.UOMDatabase.UOMs["kelvin"];
myAttribute2.DataReferencePlugIn = AFDataReference.GetPIPointDataReference(myPISystem);
myAttribute2.ConfigString = @"\\%Server%\testfloat2;ReadOnly=false";

// Send some values to tags to initialize them
for (int i = 1; i <= 2; i++)
{
    AFTime tmptime = new AFTime("*");
    inputValue1 = new AFValue(5 * i, tmptime);
    inputValue2 = new AFValue(10 * i, tmptime);
    myAttribute1.SetValue(inputValue1);
    myAttribute2.SetValue(inputValue2);
    Thread.Sleep(1000);                    
}

// Sleep for a minute
Thread.Sleep(60000);

// Create data cache object and sign up the attributes for the cache
AFDataCache myAFDataCache = new AFDataCache(1000);
AFKeyedResults<AFAttribute, AFData> addResult = myAFDataCache.Add(myElement.Attributes);

numEventsCached0 = myAFDataCache.EventsCached;
numEventsProcessed0 = myAFDataCache.EventsProcessed;

// Cache only last minute worth of data
myAFDataCache.CacheTimeSpan = new TimeSpan(0, 1, 0);

// Send values to tags
for (int i = 1; i <= 10; i++)
{
    AFTime tmptime = new AFTime("*");
    inputValue1 = new AFValue(5 * i, tmptime);
    inputValue2 = new AFValue(10 * i, tmptime);
    myAttribute1.SetValue(inputValue1);
    myAttribute2.SetValue(inputValue2);
    Thread.Sleep(1000);                    
}

// Get data for cache
// Sleep a little to make sure all events get through update manager
Thread.Sleep(100);
myAFDataCache.UpdateData();

numEventsCached1 = myAFDataCache.EventsCached;
numEventsProcessed1 = myAFDataCache.EventsProcessed;

// Sleep for a minute
Thread.Sleep(60000);

// Send values to tags after a minute so that these events replace the old ones
for (int i = 1; i <= 10; i++)
{
    AFTime tmptime = new AFTime("*");
    inputValue1 = new AFValue(5 * i, tmptime);
    inputValue2 = new AFValue(10 * i, tmptime);
    myAttribute1.SetValue(inputValue1);
    myAttribute2.SetValue(inputValue2);
    Thread.Sleep(1000);
}

// Get data for cache
Thread.Sleep(100);
myAFDataCache.UpdateData();

numEventsCached2 = myAFDataCache.EventsCached;
numEventsProcessed2 = myAFDataCache.EventsProcessed;

int numInterpolatedCalls = 100;

if (!addResult.HasErrors)
{
    AFData tmpData1 = myAttribute1.Data;
    AFTime tmpTime = new AFTime("*-30s");

    // Call made to regular Data object so therefore cache not used
    for (int i = 0; i < numInterpolatedCalls; i++)
        tmpData1.InterpolatedValue(tmpTime, null);

    AFData tmpData2 = addResult[myAttribute1];

    // Call made to cache Data object so cache is used
    for (int i = 0; i < numInterpolatedCalls; i++)
        tmpData2.InterpolatedValue(tmpTime, null);

    numHitCount = myAFDataCache.CacheHitCount;

    // Call made to a time period not covered by the cache and therefore missed hit count should increment by numInterpolatedCalls
    AFTime tmpTimediff = new AFTime(addResult[myAttribute1].CacheStartTime.UtcSeconds - 2);
    for (int i = 0; i < numInterpolatedCalls; i++)
        tmpData2.InterpolatedValue(tmpTimediff , null);

    numMissedHitCount = myAFDataCache.MissedHitCount;
}
' This example demonstrates how to create the DataReference configuration
' for all attributes with a PIPoint DataReference.

' Get the Database
Dim myPISystems As New PISystems
Dim myPISystem As PISystem = myPISystems.DefaultPISystem
Dim myDB As AFDatabase = myPISystem.Databases.DefaultDatabase
Dim inputValue1 As AFValue
Dim inputValue2 As AFValue
Dim numEventsCached0 As Long = 0
Dim numEventsProcessed0 As Long = 0
Dim numEventsCached1 As Long = 0
Dim numEventsProcessed1 As Long = 0
Dim numEventsCached2 As Long = 0
Dim numEventsProcessed2 As Long = 0
Dim numHitCount As Long = 0
Dim numMissedHitCount As Long = 0

' Create an Element with an Attribute
Dim myElement As AFElement = myDB.Elements.Add("MyElement*")
Dim myAttribute1 As AFAttribute = myElement.Attributes.Add("MyAttribute1")
Dim myAttribute2 As AFAttribute = myElement.Attributes.Add("MyAttribute2")

' Create PIPoints to Update
Dim piServer As PIServer = PIServers.GetPIServers().DefaultPIServer
Dim point As PIPoint = Nothing
If (Not PIPoint.TryFindPIPoint(piServer, "testfloat1", point)) Then
    point = piServer.CreatePIPoint("testfloat1", Nothing)
End If

If (Not PIPoint.TryFindPIPoint(piServer, "testfloat2", point)) Then
    point = piServer.CreatePIPoint("testfloat2", Nothing)
End If

myAttribute1.DefaultUOM = myPISystem.UOMDatabase.UOMs("kelvin")
myAttribute1.DataReferencePlugIn = AFDataReference.GetPIPointDataReference(myPISystem)
myAttribute1.ConfigString = "\\%Server%\testfloat1;ReadOnly=false"

myAttribute2.DefaultUOM = myPISystem.UOMDatabase.UOMs("kelvin")
myAttribute2.DataReferencePlugIn = AFDataReference.GetPIPointDataReference(myPISystem)
myAttribute2.ConfigString = "\\%Server%\testfloat2;ReadOnly=false"

' Send some values to tags to initialize them
For i As Integer = 1 To 2 Step 1
    Dim tmptime As AFTime = New AFTime("*")
    inputValue1 = New AFValue(5 * i, tmptime)
    inputValue2 = New AFValue(10 * i, tmptime)
    myAttribute1.SetValue(inputValue1)
    myAttribute2.SetValue(inputValue2)
    Thread.Sleep(1000)
Next

' Sleep for a minute
Thread.Sleep(60000)

' Create data cache object and sign up the attributes for the cache
Dim myAFDataCache As AFDataCache = New AFDataCache(1000)
Dim addResult As AFKeyedResults(Of AFAttribute, AFData) = myAFDataCache.Add(myElement.Attributes)

numEventsCached0 = myAFDataCache.EventsCached
numEventsProcessed0 = myAFDataCache.EventsProcessed

'Cache only last minute worth of data
myAFDataCache.CacheTimeSpan = New TimeSpan(0, 1, 0)

' Send values to tags
For i As Integer = 1 To 10 Step 1
    Dim tmptime As AFTime = New AFTime("*")
    inputValue1 = New AFValue(5 * i, tmptime)
    inputValue2 = New AFValue(10 * i, tmptime)
    myAttribute1.SetValue(inputValue1)
    myAttribute2.SetValue(inputValue2)
    Thread.Sleep(1000)
Next

' Get data for cache
' Sleep a little to make sure all events get through update manager
Thread.Sleep(100)
myAFDataCache.UpdateData()

numEventsCached1 = myAFDataCache.EventsCached
numEventsProcessed1 = myAFDataCache.EventsProcessed

' Sleep for a minute
Thread.Sleep(60000)

' Send values to tags after a minute so that these events replace the old ones
For i As Integer = 1 To 10 Step 1
    Dim tmptime As AFTime = New AFTime("*")
    inputValue1 = New AFValue(5 * i, tmptime)
    inputValue2 = New AFValue(10 * i, tmptime)
    myAttribute1.SetValue(inputValue1)
    myAttribute2.SetValue(inputValue2)
    Thread.Sleep(1000)
Next

' Get data for cache
Thread.Sleep(100)
myAFDataCache.UpdateData()

numEventsCached2 = myAFDataCache.EventsCached
numEventsProcessed2 = myAFDataCache.EventsProcessed

Dim numInterpolatedCalls As Integer = 100

If (Not addResult.HasErrors) Then
    Dim tmpData1 As AFData = myAttribute1.Data
    Dim tmpTime As AFTime = New AFTime("*-30s")

    ' Call made to regular Data object so therefore cache not used
    For i As Integer = 1 To numInterpolatedCalls Step 1
        tmpData1.InterpolatedValue(tmpTime, Nothing)
    Next i

    Dim tmpData2 As AFData = addResult(myAttribute1)

    ' Call made to cache Data object so cache is used
    For i As Integer = 1 To numInterpolatedCalls Step 1
        tmpData2.InterpolatedValue(tmpTime, Nothing)
    Next i

    numHitCount = myAFDataCache.CacheHitCount

    ' Call made to a time period not covered by the cache and therefore missed hit count should increment by numInterpolatedCalls
    Dim tmpTimediff As AFTime = New AFTime(addResult(myAttribute1).CacheStartTime.UtcSeconds - 2)
    For i As Integer = 1 To numInterpolatedCalls Step 1
        tmpData2.InterpolatedValue(tmpTimediff, Nothing)
    Next i
    numMissedHitCount = myAFDataCache.MissedHitCount
End If

No code example is currently available or this language may not be supported.

No code example is currently available or this language may not be supported.

Version Information

AFSDK

Supported in: 3.1.1, 3.1.0, 3.0.2, 3.0.1, 3.0.0, 2.10.11, 2.10.5, 2.10.0, 2.10, 2.9.5, 2.9, 2.8.5, 2.8, 2.7.5, 2.7, 2.6

See Also

TitleResults for “How to create a CRG?”Also Available in