AFListData.UpdateValues Method (IList(AFValue), AFUpdateOption, AFBufferOption)
- Last UpdatedJan 12, 2026
- 5 minute read
- PI System
- AF SDK 3.2.0
- Developer
Namespace: OSIsoft.AF.Data
Assembly: OSIsoft.AFSDK (in OSIsoft.AFSDK.dll) Version: 3.2.0.7
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: AFErrorsAFValueReturns 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.
| 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; }