简体   繁体   中英

StackOverflowException on Singleton

My Singleton is throwing a StackOverflowException , but yesterday it worked fine and the unique change was the database in the Connection String. It is a console application and the debug is very complicated:

class OracleSingleton
{
    private static OracleConnection instance;

    private OracleSingleton() { }

    public static OracleConnection Instance
    {
        get
        {
            if (instance == null)
            {
                try
                {
                    instance = new OracleConnection(ConfigurationManager.ConnectionStrings["OracleConnection"].ConnectionString);
                }
                catch (Exception ex)
                {
                    LogHelper.WriteMessage("Error trying to create a new connection. - " + ex.Message.ToString() + " - " + ex.InnerException.ToString().Trim());
                }
            }
            return instance;
        }
    }
}

My App.config:

<configuration>
  <connectionStrings>
    <add name="OracleConnection" connectionString="Password=somepassword;Persist Security Info=True;User ID=someuser;Data Source=DATABASE01"/>
  </connectionStrings>
    //Some stuff
</configuration>

Can you guys show me what is wrong and why yesterday it worked fine?

EDIT:

I use the Singleton to do a lot of things. I Know that the problem is in the singleton because my application shows the StackoverflowException without log anything, who is one of the places where I use the Singleton. Below, my LogHelper.WriteMessage method, who is called at the first line of program to say" Hi, the application is running right now ":

public static void WriteMessage(string info)
{
    using (OracleConnection conn = OracleSingleton.Instance)
    {
        using (OracleCommand cmd = new OracleCommand("INSERT INTO TB_LOG (DT_LOG, ID_PERMISSAO, ID_USUARIO, NM_USUARIO, DS_LOG) VALUES (TO_CHAR (SYSDATE, 'MM-DD-YYYY HH24:MI:SS'), 5025, 5025, 'IMPORTADORCAIXA', '" + info + "')", conn))
        {
            try
            {
                conn.Open();
                cmd.ExecuteNonQuery();
            } catch (Exception ex)
            {
                Console.WriteLine(DateTime.Now + " - Erro ao conectar com o banco. por favor, verifique o erro: " + ex.Message.ToString() + ", " + cmd.CommandText.ToString());
            }
        }
    }
    new LogHelper();
    eventLog.WriteEntry(info);
    Console.WriteLine(DateTime.Now + " - " + info);
    }

Your "singleton" is indeed recursive on some paths. What happens if this line

instance = new OracleConnection(ConfigurationManager.ConnectionStrings["OracleConnection"].ConnectionString);

throws exception, for example if connection string is invalid? You log that exception with WriteLog which again references singleton with

using (OracleConnection conn = OracleSingleton.Instance)

So if connection string is invalid, or connection creation constantly fails for other reason - you go into recursion and eventually end with StackOverflowException when stack space is exhausted.

By the way, with

using (OracleConnection conn = OracleSingleton.Instance)

you also dispose your connection, making it unusable for subsequent invocations.

Best way to resolve it is to just get rid of singleton, there is no need for it. It's bad practice to have global connection - just create it every time you need it and dispose (close) when you are done with it. Connection pool will manage the rest for you.

If you don't want to do serious refactoring for some reason, at least change to something like this:

public static OracleConnection Create() {
    // no need to catch any exceptions here
    return new OracleConnection(ConfigurationManager.ConnectionStrings["OracleConnection"].ConnectionString);
}

And use as you already do:

using (OracleConnection conn = OracleSingleton.Create())

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM