FIX: An Access Violation Occurs in ADO Under Heavy Stress with .NET COM Interop or Java (321415)



The information in this article applies to:

  • ActiveX Data Objects (ADO) 2.6
  • ActiveX Data Objects (ADO) 2.7
  • Microsoft Data Access Components 2.6
  • Microsoft Data Access Components 2.7

This article was previously published under Q321415

SYMPTOMS

In a Microsoft .NET program that uses ActiveX Data Objects (ADO) through COM Interop, or in a Java program that uses ADO, an access violation may occur when you call the Close method of the ADO Connection object. The access violation occurs only under heavy stress when multiple threads are connecting to and disconnecting from the backend database server. This issue is not specific to any particular OLE DB provider or ODBC driver.

CAUSE

Each ADO Connection object internally maintains a collection of Recordset and Command objects that are associated with that connection. Each Recordset object also maintains a reference to its associated Command objects. When the connection is closed, it cleans up its objects and releases the references that it is holding. While the Connection object is cleaning up its collection of Recordset and Command objects, a race condition can occur between the Recordset object's reference on the Command object and the Connection object's reference on the Command object. The nondeterministic timing of garbage collection in .NET and Java eventually triggers the race condition that causes the access violation. The following call stack is typical when the problem occurs:

ChildEBP RetAddr  Args to Child              
00aaf6d8 1f447532 00000020 0f648448 1f436fc9 msado15!CExecInfo::Term+0x44
00aaf6e4 1f436fc9 0f5d8a14 0f5d8a14 0f5d8ab8 msado15!CExecInfo::Init+0x9 
00aaf710 1f437111 0f5d8a14 0f5d8a08 1f437216 msado15!CParameters::GetAvailableOutputParams+0xd3
00aaf71c 1f437216 0f5ee274 0f5ee190 00000000 msado15!CParameters::EmptyParameters+0x9
00aaf758 1f43a5c5 00aaf984 0f5ee190 001405a8 msado15!CCommand::Close+0x2f
00aaf828 1f44494b 00aaf880 00000002 00000000 msado15!CConnection::_Close+0x348
00aaf830 00000002 00000000 00000000 00000000 msado15!CConnection::Close+0x8d

RESOLUTION

To resolve this problem, obtain the latest service pack for Microsoft SQL Server 2000. For additional information, click the following article number to view the article in the Microsoft Knowledge Base:

290211 INF: How to Obtain the Latest SQL Server 2000 Service Pack

The English version of this fix should have the following file attributes or later:
   Date         Time   Version      Size     File name
   -----------------------------------------------------
   16-Apr-2002  12:49  2.70.8616.0  753,664  Msado15.dll

STATUS

Microsoft has confirmed that this is a problem in the Microsoft products that are listed at the beginning of this article. This problem was first corrected in Microsoft SQL Server 2000 Service Pack 3.

MORE INFORMATION

In addition to the fixed version of the msado15.dll file, you can use the following two coding practices when you are programming with ADO in a language that is subject to garbage collection. These practices reduce the likelihood of this problem.
  • Explicitly release references to COM objects when you are finished using them.

    In .NET languages such as Microsoft Visual C# .NET and Microsoft Visual Basic .NET, you can do this by calling the ReleaseComObject method. The following C# example demonstrates this method:
    //m_connection is an ADODB.ConnectionClass object
    if( m_connection != null && 
         m_connection.State == ( int )ADODB.ObjectStateEnum.adStateOpen )
    {
         try
         {
              m_connection.Close();
              Marshal.ReleaseComObject(m_connection);
         }
         catch (COMException e )
         {
              Console.WriteLine( "Error - " + e.Message );
         }
    }
    m_connection = null;
    In Java, you do this by using a call to the release method that is defined in the com.ms.com.ComLib class. For additional information about this method and other coding practices for using COM in Java, click the article number below to view the article in the Microsoft Knowledge Base:

    296994 PRB: Java Components May Perform Poorly in COM+

  • Use the ADO primary interop assembly. When you use ADO through COM Interop in .NET, use the ADO primary interop assembly instead of creating your own wrapper classes by using the Type Library importer (Tlbimp.exe). The problem that is described in this article may occur whether you use the primary interop assembly or the classes that are generated by Tlbimp, but in general it is a good idea always to use the primary interop assembly. For additional information, click the article number below to view the article in the Microsoft Knowledge Base:

    318559 INFO: Using the Primary Interop Assembly for ADO (ADODB) in Visual Studio .NET

    When you use the primary interop assembly, the compiler permits several different object names for the various ADO objects. For ADO to work properly, the classes that you use must all contain the word "Class" at the end of the class name. For example:

    ADODB.ConnectionClass
    ADODB.RecordsetClass
    ADODB.CommandClass

    When you use these objects, use ReleaseComObject as described earlier in this article so that COM has an opportunity to release the reference.

Modification Type:MinorLast Reviewed:9/27/2005
Keywords:kbHotfixServer kbQFE kbSQLServ2000sp3fix kbbug kbfix kbSQLServ2000preSP3fix KB321415