Sessions

A SQLOLEDB session represents a single connection to a SQL Server.

OLE DB requires that sessions delimit transaction space for a data source. All command objects created from a specific session object will participate in the local or distributed transaction of the session object.

The first session object created on the initialized data source receives the SQL Server connection established at initialization. When all references on the interfaces of the session object are released, the SQL Server connection becomes available to another session object created on the data source.

An additional session object created on the data source establishes its own connection to the SQL Server as specified by the data source. The SQL Server connection is dropped when the application releases all references to objects created that session.

Example

This example shows SQLOLEDB SQL Server connection usage.

int main()
{
  // Interfaces used in the example.
  IDBInitialize*  pIDBInitialize  = NULL;
  IDBCreateSession* pIDBCreateSession = NULL;
  IDBCreateCommand* pICreateCmd1    = NULL;
  IDBCreateCommand* pICreateCmd2    = NULL;
  IDBCreateCommand* pICreateCmd3    = NULL;
  
  // Initialize COM.
  if (FAILED(CoInitialize(NULL)))
  {
    // Display error from CoInitialize.
    return (-1);
  }
  
  // Get the memory allocator for this task.
  if (FAILED(CoGetMalloc(MEMCTX_TASK, &g_pIMalloc)))
  {
    // Display error from CoGetMalloc.
    goto EXIT;
  }
  
  // Create an instance of the data source object.
  if (FAILED(CoCreateInstance(CLSID_SQLOLEDB, NULL,
    CLSCTX_INPROC_SERVER, IID_IDBInitialize, (void**)
    &pIDBInitialize)))
  {
    // Display error from CoCreateInstance.
    goto EXIT;
  }
  
  // The InitFromPersistedDS function 
  // performs IDBInitialize->Initialize() establishing
  // the first application connection to the SQL Server.
  if (FAILED(InitFromPersistedDS(pIDBInitialize, L"MyDataSource",
    NULL, NULL)))
  {
    goto EXIT;
  }
  
  // The IDBCreateSession interface is implemented on the data source
  // object. Maintaining the reference we receive maintains the 
  // connection of the data source to the SQL Server.
  if (FAILED(pIDBInitialize->QueryInterface(IID_IDBCreateSession,
    (void**) &pIDBCreateSession)))
  {
    // Display error from pIDBInitialize.
    goto EXIT;
  }
  
  // Releasing this has no affect on the SQL Server connection
  // of the data source object because of the reference maintained by
  // pIDBCreateSession.
  pIDBInitialize->Release();
  pIDBInitialize = NULL;
  
  // The session created next receives the SQL Server connection of
  // the data source object. No new connection is established.
  if (FAILED(pIDBCreateSession->CreateSession(NULL,
    IID_IDBCreateCommand, (IUnknown**) &pICreateCmd1)))
  {
    // Display error from pIDBCreateSession.
    goto EXIT;
  }
  
  // A new connection to the SQL Server is established to support the
  // next session object created. On successful completion, the
  // application has two active connections on the SQL Server.
  if (FAILED(pIDBCreateSession->CreateSession(NULL,
    IID_IDBCreateCommand, (IUnknown**) &pICreateCmd2)))
  {
    // Display error from pIDBCreateSession.
    goto EXIT;
  }
  
  // pICreateCmd1 has the data source connection. Because the
  // reference on the IDBCreateSession interface of the data source
  // has not been released, releasing the reference on the session
  // object does not terminate a connection to the SQL Server.
  // However, the connection of the data source object is now 
  // available to another session object. After a successful call to 
  // Release, the application still has two active connections to the 
  // SQL Server.
  pICreateCmd1->Release();
  pICreateCmd1 = NULL;
  
  // The next session created gets the SQL Server connection
  // of the data source object. The application has two active
  // connections to the SQL Server.
  if (FAILED(pIDBCreateSession->CreateSession(NULL,
    IID_IDBCreateCommand, (IUnknown**) &pICreateCmd3)))
  {
    // Display error from pIDBCreateSession.
    goto EXIT;
  }
  
EXIT:
  // Even on error, this does not terminate a SQL Server connection 
  // because pICreateCmd1 has the connection of the data source 
  // object.
  if (pICreateCmd1 != NULL)
    pICreateCmd1->Release();
  
  // Releasing the reference on pICreateCmd2 terminates the SQL
  // Server connection supporting the session object. The application
  // now has only a single active connection on the SQL Server.
  if (pICreateCmd2 != NULL)
    pICreateCmd2->Release();
  
  // Even on error, this does not terminate a SQL Server connection 
  // because pICreateCmd3 has the connection of the 
  // data source object.
  if (pICreateCmd3 != NULL)
    pICreateCmd3->Release();
  
  // On release of the last reference on a data source interface, the
  // connection of the data source object to the SQL Server is broken.
  // The example application now has no SQL Server connections active.
  if (pIDBCreateSession != NULL)
    pIDBCreateSession->Release();
  
  // Called only if an error occurred while attempting to get a 
  // reference on the IDBCreateSession interface of the data source.
  // If so, the call to IDBInitialize::Uninitialize terminates the 
  // connection of the data source object to the SQL Server.
  if (pIDBInitialize != NULL)
  {
    if (FAILED(pIDBInitialize->Uninitialize()))
    {
    // Uninitialize is not required, but it fails if an
    // interface has not been released. We can use it for
    // debugging.
    }
    pIDBInitialize->Release();
  }
  
  if (g_pIMalloc != NULL)
    g_pIMalloc->Release();
  
  CoUninitialize();
  
  return (0);
}
  

Connecting SQLOLEDB session objects to a SQL Server can generate significant application overhead for applications that continually create and release session objects. The overhead can be minimized by managing SQLOLEDB session objects efficiently. SQLOLEDB applications can keep the SQL Server connection of a session object active by maintaining a reference on at least one interface of the object.

For example, maintaining a pool of command creation object references keeps active connections for those session objects in the pool. As session objects are required, the pool maintenance code passes a valid IDBCreateCommand interface pointer to the application function requiring the session. When the application function no longer requires the session, the function returns the interface pointer back to the pool maintenance code rather than releasing the application’s reference to the command creation object.

Note   In the above example, the IDBCreateCommand interface is used because ICommand implements GetDBSession, the only function in command or rowset scope that allows an object to determine the session on which it was created. Therefore, a command object, and only a command object, allows an application to retrieve a data source object pointer from which additional sessions can be created.