kilgored

PISystem and AFDatabase behavior

Discussion created by kilgored on Jan 15, 2013
Latest reply on Jan 16, 2013 by cmanhard

I have found some unexpected behavior that I am wondering if anyone has an explanation for. I can reproduce it against AF 2010 and AF 2012, with both AF SDK 2.4.0.4431 and 2.5.0.5039 (in .NET 3.5 and 4.0 projects).

 

The code below is from my testing and reproduces the behavior found in a larger application. Basically, after you Disconnect() a PISystem object and subsequently re-Connect() to that same system - any reference that you held to an AFDatabase on that server will throw InvalidOperation indicating that the "Database 'fillintheblank' has been disconnected" whenever you try to Refresh() the database. This seems odd, but there may be a perfectly good reason for this.

 

Also, even after explicitly performing a Disconnect(), the ConnectionInfo.IsConnected property still reports true. This greatly reduces the value of the property, unless I am misunderstanding something. I did see Chris' post over here, but would have expected that Disconnect() is such an operation.

 

This all came to light while troubleshooting some connection retry logic in the real application, where after certain types of network hiccups - SQL connectivity issues arise between the AF Server and the underlying PIFD database, which won't heal themselves in the application without a disconnect and reconnect.

 
        static void Main(string[] args)
        {
            const string messageFormat = "{0} sys IsConnected: {1}. db.PISystem IsConnected: {2}.";

            PISystem sys = new PISystems().DefaultPISystem;

            sys.Connect();

            AFDatabase db = sys.Databases.DefaultDatabase;
            AFElement ele = db.Elements[0];
            AFAttribute att = ele.Attributes[0];

            try
            {
                Console.WriteLine("Refreshing after initial connection");
                db.Refresh(); // This works, which is to be expected
            }
            catch (InvalidOperationException ex)
            {
                Console.WriteLine(messageFormat, ex.Message, sys.ConnectionInfo.IsConnected, db.PISystem.ConnectionInfo.IsConnected);
            }

            Console.WriteLine(att.GetValue()); // This works

            sys.Disconnect();

            try
            {
                Console.WriteLine("Refreshing after disconnection");
                db.Refresh(); // This fails, which is to be expected
            }
            catch (InvalidOperationException ex)
            {
                // The ConnectionInfo ALWAYS reports TRUE
                Console.WriteLine(messageFormat, ex.Message, sys.ConnectionInfo.IsConnected, db.PISystem.ConnectionInfo.IsConnected);
            }

            Console.WriteLine(att.GetValue()); // This works

            sys.Connect();

            // These NEVER fail and can be removed or placed after the next db.Refresh() command, which will still always fail
            sys.Refresh();
            ele.Refresh();

            try
            {
                Console.WriteLine("Refreshing after re-connection");
                db.Refresh(); // This ALWAYS fails
            }
            catch (InvalidOperationException ex)
            {
                // The ConnectionInfo ALWAYS reports TRUE
                Console.WriteLine(messageFormat, ex.Message, sys.ConnectionInfo.IsConnected, db.PISystem.ConnectionInfo.IsConnected);
            }

            Console.WriteLine(att.GetValue()); // This works

            db = sys.Databases.DefaultDatabase; // Found repeatable pattern requiring fresh reference to AFDatabase object

            try
            {
                Console.WriteLine("Refreshing after re-referencing");
                db.Refresh(); // This works
            }
            catch (InvalidOperationException ex)
            {
                Console.WriteLine(messageFormat, ex.Message, sys.ConnectionInfo.IsConnected, db.PISystem.ConnectionInfo.IsConnected);
            }

            Console.WriteLine(att.GetValue()); // This works

            sys.Disconnect();
        }

 

 

Thanks in advance for any insight you may have.

Outcomes