Loading Partial Elements
- Last UpdatedJan 12, 2026
- 6 minute read
- PI System
- AF SDK 3.2.0
- Developer
This topic contains the following sections:
Typically, a top-level object in the AF SDK is either fully-loaded, or just has the header information for it loaded. Often, however, there is a need to just access a few specific attributes from a collection of elements. These examples use the LoadAttributes methods to load a specific list of attributes into the client. By only loading a partial set of attributes, the amount of information required to be transferred from the server to the client is reduced, resulting in faster performance and a lower memory footprint.
Partial Load Elements by IDs
This example demonstrates using the
AFSearchFindObjectIds
method to obtain a list of element unique identifiers and then partially load some of the element's attributes.
1// Get the Database 2PISystems myPISystems = new PISystems(); 3PISystem myPISystem = myPISystems.DefaultPISystem; 4if (myPISystem == null) 5 throw new InvalidOperationException("Default PISystem was not found."); 6AFDatabase myDB = myPISystem.Databases[dbName]; 7if (myDB == null) 8 throw new InvalidOperationException("Database was not found."); 9 10// Use attribute value query to find a list of tanks that are 11// In Service (tanks which are out-of-service have their 12// Status attribute set to "OS"). 13int totalCount = 0; 14using (var search = new AFElementSearch(myDB, "FindTanks", @"Template:'TankAdvanced' |Status:<>'OS'")) 15{ 16 search.CacheTimeout = TimeSpan.FromMinutes(10); 17 18 // Because we are only going to use a few of the attributes for each 19 // of the elements found, we can reduce the load time and memory space 20 // by just loading the attributes we need. Note that if we inadvertently 21 // use attributes other than these, we will incur a load penalty. 22 AFElementTemplate tankTemplate = myDB.ElementTemplates["Tank"]; 23 AFNamedCollectionList<AFAttributeTemplate> myAttributes = 24 new AFNamedCollectionList<AFAttributeTemplate>(); 25 myAttributes.Add(tankTemplate.AttributeTemplates["Volume"]); 26 myAttributes.Add(tankTemplate.AttributeTemplates["Level"]); 27 myAttributes.Add(tankTemplate.AttributeTemplates["Level|HighLimit"]); 28 myAttributes.Add(tankTemplate.AttributeTemplates["Level|LowLimit"]); 29 30 // Get today's date and UOMs to be used for converting values. 31 AFTime today = new AFTime("T", CultureInfo.CurrentCulture); 32 UOM bbl = myDB.PISystem.UOMDatabase.UOMs["bbl"]; 33 UOM meter = myDB.PISystem.UOMDatabase.UOMs["m"]; 34 35 const int pageSize = 1000; 36 int startIndex = 0; 37 IList<Guid> myElementIds = new List<Guid>(pageSize); 38 do 39 { 40 // Find the element IDs and load the attributes we will be using. 41 var results = search.FindObjectIds(startIndex, pageSize: pageSize); 42 myElementIds.Clear(); 43 int c = 0; 44 foreach (Guid id in results) 45 { 46 totalCount++; 47 myElementIds.Add(id); 48 c++; 49 if (c >= pageSize) 50 break; 51 } 52 53 if (myElementIds.Count == 0) break; 54 AFNamedCollectionList<AFElement> elements = 55 AFElement.LoadAttributes(myPISystem, myElementIds, myAttributes); 56 57 // Once the elements are loaded, we can process them. 58 foreach (AFElement element in elements) 59 { 60 try 61 { 62 AFAttributeList attributes = new AFAttributeList(); 63 attributes.Add(element.Attributes["Volume"]); 64 attributes.Add(element.Attributes["Level"]); 65 attributes.Add(element.Attributes["Level|HighLimit"]); 66 attributes.Add(element.Attributes["Level|LowLimit"]); 67 AFValues values = attributes.GetValue(today); 68 69 if (values[0].IsGood && values[1].IsGood && 70 values[2].IsGood && values[3].IsGood) 71 { 72 double volume = (double)values[0].Convert(bbl).Value; 73 double level = (double)values[1].Convert(meter).Value; 74 double high = (double)values[2].Convert(meter).Value; 75 double low = (double)values[3].Convert(meter).Value; 76 77 Console.WriteLine("Tank Inventory for '{0}' is {1} bbl. %Full={2}", 78 element.Name, volume, 100 * (high - low) / level); 79 } 80 else 81 { 82 Console.WriteLine("Bad data in Tank '{0}'", element.Name); 83 } 84 } 85 catch (FormatException) 86 { 87 Console.WriteLine("Error in Tank '{0}'", element.Name); 88 } 89 } 90 91 startIndex += myElementIds.Count; // Advance to next page. 92 } while (myElementIds.Count > 0 && myElementIds.Count >= pageSize); 93} 94 95Console.WriteLine("Processed {0} Elements.", totalCount);
Partial Load Elements from Search
This example demonstrates partially loading elements using the
AFElementSearchFindElements
method to find the element headers and then partially load some of the element's attributes.
1// Get the Database 2PISystems myPISystems = new PISystems(); 3PISystem myPISystem = myPISystems.DefaultPISystem; 4if (myPISystem == null) 5 throw new InvalidOperationException("Default PISystem was not found."); 6AFDatabase myDB = myPISystem.Databases[dbName]; 7if (myDB == null) 8 throw new InvalidOperationException("Database was not found."); 9 10// Use attribute value query to find a list of tanks that are 11// In Service (tanks which are out-of-service have their 12// Status attribute set to "OS"). 13int totalCount = 0; 14using (var search = new AFElementSearch(myDB, "FindTanks", @"Template:'TankAdvanced' |Status:<>'OS'")) 15{ 16 search.CacheTimeout = TimeSpan.FromMinutes(10); 17 18 // Because we are only going to use a few of the attributes for each 19 // of the elements found, we can reduce the load time and memory space 20 // by just loading the attributes we need. Note that if we inadvertently 21 // use attributes other than these, we will incur a load penalty. 22 AFElementTemplate tankTemplate = myDB.ElementTemplates["Tank"]; 23 AFNamedCollectionList<AFAttributeTemplate> myAttributes = 24 new AFNamedCollectionList<AFAttributeTemplate>(); 25 myAttributes.Add(tankTemplate.AttributeTemplates["Volume"]); 26 myAttributes.Add(tankTemplate.AttributeTemplates["Level"]); 27 myAttributes.Add(tankTemplate.AttributeTemplates["Level|HighLimit"]); 28 myAttributes.Add(tankTemplate.AttributeTemplates["Level|LowLimit"]); 29 30 // Get today's date and UOMs to be used for converting values. 31 AFTime today = new AFTime("T", CultureInfo.CurrentCulture); 32 UOM bbl = myDB.PISystem.UOMDatabase.UOMs["bbl"]; 33 UOM meter = myDB.PISystem.UOMDatabase.UOMs["m"]; 34 35 const int pageSize = 1000; 36 int startIndex = 0; 37 IList<AFElement> myElements = new List<AFElement>(pageSize); 38 do 39 { 40 // Find the elements and load the attributes we will be using. 41 var results = search.FindObjects(startIndex, fullLoad: false, pageSize: pageSize); 42 myElements.Clear(); 43 int c = 0; 44 foreach (AFElement item in results) 45 { 46 totalCount++; 47 myElements.Add(item); 48 c++; 49 if (c >= pageSize) 50 break; 51 } 52 53 if (myElements.Count == 0) break; 54 AFElement.LoadAttributes(myElements, myAttributes); 55 56 // Once the elements are loaded, we can process them. 57 foreach (AFElement element in myElements) 58 { 59 try 60 { 61 AFAttributeList attributes = new AFAttributeList(); 62 attributes.Add(element.Attributes["Volume"]); 63 attributes.Add(element.Attributes["Level"]); 64 attributes.Add(element.Attributes["Level|HighLimit"]); 65 attributes.Add(element.Attributes["Level|LowLimit"]); 66 AFValues values = attributes.GetValue(today); 67 68 if (values[0].IsGood && values[1].IsGood && 69 values[2].IsGood && values[3].IsGood) 70 { 71 double volume = (double)values[0].Convert(bbl).Value; 72 double level = (double)values[1].Convert(meter).Value; 73 double high = (double)values[2].Convert(meter).Value; 74 double low = (double)values[3].Convert(meter).Value; 75 76 Console.WriteLine("Tank Inventory for '{0}' is {1} bbl. %Full={2}", 77 element.Name, volume, 100 * (high - low) / level); 78 } 79 else 80 { 81 Console.WriteLine("Bad data in Tank '{0}'", element.Name); 82 } 83 } 84 catch (FormatException) 85 { 86 Console.WriteLine("Error in Tank '{0}'", element.Name); 87 } 88 } 89 90 startIndex += myElements.Count; // Advance to next page. 91 } while (myElements.Count > 0 && myElements.Count >= pageSize); 92} 93 94Console.WriteLine("Processed {0} Elements.", totalCount);