Calling Oracle Retrieval Stored Procedure

Posts   
 
    
xc_lw2000
User
Posts: 48
Joined: 12-Dec-2006
# Posted on: 20-Jan-2009 10:49:54   

I'm using v2.5. I retrive dataset from store procedure.But I got "ora-01000 maximum open cursors exceeded" error sometimes.Didn't LLBL close cursor itself?

If I close cursor in store procedure,then it will return null other than a dataset.So there are only open statement no close statement in the SP.

Any solution?

xc_lw2000
User
Posts: 48
Joined: 12-Dec-2006
# Posted on: 20-Jan-2009 17:19:49   

Anybody know this?

MTrinder
User
Posts: 1461
Joined: 08-Oct-2008
# Posted on: 20-Jan-2009 21:16:19   

Are you "Disposing" of your adapters after the retrieval calls...?

either in a "FinallY" clause


try
{
    adapter.DoStuff()
}
catch
{
}
finally 
{
    adapter.Dispose
}

or by


using (DataAccessAdapter adatper = new DataAccessAdapter())
{
    adapter.DoStuff()
}

Matt

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 22-Jan-2009 10:53:31   

the generated method which calls the proc and fills the dataset is:


/// <summary>
/// Calls the specified retrieval stored procedure in the Oracle database. Fills the
/// specified DataSet. Will participate in the transaction if a transaction is in progress.
/// </summary>
/// <param name="storedProcedureToCall">Stored procedure to call</param>
/// <param name="parameters">array of parameters to specify</param>
/// <param name="dataSetToFill">DataSet to fill by the stored procedure</param>
/// <returns>true if succeeded, false otherwise</returns>
public virtual bool CallRetrievalStoredProcedure(string storedProcedureToCall, OracleParameter[] parameters, DataSet dataSetToFill)
{
    OracleCommand command = new OracleCommand(CreateCorrectStoredProcedureName(storedProcedureToCall));
    command.Connection = (OracleConnection)base.GetActiveConnection();
    if(base.IsTransactionInProgress)
    {
        ((IDbCommand)command).Transaction = (OracleTransaction)base.PhysicalTransaction;
    }
    command.CommandType = CommandType.StoredProcedure;
    command.CommandTimeout = base.CommandTimeOut;

    for(int i=0;i<parameters.Length;i++)
    {
        command.Parameters.Add(parameters[i]);
    }
    
    try
    {
        base.OpenConnection();
        command.ExecuteNonQuery();

        // for each cursor parameter, create a datatable in dataset and fill it. 
        using(OracleDataAdapter adapter = (OracleDataAdapter)CreateNewPhysicalDataAdapter())
        {
            for (int i = 0; i < parameters.Length; i++)
            {
                if(parameters[i].OracleDbType == OracleDbType.RefCursor)
                {
                    DataTable tableToFill = dataSetToFill.Tables.Add(parameters[i].ParameterName);
                    adapter.Fill(tableToFill, (OracleRefCursor)parameters[i].Value);
                }
            }
        }
    }
    finally
    {
        command.Dispose();
        // clean up a dangling automaticly opened connection if needed.
        if(!(base.KeepConnectionOpen || base.IsTransactionInProgress))
        {
            base.CloseConnection();
        }
    }

    return true;
}

(DataAccessAdapter)

the methods which call this piece of code are the methods in the RetrievelProcedures class in the generated code. If you look at these routines, you'll see that a Dispose() call is issued on the cursor parameters. So I don't know what more to do, as the fetching itself (the cursor consumption) is done inside the OracleDataAdapter object.

I'm not sure if your template version contains the code above and the dispose calls. If not, please let us know. Also it would be great if you'd mention which oracle provider you're using (MS Oracle or ODP.NET), which version (9i, 10g etc.) and if you've checked with oracle if there's a patch for your odp.net version (if you're using ODP.NET)

Frans Bouma | Lead developer LLBLGen Pro