5 Replies Latest reply on Nov 29, 2016 9:40 PM by Mike Zboray

    Best way to retrieve whole PI AF hierarchy elements with non PI data reference attributes.

    AbhayP

      I am building a job scheduler window service and scheduling it once per day. This scheduler uses AF SDK to retrieve:-

       

      1. All elements with associated attributes (non PI Points)

      2. All attribute templates (if exists)

      3. All element templates (if exists)

       

      I am using static method of AFElement class - "public static AFNamedCollectionList<AFElement> LoadElementsToDepth(IList<AFElement> elements, bool fullLoad, int depth, int maxCount);" to retrieve all elements and then I am iterating all elements for getting associated attributes:-

       

                  AFAttributes attrsAfAttributes = element.Attributes;

                  foreach (var attribute in attrsAfAttributes)

                  {

                      if (attribute.DataReference == null ||  !attribute.DataReference.Name.Equals("PI Point", StringComparison.OrdinalIgnoreCase))

                      {

                          var afValues= attribute.GetValues(timeRange, int.MaxValue, null);

                      }

                  }

      Question 1: I can see some problem with "LoadElementsToDepth" if there are huge list of elements (it may increase memory footprint and I don't know the depth in advance). Is there any better way to get all elements with non PI attributes? (which is better in performance and with less memory footprint). I am not sure if client installation has templates or not (elements and/or attributes) so I am not sure if I can use overloaded methods to get elements based on template parameters.

       

      Question 2: I am planning to load full snapshot only once at the start of service and will subscribe to Changed event of AFDatabase to retrieve changed element/attribute. Is it good implementation choice? Also if something fails on Changed event then I will load whole snapshot again (data duplication is not a problem for me). What is the different between AFDataPipe and Changed event of AFDatabase?

       

      My end goal is to push whole hierarchy once per day into data lake.

       

      Thanks in advance.

        • Re: Best way to retrieve whole PI AF hierarchy elements with non PI data reference attributes.
          Rhys Kirk

          The Changed event of the AFDatabase object is only scoped to your application if it makes a change. You won't get the event triggered for other changes made outside of your application.

          Instead you should be using the AFDatabase.FindChangedItems() method to get changes in between set intervals.

           

          AFDataPipe will give you value/data changes, not the meta-data changes that you seem to be after.

          1 of 1 people found this helpful
          • Re: Best way to retrieve whole PI AF hierarchy elements with non PI data reference attributes.
            Paurav Joshi

            Hi Abhay,

             

            Question 1: I can see some problem with "LoadElementsToDepth" if there are huge list of elements (it may increase memory footprint and I don't know the depth in advance). Is there any better way to get all elements with non PI attributes? (which is better in performance and with less memory footprint). I am not sure if client installation has templates or not (elements and/or attributes) so I am not sure if I can use overloaded methods to get elements based on template parameters.

            If you don't know depth of the hierarchy, then you have to go through each element and search each attribute in it.

            You can do that by using recursive function such as

            foreach(AFElement e in db.Elements){

                //look for attributes

                //look for child elements (using a recursive function)

            }

            and here only you can have list of AF attributes which are non PI-Point.

             

            Question 2: I am planning to load full snapshot only once at the start of service and will subscribe to Changed event of AFDatabase to retrieve changed element/attribute. Is it good implementation choice? Also if something fails on Changed event then I will load whole snapshot again (data duplication is not a problem for me). What is the different between AFDataPipe and Changed event of AFDatabase?

            As suggested by Rhys, use AFDatabase.FindChangedItems Method which will give you all changes done to the AF Database for the time-period you give.

            1 of 1 people found this helpful
            • Re: Best way to retrieve whole PI AF hierarchy elements with non PI data reference attributes.
              Mike Zboray

              A few comments:
              1. This is an inefficient way to filter for non-PI Point attributes. Accessing the DataReference property on an attribute is an expensive operation the first time it is done. It may involve resolving the underlying PI point in the configuration so only do it if you are really sure you want that. Since you are going to throw away attributes that are not PI points, resolving points is completely useless. A much better way to filter is based on the DataReferencePlugIn.Name property. See Rick Davin's post on this. The difference can mean a factor 50x in your startup times.

              2. Rather than use LoadToDepth, you might try the AFElementSearch while specifying "fullLoad:true" when calling FindElements. Also using the caching options (via CacheTimeout) will probably improve your loading performance. Right now there is no way to filter the elements based on what kind of attributes they have, so you might just use an empty criteria to find all elements in the database and then filter client side.

              3. The AFDataPipe is designed to deliver data changes (attribute values) efficiently while FindChangedItems is efficient for configuration changes (think AF structure changes. Adding/removing elements, adding/removing attributes, etc.) Typically you use AFChangeInfo.Refresh in combination with FindChangedItems to avoid excess reloading of data on a refresh. The database Changed event is more like using FindChangedItems. As noted by Rhys, you will have to call Refresh to fire off the event for changes that happen outside of the current application.

              2 of 2 people found this helpful