11 Replies Latest reply on Jan 22, 2016 4:05 PM by pthivierge

    I have a list of Elements name, can I get the respective AFElements in one go?

    Suganya_Ganesan

      Hello,

       

      I have a list of Elements name, can I get the respective AFElements in one go?

       

      Currently I am using the below code, which is time consuming because I am passing only one query at a time.

      Please suggest some solution to improve the performance.

       

       

      Code Snippet:

       

      List<string> objMeterList=new List<string> ();

       

      foreach (string strMeterElement in objMeterList)

      {

                         var MeterElement = AFElement.FindElements(obj_AFDatabase, null, strMeterElement, AFSearchField.Name, true, AFSortField.Name, AFSortOrder.Ascending, 100);

       

                          if (MeterElement.Count > 0)

                              MeterElements.Add(MeterElement[0]);

      }

        • Re: I have a list of Elements name, can I get the respective AFElements in one go?
          Rhys Kirk

          Depends...looks like you're searching for meters. Are you using a template to define the meters?

           

          You could use AFElement.FindElementsByTemplate(...)

           

          List<string> meterNames = new List<string>();
          OSIsoft.AF.AFNamedCollectionList<OSIsoft.AF.Asset.AFElement> potentialMeters = OSIsoft.AF.Asset.AFElement.FindElementsByTemplate(...);
          IEnumerable<OSIsoft.AF.Asset.AFElement> foundMeters = potentialMeters.Where(meter => meterNames.Contains(meter.Name));
          
          2 of 2 people found this helpful
          • Re: I have a list of Elements name, can I get the respective AFElements in one go?
            Rick Davin

            Could you provide more details about your hierarchy? As more information is provided to clarify your structure, then possibly the answers can be more specific.  For example, I had to read through several different posts to get this much info:

             

            • You are using an element template.
            • Over 1 million elements are based on this template.
            • You want to fetch less than 2 dozen specific elements in 1 call.
            • The element names are based on a meter number.
            • The 2 dozen or so meter numbers of interest are read from a CSV file.

             

            You could of provided all of this information in your original post.  It would have helped refine possible solutions from other readers.

             

            Perhaps you can tell us about your structure.  Is it a flat structure, that is to say all 1 million elements (meters) exist under 1 parent element?  Or is it a bushy structure where either (a) the elements of interest exist under the same parent or (b) the elements of interest are scattered among the many unrelated branches?

             

            I presume the the CSV file just has meter numbers, and would not be able to provide a path for you.  Is there any easy way in your code to generate the element path based solely upon the meter number?  If so you could use the AFElement.FindElementsByPath method.

             

            AFElement.FindElementsByPath Method (IEnumerable(String), AFObject)

             

            The more complicated your structure and more scattered the meter numbers, the slower the search.

              • Re: I have a list of Elements name, can I get the respective AFElements in one go?
                Suganya_Ganesan

                Rick,

                 

                Exactly as you said, csv file gives only the meter name.

                All the meters will be under one parent and they follow a template, which is specific only to the children of that parent. So, search based on searchRoot and template will fetch same meters.

                 

                Rhys,

                 

                I tried using FindElementsByAttributeValue method for each meter, but there is no performance improvement compared to FindElements.

                Can we refine the below code?

                Kindly suggest.

                 

                Code Snippet:

                foreach (string strMeter in objMeterList)

                  {

                                    AFAttributeValueQuery avq = new AFAttributeValueQuery(objAFEleTemplate.AttributeTemplates["ECD_IDN"], AFSearchOperator.Equal, strMeter);

                                    AFAttributeValueQuery[] objAFAttribValQuery = new AFAttributeValueQuery[] { avq };

                 

                                    AFElement objAFRoot = obj_AFDatabase.Elements["Meters"];

                                    var AFMeterList = AFElement.FindElementsByAttribute(objAFRoot, null, objAFAttribValQuery, true, AFSortField.Name, AFSortOrder.Ascending, 1000);

                                    if(AFMeterList.Count>0)

                                        MeterElements.Add(AFMeterList[0]);

                  }

                  • Re: I have a list of Elements name, can I get the respective AFElements in one go?
                    Rick Davin

                    Given that your meters of interest (less than 20) reside under the same parent element (the search root) alongside 1 million other peer meters (elements), you can try this bit of code:

                     

                    public AFNamedCollectionList<AFElement> GetMeterElements(AFDatabase database, string rootName, IList<string> meterNames)
                    {
                        AFElement rootElement = database.Elements[rootName];
                        List<string> meterPaths = new List<string>();
                    
                        foreach (var meterName in meterNames)
                        {
                            // If the meters, aka elements, have a consistent naming pattern, build the name accordingly.
                            string elementName = meterName;
                            // after elementName is built, add it to list.
                            meterPaths.Add(elementName);
                        }
                    
                        var rawFetch = AFElement.FindElementsByPath(meterPaths, rootElement);
                    
                        return new AFNamedCollectionList<AFElement>(rawFetch.Results.Values);
                    }
                    

                     

                    You would call it like:

                     

                    var meters = GetMeterElements(obj_AFDatabase, "Meters", objMeterList);
                    

                     

                    The critical bit of code is line 9 when you build the elementName.  This assumes you have a consistent naming pattern to your element instances.

                    5 of 5 people found this helpful