Когда использовать SqlConnection.ClearAllPools () в c #

Я заметил, что мой код содержит ошибкиsqlWrite.ExecuteNonQuery(); после выполнения 200 запросов на вставку за пару секунд. Я всегда думал, чтоusing обеспечит правильное повторное использование ресурсов и не будет необходимости ничего делать. Это первый раз, когда я получаю эту ошибку, и я почти три года имею дело с sql / c #, делая разные вещи.

<code>using (SqlConnection varConnection = Locale.sqlConnectOneTime(Locale.sqlDataConnectionDetails)) 
{
    using (var sqlWrite = new SqlCommand(preparedCommand, varConnection)) 
    {
        sqlWrite.Parameters.AddWithValue("@var_agr_fname", var_agr_fname == "" ? (object) DBNull.Value : var_agr_fname);
        sqlWrite.ExecuteNonQuery();
    }
}


public static SqlConnection sqlConnectOneTime(string varSqlConnectionDetails)
{
    var sqlConnection = new SqlConnection(varSqlConnectionDetails);
    try
    {
        sqlConnection.Open();
    }
    catch
    {
        DialogResult result = MessageBox.Show(new Form {TopMost = true},
                                              "Błąd połączenia z bazą danych. Czy chcesz spróbować nawiązac połączenie ponownie?",
                                              "Błąd połączenia (000001)",
                                              MessageBoxButtons.YesNo,
                                              MessageBoxIcon.Stop);
        if (result == DialogResult.No)
        {
            if (Application.MessageLoop)
            {
                Application.Exit(); // Use this since we are a WinForms app
            }
            else
            {
                Environment.Exit(1); // Use this since we are a console app
            }
        }
        else
        {
            sqlConnection = sqlConnectOneTime(varSqlConnectionDetails);
        }
    }
    return sqlConnection;
}
</code>

Сообщение об ошибке:A transport-level error has occurred when sending the request to the server. (provider: Shared Memory Provider, error: 0 - No process is on the other end of the pipe.)

Учитывая совет дляэта ошибка Я должен использоватьSqlConnection.ClearAllPools(); чтобы убедиться, что соединения сброшены или отброшены правильно. Таким образом, я могу использовать это, но вопрос в том, где это использовать и когда? Как узнать, будет ли предел превышен? Где предел? на 50/150/200? или я должен использовать это каждый раз в цикле?

 Rango04 апр. 2012 г., 23:59
@Madboy: Похоже, вы заново изобрели Connection-Pool. Он всегда использует соединения, если они закрыты, и не может использовать их, если они открыты. Вы также видели ссылки в ответах на другие вопросы (не принимаются)?social.msdn.microsoft.com/Forums/en-US/sqldataaccess/thread/… а такжеblogs.msdn.com/b/spike/archive/2009/04/16/…
 Erik Philips05 апр. 2012 г., 00:11
@AustinSalonen Вы правы ... тьфу.
 MadBoy05 апр. 2012 г., 00:23
@ErikPhilipsmsdn.microsoft.com/en-us/library/8xx3tyca.aspx он повторно используется при использовании внутриusing и условия применяются
 Erik Philips04 апр. 2012 г., 23:54
Почему бы не раскрутить только одинSqlConnection и использовать это исключительно? Похоже, вы используете какие-либо темы, так что это должно работать без каких-либоhacky SqlConnection.ClearAllPools().
 MadBoy04 апр. 2012 г., 23:57
У меня есть метод, который я повторно использую, используя его один или несколько раз. Все это делается от установления соединения (или использования соединения, которое уже подключено) до возврата соединения в пул. Это советы, которые я получил. Таким образом, я всегда повторно использую соединение, если оно открыто, и если оно закрыто, я всегда открываю его. Никогда не было проблем с этим до сих пор. Я думал / мне сказали, что пул соединений позаботится об этом для меня, когда я используюusing :-) Кажется, нет :-)

Ответы на вопрос(3)

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

Кроме того, ваш код должен работать нормально, но если вы получаетеNo process is on the other end of the pipe. ошибка, которая означает, что что-то не так с вашей базой данных и / или SQL Server. Похоже, что он засорен и просто не принимает больше соединений. Если вы запустите пакет вставок за короткое время, сделайте их по одному соединению, если это возможно.ClearAllPools это способ восстановиться, когда что-то не так, и было бы лучше выяснить, что это, а не скрывать это. Это похоже на прием парацетамола, когда у вас болит зуб, и он никогда не посещает стоматолога.

Другое дело, что использование нескольких SqlConnections создает отдельную транзакцию для каждого соединения. Это увеличивает нагрузку на SQL Server, хотя, безусловно, может выполнять более сотен транзакций в секунду.

Кроме того, вы можете изменить транспорт на именованный канал и TCP, чтобы посмотреть, изменит ли он что-либо.

 05 апр. 2012 г., 00:51
Это правда, что настоящее соединение с БД останется открытым и будет использоваться повторно, но создание SqlConnection сотни раз в несколько секунд, а затем оставление его для сборщика мусора является ненужной нагрузкой на ресурсы (главным образом GC)
 05 апр. 2012 г., 00:56
Проведите некоторое тестирование - введите задержку между вставками и посмотрите, что произойдет. Также посмотрите, изменит ли он все вставки на одном соединении.
 05 апр. 2012 г., 01:18
Другая идея: измените транспорт на именованный канал и tcp, чтобы проверить, помогает ли это
 MadBoy05 апр. 2012 г., 01:04
Я пробовал с 50 мс спать не ходи. Также я проверил, и есть только 3 соединения с базой данных (1-2 сделано в SQL Management Studio и 1 во время цикла. Таким образом, соединение используется повторно правильно (кажется).
 MadBoy05 апр. 2012 г., 00:46
Обычно это происходит на 3 разных компьютерах, так что это не связано с сервером или, по крайней мере, что-то, что я вижу. На странице Microsoftmsdn.microsoft.com/en-us/library/8xx3tyca.aspx#Y1790 они предполагают, что если строка подключения та же самая, соединение останется открытым для следующих соединений. Так что, если я делаю их все в одном цикле foreach, это, вероятно, только одно соединение. Конечно, способ является немного более коротким примером, поскольку имеется около 20 параметров вместо просто 1. Но это не повлияло на него ранее. И проблема начинается с 180 вставки.

"I have a method that I reuse by using it either once or more times. It does it all from establishing a connection (or using the one that's already connected) to returning the connection to the pool. Those are advices I got. This way I always reuse the connection if it's open and if it's closed I always open it up."

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

So close the connection in the catch block:

public static SqlConnection sqlConnectOneTime(string varSqlConnectionDetails) {
    var sqlConnection = new SqlConnection(varSqlConnectionDetails);
    try {
        sqlConnection.Open();
    } catch {
        //log and
        sqlConnection.Close();
        throw
    }
    return sqlConnection;
}

EditЧестно говоря, я бы вообще не использовал такие фабричные методы. Они просто источник невоспроизводимых ошибок. Сколько времени занимает создание и открытие соединения, где вы его используете?

using(SqlConnection varConnection = new SqlConnection(Locale.sqlDataConnectionDetails)) {
    using (var sqlWrite = new SqlCommand(preparedCommand, varConnection)) {
        sqlWrite.Parameters.AddWithValue("@varSecus_agr_fname", varSecus_agr_fname == "" ? (object) DBNull.Value : varSecus_agr_fname);
        varConnection.Open();
        sqlWrite.ExecuteNonQuery();
    }
}

Первые две ссылки взяты из вашего связанного вопроса (не принятого ответа), они также могут быть полезны:

http://social.msdn.microsoft.com/Forums/en-US/sqldataaccess/thread/9609559d-f7ce-4bd8-97d0-0003ff7c9c98/ http://blogs.msdn.com/b/spike/archive/2009/04/16/a-transport-level-error-has-occurred-when-sending-the-request-to-the-server-provider-tcp-provider-error-0-an-existing-connection-was-forcibly-closed-by-the-remote-host.aspx ExecuteReader requires an open and available Connection. The connection's current state is Connecting (not the same subject but apparently a similar background)
 05 апр. 2012 г., 00:12
@ Мэдбой: Вы правы, исправлено. Честно говоря, я бы вообще не использовал такие фабричные методы. Они просто источник невоспроизводимых ошибок. Сколько времени занимает создание и открытие соединения, где вы его используете?
 MadBoy05 апр. 2012 г., 00:18
stackoverflow.com/questions/2230062/… где он говорит, что .Close вызывается .Dispose и Dispose является естественным при использованииusing а также мой другой вопросstackoverflow.com/questions/2150580/…
 MadBoy05 апр. 2012 г., 00:21
Я понимаю, что я мог бы использовать новый SqlConnection (как предложено) внутри Вставки, но наличие его во внешнем методе дает мне возможность "восстановить соединение" если это не удастся (предупредить пользователя и дать ему параметр «Переподключить Да / Нет»), а также даст мне возможность добавить некоторую логику ошибок. В противном случае мне придется дублировать много кода. Также не будет вашего нового SqlConnection внутри метода using быть точно таким же, как мой метод только в другом методе? В конце концов, все, что я делаю, это вызывает другой метод внутри использования, который в любом случае должен удалить соединение.
 MadBoy05 апр. 2012 г., 00:15
Что ж, я могу найти его (это где-то в вопросах моего профиля), когда я искал правильное использование соединений Open / Close, было предложено (и проголосовало), что если я открою Connection и не закрою его явно, он будет возвращен бассейн поusing и этоopen Соединение в пуле все еще может быть повторно использовано в следующих запросах без необходимости устанавливать соединение (следовательно, оно быстрее). Если я явно скажу ему открыть, а затем всегда закрыть, следующий запрос займет столько же времени, сколько и первый.
 MadBoy05 апр. 2012 г., 00:09
Не удалось бы окончательно закрыть соединение, если попытка все равно будет успешной? Вернуть мне закрытую строку подключения в любом случае? По сути, ваш код открывает соединение и закрывает его за секунду. Хотя мой код должен был открыть открытое соединение, чтобы его можно было использовать, и когда это будет сделаноusing должен очистить его / вернуться в бассейн.
Решение Вопроса

Те 2 ошибки:

A transport-level error has occurred when sending the request to the server. (provider: TCP Provider, error: 0 - An existing connection was forcibly closed by the remote host.)

A transport-level error has occurred when sending the request to the server. (provider: Shared Memory Provider, error: 0 - No process is on the other end of the pipe.)

Были связаны со значением DateTime, вставляемым в SQL с датой до 1900 года. Здесь действует правило Microsoft: не храните значение DateTime меньше 1900 года в значении DateTime в SQL. Вместо этого используйте строку ...

Ваш ответ на вопрос