Что означает сброс соединения? System.Data.SqlClient.SqlException (0x80131904)

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

Когда я запускаю немного кода для локальной базы данных, он работает нормально. Когда я использую удаленную базу данных, я получаю сообщение об ошибке. Это происходит в середине выполнения программы. Обновление DBup запускается, а затем ручной запрос завершается с ошибкой с этим исключением:

System.Data.SqlClient.SqlException (0x80131904): сброс подключения приводит к состоянию, отличному от исходного входа в систему. Логин не работает. Ошибка входа для пользователя 'sa'.

Я создаю SqlConnection вручную с помощью new SqlConnection(), а также использую DbUp

Я не уверен, что я могу делать неправильно. Ни с чего начать отладку этого. ConnectionString не меняется, и я всегда использую sa для подключения к базе данных.

Хороший вопрос для начала: что означает сброс соединения? Как я это делаю?


person pitermarx    schedule 03.09.2020    source источник
comment
Если база данных подключена к серверу, никогда не используйте свойство AttachDB (localdb) в строке подключения (удалить). Сервер владеет файлом базы данных mdf и не позволяет пользователям напрямую обращаться к файлу. Вы должны подключиться к базе данных через сервер и экземпляр. Для отладки я использую SQL Server Management Studio. Окно входа в систему SSMS покажет имя сервера и экземпляра, которые следует использовать в строке подключения С#. В окне входа также отображаются учетные данные окна, которые в строке подключения эквивалентны Integrated Security = true и используют учетные данные Windows пользователей (или групп).   -  person jdweng    schedule 03.09.2020
comment
@Igor Игорь, решение состоит в том, чтобы использовать простой ado.net, что я и делаю.   -  person pitermarx    schedule 03.09.2020
comment
@jdweng Я не использую (localdb), это просто экземпляр SQLServer, работающий на локальном хосте   -  person pitermarx    schedule 03.09.2020
comment
Для работы соединения локальный компьютер и удаленный компьютер должны иметь одинаковые учетные данные. Обычно я делаю учетные данные базы данных группой пользователей окна, а затем добавляю пользователей в группу. Группа должна быть назначена как на локальной, так и на удаленной машине. Компания обычно имеет настройку групповой политики, которую можно использовать для учетных данных базы данных.   -  person jdweng    schedule 03.09.2020
comment
@jdweng это 2 совершенно разных сервера с разными учетными данными. Совершенно разные строки подключения. Просто при использовании локального сервера ошибка не возникает   -  person pitermarx    schedule 03.09.2020
comment
Используйте ту же подачу/экземпляр, что и в окне входа в систему SSMS. В окне должны отображаться учетные данные окна. Затем добавьте в строку подключения Integrated Security = true и удалите имя пользователя/пароль из строки подключения.   -  person jdweng    schedule 03.09.2020
comment
Я не использую встроенную безопасность ни в одном из них. Он даже не включен   -  person pitermarx    schedule 03.09.2020
comment
Просто чтобы уточнить, исключение возникает на полпути выполнения. Некоторые запросы выполняются успешно, а затем нет   -  person pitermarx    schedule 03.09.2020
comment
Интегрированная безопасность = true просто означает, что вы используете учетные данные пользователя, которые в SSMS отображаются как учетные данные Windows.   -  person jdweng    schedule 03.09.2020
comment
Те же запросы следует тестировать в SSMS, что дает более качественные сообщения об ошибках. Я подозреваю, что некоторые из ваших таблиц имеют разные учетные данные, и SSMS укажет на эти ошибки, чтобы вы могли их исправить.   -  person jdweng    schedule 03.09.2020
comment
как я могу проверить, имеет ли таблица разные учетные данные? Почему это происходит только дистанционно?   -  person pitermarx    schedule 03.09.2020
comment
Еще одна часть информации заключается в том, что я всегда использую пользователя sa   -  person pitermarx    schedule 03.09.2020
comment
I'm always using the sa user это очень плохая привычка, из-за которой вас могут взломать. Никогда не используйте эту учетную запись в коде приложения. Что касается того, что не так - вы должны предоставить информацию в самом вопросе. Аутентификация учетной записи SQL, очевидно, работает, иначе тысячи разработчиков заметили бы это 23 года назад.   -  person Panagiotis Kanavos    schedule 03.09.2020
comment
@pitermarx опубликуйте свой код, строку подключения (без пароля), строку, которая выдает, и полную строку исключения, а не только часть сообщения. Вы можете легко получить это с помощью Exception.ToString() или нажав на ссылку Copy Details во всплывающем окне исключения. Полный текст включает все внутренние исключения и стек вызовов, которые привели к исключению.   -  person Panagiotis Kanavos    schedule 03.09.2020
comment
@pitermarx, что касается дубликата, говорит использовать другое соединение. EF использует ADO.NET внизу, поэтому использование только классов ADO.NET не решит проблему.   -  person Panagiotis Kanavos    schedule 03.09.2020


Ответы (2)


После пары часов проб и ошибок я добрался до минимального фрагмента кода, который воспроизводит ошибку

string dbName = "TESTDB";
Run("master", $"CREATE DATABASE [{dbName}]");
Run(dbName, $"ALTER DATABASE [{dbName}] COLLATE Latin1_General_100_CI_AS");
Run(dbName, "PRINT 'HELLO'");

void Run(string catalog, string script)
{
    var cnxStr = new SqlConnectionStringBuilder
    {
        DataSource = serverAndInstance,
        UserID = user,
        Password = password,
        InitialCatalog = catalog
    };

    using var cn = new SqlConnection(cnxStr.ToString());
    using var cm = cn.CreateCommand();
    cn.Open();
    cm.CommandText = script;
    cm.ExecuteNonQuery();
}

Полная трассировка стека

Unhandled Exception: System.Data.SqlClient.SqlException: Resetting the connection results in a different state than the initial login. The login fails.
Login failed for user 'user'.
Cannot continue the execution because the session is in the kill state.
A severe error occurred on the current command.  The results, if any, should be discarded.
   at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
   at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
   at System.Data.SqlClient.SqlCommand.RunExecuteNonQueryTds(String methodName, Boolean async, Int32 timeout, Boolean asyncWrite)
   at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, String methodName, Boolean sendToPipe, Int32 timeout, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry)
   at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
...

Если я изменю первый Run(dbName... на Run("master"..., он будет работать нормально. Так что это связано с запуском ALTER DATABASE в контексте той же базы данных.

person pitermarx    schedule 03.09.2020
comment
может быть, лучше всего задать новый вопрос с этим минимальным примером... - person pitermarx; 03.09.2020
comment
stackoverflow.com/ вопросы/63726424/ - person pitermarx; 03.09.2020

Это не ответ на мой вопрос, но я решил проблему, не удаляя SqlConnection, а повторно используя его.

я до сих пор не понимаю проблемы

person pitermarx    schedule 03.09.2020
comment
Это почти так же плохо, как использование sa. Теперь вы накапливаете блокировки на всех таблицах, которые вы используете, блокируя другие соединения. Вы не опубликовали код или даже полное исключение, поэтому невозможно понять проблему. - person Panagiotis Kanavos; 03.09.2020
comment
Однако это показывает, что код, который вы используете для создания соединений, делает что-то странное. - person Panagiotis Kanavos; 03.09.2020
comment
Как выглядят две строки подключения? Какие выпуски и версии SQL Server вы используете? ADO.NET объединяет соединения и повторно использует их. Каждый раз, когда вы закрываете/удаляете соединение, оно сбрасывается и возвращается в пул. Подключения объединяются по строке подключения и учетной записи Windows, если используется проверка подлинности Windows. Ошибка при сбросе соединения предполагает, что пул перепутался (маловероятно, иначе вы бы увидели много похожих вопросов) или что-то изменилось на удаленном сервере. Возможно, разные базы данных? Переключиться в однопользовательский режим? База данных экземпляра пользователя? - person Panagiotis Kanavos; 03.09.2020
comment
@PanagiotisKanavos спасибо за комментарии. Я не публиковал код, потому что это большая кодовая база, и я не уверен, что вызывает проблему. Код для создания подключения так же прост, как new SqlConnection(connectionString); а затем Open() - person pitermarx; 03.09.2020
comment
@pitermax соответствующий код состоит всего из пары строк. Опять же, если бы простая строка подключения вызывала такие проблемы, многие заметили бы это. Ни SQL Server, ни ADO.NET не сломаны - person Panagiotis Kanavos; 03.09.2020
comment
С другой стороны, использование sa не работает, как ни крути. Вот почему он также отключен по умолчанию - даже если вы используете учетные записи SQL, лучше использовать новую учетную запись с правами системного администратора, чем оставлять активную известную учетную запись sa. - person Panagiotis Kanavos; 03.09.2020
comment
Я не говорю, что ADO.NET не работает. Я пытаюсь понять проблему. У меня также была идея, что соединения уже были опрошены. Локально это экспресс SQL2016 и удаленно тоже. Варианты, которые вы даете: 1. Объединение перепуталось. 2. Что-то изменилось на удаленном сервере. - Различные базы данных. Я выполняю запросы к нескольким базам данных как удаленно, так и локально — переключитесь на однопользовательский режим. Вы предлагаете мне перейти на однопользовательский режим? - База данных экземпляров пользователей. Я не использую эту функцию. Вы предлагаете включить его? - person pitermarx; 03.09.2020
comment
Я бы посоветовал еще раз прочитать возможный дубликат, потому что вы, кажется, делаете то же самое - создаете новую базу данных. Дубликат использует миграции EF, вы используете DbUp. Это означает, что соединение с одним и тем же сервером может закончиться попыткой входа в разные базы данных от одного этапа к другому. - person Panagiotis Kanavos; 03.09.2020
comment
@PanagiotisKanavos спасибо за помощь. Я создал новый вопрос с примером кода и более конкретными вопросами stackoverflow.com/questions/63726424/ - person pitermarx; 03.09.2020