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

AF SDK Reference

AFListData.UpdateValues Method (IList(AFValue), AFUpdateOption, AFBufferOption)

AFListData.UpdateValues Method (IList(AFValue), AFUpdateOption, AFBufferOption)

  • Last UpdatedNov 18, 2025
  • 8 minute read
AFListData.UpdateValues Method (IList(AFValue), AFUpdateOption, AFBufferOption)
Write, update, or remove a AFAttribute value for each AFValue in the specified list.

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

Syntax

public static AFErrors<AFValue> UpdateValues(
	IList<AFValue> values,
	AFUpdateOption option,
	AFBufferOption bufferOption
)
Public Shared Function UpdateValues ( 
	values As IList(Of AFValue),
	option As AFUpdateOption,
	bufferOption As AFBufferOption
) As AFErrors(Of AFValue)

Dim values As IList(Of AFValue)
Dim option As AFUpdateOption
Dim bufferOption As AFBufferOption
Dim returnValue As AFErrors(Of AFValue)

returnValue = AFListData.UpdateValues(values, 
	option, bufferOption)
public:
static AFErrors<AFValue^>^ UpdateValues(
	IList<AFValue^>^ values, 
	AFUpdateOption option, 
	AFBufferOption bufferOption
)
static member UpdateValues : 
        values : IList<AFValue> * 
        option : AFUpdateOption * 
        bufferOption : AFBufferOption -> AFErrors<AFValue> 

Parameters

values
Type: System.Collections.GenericIListAFValue
The list of values with an associated AFAttribute for each value.
option
Type: OSIsoft.AF.DataAFUpdateOption
An enumeration value that specifies how to treat duplicate values. It can also be used to specify that an existing value should be removed.
bufferOption
Type: OSIsoft.AF.DataAFBufferOption
An enumeration value that specifies buffering option.

Return Value

Type: AFErrorsAFValue
Returns a list of the errors associated with the AFValue that caused the error. If there are no errors, then is returned.

Remarks

This method will take the list of values with an associated AFAttribute and update multiple values for multiple attributes. Multiple values for the same AFAttribute can be in the list. The value cannot be updated if the AFValue.Attribute is not defined.

For the case of attributes which are configuration items, this method (unlike AFAttribute.SetValue) does not require the corresponding AFElement to be checked out or checked in.

If AFBufferOption is set to Buffer, this method requires that the attribute has a configured data reference which supports buffering. This is indicated by having the Buffering flag set in the SupportedDataMethods property. The PI Point Data Reference supports buffering.

Important note Important
For the case of attributes that do not have a data reference and which are configuration items, if the corresponding AFElement is already checked out by another user (i.e. through AFAttribute.SetValue) when this method is called, then the value(s) to update may be lost when the other user checks in the AFElement.

Examples

// This example demonstrates how to update values to attributes with PIPoint data reference from different PIServers through AFListData.
// Note: For successful write through Buffer, PI Buffer Subsystem needs to be correctly pre-configured with PI Buffer Manager. 

// Get the Database and UOMs
PISystems myPISystems = new PISystems();
PISystem myPISystem = myPISystems.DefaultPISystem;
AFDatabase myDB = myPISystem.Databases.DefaultDatabase;
UOM uomFoot = myPISystem.UOMDatabase.UOMs["foot"];
UOM uomYard = myPISystem.UOMDatabase.UOMs["yard"];

// Create Attributes and their new values
AFAttributeList attrList = new AFAttributeList();
AFTime newStartTime = new AFTime("T-1d", CultureInfo.CurrentCulture);
List<AFValue> newValues = new List<AFValue>();
Random randomValues = new Random();

// Create Dynamic Attributes to a PIPoint (from different PIServers if possible) to Update
List<PIServer> piServers = new List<PIServer>();
piServers.Add(PIServers.GetPIServers().DefaultPIServer);
//ToDo: change "jcncpi390" to a valid (and accessible) piserver name available in KST, that is different than the default piserver
PIServer secondServer = PIServers.GetPIServers()["jcncpi390"];
if (secondServer != null && String.Compare(secondServer.Name, piServers[0].Name, StringComparison.OrdinalIgnoreCase) != 0)
    piServers.Add(secondServer);
int dataCount = 5; //Create 5 new values to update
AFTime newTime = newStartTime;
foreach(PIServer piServer in piServers)
{
    newTime = newStartTime;
    PIPoint point;
    if (!PIPoint.TryFindPIPoint(piServer, "MyTestPoint#1", out point))
    {
        point = piServer.CreatePIPoint("MyTestPoint#1");
    }
    AFAttribute myAttribute = new AFAttribute(String.Format(CultureInfo.InvariantCulture, @"\\{0}\{1}", piServer.Name, point.Name));
    myAttribute.DefaultUOM = uomFoot;
    myAttribute.ConfigString += ";ReadOnly=False";
    attrList.Add(myAttribute);
    for (int i = 0; i < dataCount; i++)
    {
        AFValue newValue = new AFValue(myAttribute, randomValues.NextDouble(), newTime, uomYard);
        newValues.Add(newValue);
        newTime = newTime.LocalTime.AddMinutes(10);
    }
}
AFTime newEndTime = newTime;

// Get the Recorded Values for the Attributes
int totalRecordedValuesCount = 0;
foreach (AFAttribute myAttribute in attrList)
{
    AFValues recordedValues = myAttribute.Data.RecordedValues(new AFTimeRange(newStartTime, newEndTime), AFBoundaryType.Inside,
        myAttribute.DefaultUOM, null, false);
    Console.WriteLine("Recorded Values:");
    foreach (AFValue value in recordedValues)
    {
        Console.WriteLine("  {0}: '{1} {2}' at '{3}'",
            value.Attribute, value.Value, value.UOM, value.Timestamp);
    }
    totalRecordedValuesCount += recordedValues.Count;
}

// Get the Buffer Option
// Note: If not specified in AFSDK.config, the buffer option is defaulted to "BufferIfPossible". 
Console.WriteLine("Current Buffer Option: {0}", AFData.BufferOption);

// Set the Buffer Option to "Buffer" if it is not already, which will be valid throughout this client instance.
if (AFData.BufferOption != AFBufferOption.Buffer)
{
    AFData.BufferOption = AFBufferOption.Buffer;
    Console.WriteLine("Current Buffer Option for this instance has been changed to: {0}", AFData.BufferOption);
}

//1. Update the Attribute Values and Display any Errors
AFErrors<AFValue> errorsWithBuffer =
    AFListData.UpdateValues(newValues, AFUpdateOption.InsertNoCompression); //Insert or InsertNoCompression
Thread.Sleep(1000);

if (errorsWithBuffer != null && errorsWithBuffer.HasErrors)
{
    Console.WriteLine("\nErrors returned from AFListData.UpdateValues:");

    // Display Value errors
    if (errorsWithBuffer.Errors != null && errorsWithBuffer.Errors.Count > 0)
    {
        foreach (var item in errorsWithBuffer.Errors)
        {
            Console.WriteLine("  AFValue '{0}': {1}", item.Key, item.Value);
        }
    }

    // Display error from the PI Data Archive
    if (errorsWithBuffer.PIServerErrors != null && errorsWithBuffer.PIServerErrors.Count > 0)
    {
        foreach (var item in errorsWithBuffer.PIServerErrors)
        {
            Console.WriteLine("  AFValue '{0}': {1}", item.Key, item.Value);
        }
    }

    // Display PI System errors
    if (errorsWithBuffer.PISystemErrors != null && errorsWithBuffer.PISystemErrors.Count > 0)
    {
        foreach (var item in errorsWithBuffer.PISystemErrors)
        {
            Console.WriteLine("  AFValue '{0}': {1}", item.Key, item.Value);
        }
    }
}


//2. Alternatively, one can specify buffer option in the UpdateValues method
AFErrors<AFValue> errorsWithBufferIfPossible =
    AFListData.UpdateValues(newValues, AFUpdateOption.InsertNoCompression, AFBufferOption.BufferIfPossible);
Thread.Sleep(1000);

// Get the Updated Recorded Values for the Attributes
int totalRecordedValuesCountUpdated = 0;
foreach (AFAttribute myAttribute in attrList)
{
    AFValues recordedValuesUpdated = myAttribute.Data.RecordedValues(new AFTimeRange(newStartTime, newEndTime), AFBoundaryType.Inside,
        myAttribute.DefaultUOM, null, false);
    Console.WriteLine("\nUpdated Recorded Values:");
    foreach (AFValue value in recordedValuesUpdated)
    {
        Console.WriteLine("  {0}: '{1} {2}' at '{3}'",
            value.Attribute, value.Value, value.UOM, value.Timestamp);
    }
    totalRecordedValuesCountUpdated += recordedValuesUpdated.Count;
}
' This example demonstrates how to update values to attributes with PIPoint data reference from different PIServers through AFListData.
' Note: For successul write through Buffer, PI Buffer Subsystem needs to be correctly pre-configured with PI Buffer Manager. 

' Get the Database and UOMs
Dim myPISystems As PISystems = New PISystems
Dim myPISystem As PISystem = myPISystems.DefaultPISystem
Dim myDB As AFDatabase = myPISystem.Databases.DefaultDatabase
Dim uomFoot As UOM = myPISystem.UOMDatabase.UOMs("foot")
Dim uomYard As UOM = myPISystem.UOMDatabase.UOMs("yard")

' Create Attributes and their new values
Dim attrList As AFAttributeList = New AFAttributeList
Dim newStartTime As AFTime = New AFTime("T-1d", CultureInfo.CurrentCulture)
Dim newValues As List(Of AFValue) = New List(Of AFValue)
Dim randomValues As Random = New Random

' Create Dynamic Attributes to a PIPoint (from different PIServers if possible) to Update
Dim piServers As List(Of PIServer) = New List(Of PIServer)
piServers.Add(OSIsoft.AF.PI.PIServers.GetPIServers.DefaultPIServer)
'ToDo: change "jcncpi390" to a valid (and accessible) piserver name available in KST, that is different than the default piserver
Dim secondServer As PIServer = OSIsoft.AF.PI.PIServers.GetPIServers()("jcncpi390")
If Not secondServer Is Nothing AndAlso Not String.Compare(secondServer.Name, piServers(0).Name, StringComparison.OrdinalIgnoreCase) = 0 Then
    piServers.Add(secondServer)
End If

Dim dataCount As Integer = 5 'Create 5 new values to update
Dim newTime As AFTime = newStartTime
For Each piServer As PIServer In piServers
    newTime = newStartTime
    Dim point As PIPoint = Nothing
    If Not PIPoint.TryFindPIPoint(piServer, "MyTestPoint#1", point) Then
        point = piServer.CreatePIPoint("MyTestPoint#1")
    End If

    Dim myAttribute As AFAttribute = New AFAttribute(String.Format(CultureInfo.InvariantCulture, "\\{0}\{1}", piServer.Name, point.Name))
    myAttribute.DefaultUOM = uomFoot
    myAttribute.ConfigString = (myAttribute.ConfigString + ";UOM=ft;ReadOnly=True")
    attrList.Add(myAttribute)
    For i As Integer = 1 To dataCount
        Dim newValue As AFValue = New AFValue(myAttribute, randomValues.NextDouble(), newTime, uomYard)
        newValues.Add(newValue)
        newTime = newTime.LocalTime.AddMinutes(10)
    Next
Next
Dim newEndTime As AFTime = newTime

' Get the Recorded Values for the Attributes
Dim totalRecordedValuesCount As Integer = 0
For Each myAttribute As AFAttribute In attrList
    Dim recordedValues As AFValues = myAttribute.Data.RecordedValues(New AFTimeRange(newStartTime, newEndTime), AFBoundaryType.Inside,
        myAttribute.DefaultUOM, Nothing, False)
    Console.WriteLine("Recorded Values:")

    For Each value As AFValue In recordedValues
        Console.WriteLine("  {0}: '{1} {2}' at '{3}'",
            value.Attribute, value.Value, value.UOM, value.Timestamp)
    Next
    totalRecordedValuesCount += recordedValues.Count
Next

' Get the Buffer Option
' Note: If not specified in AFSDK.config, the buffer option is defaulted to "BufferIfPossible". 
Console.WriteLine("Current Buffer Option: {0}", AFData.BufferOption)

' Set the Buffer Option to "Buffer" if it is not already, which will be valid throughout this client instance.
If Not AFData.BufferOption.Equals(AFBufferOption.Buffer) Then
    AFData.BufferOption = AFBufferOption.Buffer
    Console.WriteLine("Current Buffer Option for this instance has been changed to: {0}", AFData.BufferOption)
End If

'1. Update the Attribute Values and Display any Errors
Dim errorsWithBuffer As AFErrors(Of AFValue) =
    AFListData.UpdateValues(newValues, AFUpdateOption.InsertNoCompression) 'Insert or InsertNoCompression
Thread.Sleep(1000)

If Not errorsWithBuffer Is Nothing AndAlso errorsWithBuffer.HasErrors Then
    Console.WriteLine("Errors returned from AFListData.UpdateValues:")

    ' Display Value errors
    If Not errorsWithBuffer.Errors Is Nothing AndAlso errorsWithBuffer.Errors.Count > 0 Then
        For Each item As KeyValuePair(Of AFValue, Exception) In errorsWithBuffer.Errors
            Console.WriteLine("  AFValue '{0}': {1}", item.Key, item.Value)
        Next
    End If

    ' Display PI Data Archive error
    If Not errorsWithBuffer.PIServerErrors Is Nothing AndAlso errorsWithBuffer.PIServerErrors.Count > 0 Then
        For Each item As KeyValuePair(Of PIServer, Exception) In errorsWithBuffer.PIServerErrors
            Console.WriteLine("  AFValue '{0}': {1}", item.Key, item.Value)
        Next
    End If

    ' Display PI System errors
    If Not errorsWithBuffer.PISystemErrors Is Nothing AndAlso errorsWithBuffer.PISystemErrors.Count > 0 Then
        For Each item As KeyValuePair(Of PISystem, Exception) In errorsWithBuffer.PISystemErrors
            Console.WriteLine("  AFValue '{0}': {1}", item.Key, item.Value)
        Next
    End If
End If


'2. Alternatively, one can specify buffer option in the UpdateValues method
Dim errorsWithBufferIfPossible As AFErrors(Of AFValue) =
    AFListData.UpdateValues(newValues, AFUpdateOption.InsertNoCompression, AFBufferOption.BufferIfPossible)
Thread.Sleep(1000)

' Get the Updated Recorded Values for the Attributes
Dim totalRecordedValuesCountUpdated As Integer = 0
For Each myAttribute As AFAttribute In attrList
    Dim recordedValuesUpdated As AFValues = myAttribute.Data.RecordedValues(New AFTimeRange(newStartTime, newEndTime), AFBoundaryType.Inside,
        myAttribute.DefaultUOM, Nothing, False)
    Console.WriteLine("Updated Recorded Values:")

    For Each value As AFValue In recordedValuesUpdated
        Console.WriteLine("  {0}: '{1} {2}' at '{3}'",
            value.Attribute, value.Value, value.UOM, value.Timestamp)
    Next
    totalRecordedValuesCountUpdated += recordedValuesUpdated.Count
Next

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

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