StackOverflowException в синглтоне - PullRequest
0 голосов
/ 24 апреля 2018

Мой синглтон выбрасывает StackOverflowException, но вчера он работал нормально, и единственным изменением стала база данных в строке подключения.Это консольное приложение, и отладка очень сложна:

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>

Ребята, можете ли вы показать мне, что не так и почему вчера все работало нормально?

РЕДАКТИРОВАТЬ:

Я использую Singleton, чтобы сделать много вещей.Я знаю, что проблема в синглтоне, потому что мое приложение показывает StackoverflowException без лога, который является одним из мест, где я использую синглтон.Ниже мой LogHelper.WriteMessage метод, который вызывается в первой строке программы и говорит «Привет, приложение работает прямо сейчас»:

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);
    }

1 Ответ

0 голосов
/ 24 апреля 2018

Ваш "синглтон" действительно рекурсивен на некоторых путях.Что произойдет, если эта строка

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

выдаст исключение, например, если строка подключения недопустима?Вы регистрируете это исключение с помощью WriteLog, которое снова ссылается на синглтон с помощью

using (OracleConnection conn = OracleSingleton.Instance)

Так что, если строка подключения недопустима или создание соединения постоянно завершается неудачей по другой причине - вы переходите в рекурсию и в конечном итоге заканчиваете StackOverflowException, когдапространство стека исчерпано.

Кстати, с помощью

using (OracleConnection conn = OracleSingleton.Instance)

вы также избавляетесь от своего соединения, что делает его непригодным для последующих вызовов.

Лучший способ решить эточтобы просто избавиться от синглтона, в этом нет необходимости.Это плохая практика - иметь глобальное соединение - просто создавайте его каждый раз, когда вам это нужно, и удаляйте (закрывайте), когда вы закончите с ним.Пул подключений будет управлять остальным за вас.

Если вы по какой-то причине не хотите проводить серьезный рефакторинг, по крайней мере, измените его на что-то вроде этого:

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

И используйте как выуже делаем:

using (OracleConnection conn = OracleSingleton.Create())
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...