Subscribe Now: Feed Icon

Monday, December 26, 2011

ArcObjects: Workspace is Down

This post is the sixth post in my ArcObjects series.

This is a direct continuation from my post ArcObjects: Workspace Provider.

 

Back in March our DB was down over the night and unlike all the other systems ours didn't just resume work after the DB was brought up, it needed the team’s involvement.

The Exception we got was:

System.Runtime.InteropServices.COMException was unhandled

  HelpLink=esri_csGeoDatabase.hlp

  Message=Failure to access the DBMS server [Microsoft SQL Server Native Client 10.0: Communication link failure] [SERVER.SCHEMA.LAYER_NAME]

  Source=esriDataSourcesGDB.SdeWorkspace.1

  ErrorCode=-2147155559

  StackTrace:

       at ESRI.ArcGIS.Geodatabase.IFeatureClass.Search(IQueryFilter filter, Boolean Recycling)

  InnerException:

 

So I recreated the error by restarting the "SQL Server (MSSQLSERVER)" service in our DB with some special code.

 

Symptoms:

1.       The IWorkspace status:

((IWorkspace) _workspace).Exists();

                Returns true

2.       Then I started looking at other places like ESRI’s diagrams. One of the diagrams:

image

(Not mine EDN's)

IWorkspaceStatus sounded a bit off to me that it is under WorkspaceFactory and not under Workspace but the real problem was what was written in the documentation. There are no implementations of this according to EDN…

But I found another interface IWorkspaceFactoryStatus, managed to point it to my workspace and got back:

((ESRI.ArcGIS.Geodatabase.IWorkspaceFactoryStatus  )workspaceFactoryTemp).PingWorkspaceStatus((ESRI.ArcGIS.Geodatabase.IWorkspace)_workspace)

{System.__ComObject}

    [System.__ComObject]: {System.__ComObject}

    ConnectionStatus: esriWCSAvailable

    Workspace: {System.__ComObject}

 

I just thought to myself how can it possibly be Available, until I look at the documentation at esriWorkspaceConnectionStatus:

image

Available doesn't mean it's up - just that it was lost and now is available. And I was sure it meant something else… (Couldn’t they name it something like LostAndNowAvailable or AvailableToReconnect? – Available just does not cut it!!!).

 

The end result looks like this:

  1. if (!IsWorkspaceRunning(_workspace))
  2. {
  3.     ReactivateWorkspace();
  4.     InitializeWorkspaceUtils(_workspace);
  5. }
  6. return _workspaceUtils;

Checking if the workspace is running:

  1. private bool IsWorkspaceRunning(IWorkspace workspace)
  2. {
  3.     IWorkspaceFactoryStatus workspaceFactory = new SdeWorkspaceFactoryClass();
  4.     return workspaceFactory.PingWorkspaceStatus(workspace).ConnectionStatus == esriWorkspaceConnectionStatus.esriWCSUp && workspace.Exists();
  5. }

If it’s down recreate it (and if it can’t be recreated throw an exception):

  1. private void ReactivateWorkspace()
  2. {
  3.     IWorkspaceFactoryStatus workspaceFactory = new SdeWorkspaceFactoryClass();
  4.     var status = workspaceFactory.PingWorkspaceStatus(_workspace);
  5.     if (status.ConnectionStatus != esriWorkspaceConnectionStatus.esriWCSDown)
  6.     {
  7.         _workspace = workspaceFactory.OpenAvailableWorkspace(status);
  8.     }
  9.  
  10.     //try to create it again:
  11.     _workspace = CreateWorkspace(_connectionString);
  12.     status = workspaceFactory.PingWorkspaceStatus(_workspace);
  13.  
  14.     if (status.ConnectionStatus == esriWorkspaceConnectionStatus.esriWCSDown)
  15.     {
  16.         throw new ApplicationException("The Connection to the database was lost. Please contact your system administrators.");
  17.     }
  18. }

You can also look at the full code here.

 

Hopefully next time the DB is down it will just recreate IWorksapce…

 

Resources:

The forum post I wrote