Objects, References, and Reference Counting

SQL-DMO

SQL-DMO

Objects, References, and Reference Counting

Any COM application receives an object reference through which it controls an instance of a SQL-DMO object. This is true regardless of the application development tool.

COM defines reference counting as the mechanism for COM server-created object lifetime management. When a COM client application receives an object reference, the reference count on the object instance is implicitly incremented. When the COM client is finished with the object reference, it decrements the reference count using the Release function. When the reference count is zero, the COM server may, at its discretion, free resources used to implement the object instance.

When using an OLE Automation controller, such as Microsoft®Visual Basic®, the controller generally maintains references and reference counts as directed by the scope of the variable referencing the object. For example, this Visual Basic subroutine shows an application receiving a reference to a Databases collection, and references to multiple SQL-DMO Database and OLE BSTR objects:

Private Sub ListDatabases(oSQLServer as SQLDMO.SQLServer)
    Dim oDatabase as SQLDMO.Database
    For Each oDatabase in oSQLServer.Databases
        lstDatabases.AddItem oDatabase.Name
    Next oDatabase
End Sub

No reference is ever released explicitly by the developer. Instead, Database object references are released as the object variable is reassigned in the For Each loop. The reference maintained on the Databases collection and the last reference obtained on a Database object in the collection are released as the variables go out of scope with the End Sub statement. The OLE BSTR object references are hidden, and handled, even more effectively.

The C/C++ application developer must be aware of and control reference counts as necessary. When an object reference is received from the SQL-DMO library, the application implicitly increases the reference count on an instance of the SQL-DMO object, as shown here:

void CDlgSelectDatabase::GetDatabases(LPSQLDMOSERVER pServer)
    {
    LPSQLDMODATABASE    pDatabase;
    BSTR                bstrDBName;
    LONG                nDatabase;
    LONG                nDatabases;

    HRESULT             hr;

    if (FAILED(hr = pServer->GetDatabaseCount(&nDatabases)))
        return;

    for (nDatabase = 0; nDatabase < nDatabases && SUCCEEDED(hr);
        nDatabase++)
        {
        pDatabase = NULL;
        bstrDBName = NULL;

        // Getting the next Database object from the collection
        // increases the client initiated reference count by one.
        hr = pServer->GetDatabaseByOrd(nDatabase, &pDatabase);

        // Getting a string back from SQL-DMO is also getting a
        // reference on an object. Be sure to release it.
        if (SUCCEEDED(hr))
            hr = pDatabase->GetName(&bstrDBName);

        if (SUCCEEDED(hr))
            m_listboxDatabases->AddString(bstrDBName);

        if (bstrDBName != NULL)
            SysFreeString(bstrDBName);

        if (pDatabase != NULL)
            pDatabase->Release();
        }
    }

For the C++ developer, SQL-DMO defines in Sqldmo.h the scope-aware, template classes CTempOLERef and CTempBSTR that can simplify development.

See Also

CTempBSTR

CTempOLERef