Go Back   Attunity Integration Technology Forum > Integration Technology > Data Access > ADO.NET Provider


Contact Us to hear more about

AIS Server Memory Leaks When Using ADO.NET Clients

Attunity AIS - Data Integration Technology - ADO.NET Provider


Post New Thread Reply
 
LinkBack Thread Tools Display Modes
  #1 (permalink)  
Old 09-05-2007, 03:14 PM
DrorHarari DrorHarari is offline
Chief Product Architect
 
Join Date: Sep 2006
Posts: 183
My Photos: (3)
Rep Power: 6
DrorHarari is on a distinguished road
Default AIS Server Memory Leaks When Using ADO.NET Clients

Several developers reported that when they test applications that use ADO.NET clients to access AIS servers they see indications of memory leaks on the AIS server that eventually causes allocation failures or otherwise excessive server load.

As it happens, there is a common programming error when using ADO.NET which is causing this problem. In this short article we'll discuss the problem and the easy way to resolve it. This problem is applicable to any ADO.NET provider and specifically to:
  • The Microsoft ADO.NET provider for OLEDB providers
  • The Microsoft ADO.NET provider for ODBC providers
  • The Attunity ADO.NET provider
The problem, in a nutshell, is manifested by accomulation of 'QuerySpec' objects on the server (which in the Attunity speak means 'prepared statements') and some times other types of objects (e.g, cursors or rowsets in the Attunity speak).

The problem exists for both C# and VB.NET and it stems from the fact that the .NET architecture does not use reference counting like the COM architecture (and its ADO library) so when a reference to an object in the code goes out of scope, it is not necessarily released and as a result, related resources on the server are also kept. Since the reference is gone, there is no direct way to release these resources and eventually the server process exhausts its resources and terminates.

An example may make the problem clearer. The following is an excerpt from a module called OleHelper.c:

Code:
public static OleDbDataReader ExecuteReader(string constr, string sql, params OleDbParameter[] parms)
{
    OleDbConnection conn = new OleDbConnection(constr); 
    
    try
    {
        OleDbCommand cmd = new OleDbCommand();

        if (conn.State != ConnectionState.Open)
            conn.Open();
 
        cmd.Connection = conn;
        cmd.CommandText = sq;;

        if (parms != null)
        {
            foreach (OleDbParameter parm in parms)
                cmd.Parameters.Add(parm);
        }

        OleDbDataReader rdr =  cmd.ExecuteReader(CommandBehavior.CloseConnection);
        
        return rdr;
    }
    catch (OleDbException ex)
    {
        // Log something...
        throw new ServerException(ServerErrorCode.DataError, ex.ToString() , ErrorSeverity.Error);
    }
}
The problem with this code is that when the function returns and the 'cmd' object goes out of scope, the server resources associated with that object remain held until it gets garbage collected by the .NET framework. This may happen after long time during which time server resources are accomulated.

The general guideline in the .NET framework is that objects that offer a Dispose() method must be disposed explicitly before going out of scope. In the case of the AIS ADO.NET provider, objects the following classes shuold be disposed:
  • AisCommand
  • AisCommandBuilder
  • AisConnection
  • AisDataReader
  • AisTransaction
In the case of the Microsoft ADO.NET provider for OLEDB providers, objects the following classes shuold be disposed:
  • OleDbCommand
  • OleDbCommandBuilder
  • OleDbConnection
  • OleDbDataAdapter
  • OleDbDataReader
  • OleDbTransaction
The code above fails indeed to call the Dispose method on the 'cmd' object but, fortunately, there is a very simple way to make sure the object is properly destructed.

The above code can be written correctly as follows:

Code:
public static OleDbDataReader ExecuteReader(string constr, string sql, params OleDbParameter[] parms)
{
    try
    {
        using (OleDbConnection conn = new OleDbConnection(constr))
        {    
            if (conn.State != ConnectionState.Open)
                conn.Open();
     
            using (OleDbCommand cmd = new OleDbCommand())
            {
                cmd.Connection = conn;
                cmd.CommandText = sql;
        
                if (parms != null)
                {
                    foreach (OleDbParameter parm in parms)
                        cmd.Parameters.Add(parm);
                }
        
                OleDbDataReader rdr =  cmd.ExecuteReader(CommandBehavior.CloseConnection);
                
                return rdr;
            }
        }
    }
    catch (OleDbException ex)
    {
        // Log something...
        throw new ServerException(ServerErrorCode.DataError, ex.ToString() , ErrorSeverity.Error);
    }
}
The C# 'using' keyword makes sure that the Dispose() method of 'cmd' (as well as of 'conn') is called when the block is exited. This will, in turn,release the server side QuerySpec objects. The Dispose() method of 'cmd' will be called even in case of an exception inside the 'using' block. Note that since this is OLEDB, connection pooling is in effect so the automatic connection close does not really close the connection and its backend resources. It only moves the connection with its many unclosed commands into the pool to be reused again and again.

In case you work in VB.NET, a similar pattern can be used:

Code:
Public Function ExecuteReader(constr As String, sql As String) As OleDbDataReader
    Try
        Using conn As New OleDbConnection(constr)
            If conn.State <> ConnectionState.Open Then
                conn.Open()
            End If

            Using cmd As New OleDbCommand
                cmd.Connection = conn
                cmd.CommandText = sql

                ExecuteReader = cmd.ExecuteReader(CommandBehavior.CloseConnection)
            End Using
        End Using

    Catch ex As Exception
        ' Log something
        throw ex;
    End Try
    
End Function
__________________
/d -|8-) DrorHarari

To Find Out more About Attunity Technology:
Attunity
or:
Contact Us
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Post New Thread Reply



Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On


All times are GMT -4. The time now is 12:07 AM.


Content Relevant URLs by vBSEO 3.0.0
© 2009 Attunity Ltd. All rights reserved.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235