Biren Vakharia Ответов: 1

Системы.исключение InvalidOperationException: метод executenonquery требуется открытое и доступное подключение. Текущее состояние соединения-закрыто.


Я получаю эту ошибку

System.InvalidOperationException: ExecuteNonQuery requires an open and available Connection. The connection's current state is closed.
   at System.Data.SqlClient.SqlCommand.ValidateCommand(String method, Boolean async)
   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()
   at GPSParser.DBLogic.DBUtils.ExecSP(SqlCommand sp) in C:\Users\Biren Vakharia\source\repos\FMB920Parser\GPS Listener Parser\DBLogic\DBUtils.cs:line 47
   at GPSParser.DBLogic.Data.SaveGPSPositionFMXXXX(GPSdata gpsPos) in C:\Users\Biren Vakharia\source\repos\FMB920Parser\GPS Listener Parser\DBLogic\Data.cs:line 40\n\


Что я уже пробовал:

Это мой код DBUtils.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using System.Data;

namespace GPSParser.DBLogic
{   
        public class DBUtils
        {
            private string connectionString;
            public DBUtils()
            {
                connectionString = GetConnectionString();
            }
            public string GetConnectionString()
            {               
                return GPSParser.Properties.Settings.Default.GPS_TrackingConnectionString;
            }        
          
            //----------------------------------------------------------------------------------//
            //**********************************************************************************//
            //----------------------------------------------------------------------------------//
            public SqlCommand InitSP(string spname)
            {
                SqlCommand command = new SqlCommand();
                command.Connection = new SqlConnection(GetConnectionString());
                command.Connection.Open();
                command.CommandText = spname;
                command.CommandType = System.Data.CommandType.StoredProcedure;
                command.Parameters.Add(new SqlParameter("Result", System.Data.SqlDbType.Int)).Direction = System.Data.ParameterDirection.ReturnValue;
                return command;
            }
            public SqlCommand InitQuery(string sql)
            {
                SqlCommand command = new SqlCommand();
                command.Connection = new SqlConnection(GetConnectionString());
                command.Connection.Open();
                command.CommandText = sql;
                command.CommandType = System.Data.CommandType.Text;
                return command;
            }         

            public void ExecSP(SqlCommand sp)
            {
                sp.ExecuteNonQuery();

                if (!sp.Parameters[0].Value.Equals(0))
                    throw new Exception("Stored	procedure (" + sp.CommandText + ") result error: " + sp.Parameters[0].Value.ToString());
            }

            public object ExecFunction(SqlCommand sp)
            {
                sp.ExecuteNonQuery();
                return sp.Parameters[0].Value;
            }

            public void ExecQuery(SqlCommand InitQuery)
            {
                try
                {
                    InitQuery.ExecuteNonQuery();
                }
                catch (Exception ex)
                {
                    throw new Exception("Exception while store in db: " + ex.ToString());
                }
                finally
                {                    
                    FreeSP(InitQuery);
                }
            }

            public SqlDataReader OpenSP(SqlCommand sp)
            {
                return sp.ExecuteReader(CommandBehavior.CloseConnection);
            }

            public void FreeSP(SqlCommand sp)
            {
                if (sp == null) return;
                sp.Connection.Close();             
                sp.Dispose();
                sp = null;
            }
        }
    

}

1 Ответов

Рейтинг:
1

OriginalGriff

Не делай этого так. Выбросьте этот код и переосмыслите весь свой подход. Никогда не объединяйте строки для построения команды SQL. Это оставляет вас широко открытыми для случайной или преднамеренной атаки SQL-инъекции, которая может уничтожить всю вашу базу данных. Вместо этого всегда используйте параметризованные запросы.

Когда вы объединяете строки, вы вызываете проблемы, потому что SQL получает такие команды, как:

SELECT * FROM MyTable WHERE StreetAddress = 'Baker's Wood'
Цитата, добавленная пользователем, завершает строку в том, что касается SQL, и вы получаете проблемы. Но могло быть и хуже. Если я приду и наберу вместо этого: "x';DROP TABLE MyTable;--", то SQL получит совсем другую команду:
SELECT * FROM MyTable WHERE StreetAddress = 'x';DROP TABLE MyTable;--'
Которые SQL видит как три отдельные команды:
SELECT * FROM MyTable WHERE StreetAddress = 'x';
Совершенно правильный выбор
DROP TABLE MyTable;
Вполне допустимая команда "удалить таблицу"
--'
А все остальное-это комментарии.
Так оно и происходит: выбирает любые совпадающие строки, удаляет таблицу из базы данных и игнорирует все остальное.

Поэтому всегда используйте параметризованные запросы! Или будьте готовы часто восстанавливать свою БД из резервной копии. Вы ведь регулярно делаете резервные копии, не так ли?
Не имеет значения, является ли это SP, который вы вызываете, или "нормальный" выбор: конкатенация строк опасна. И этот код:
public SqlCommand InitQuery(string sql)
это то, что вызовет это в будущем.

Кроме того, SQL - соединения, SQLCommands и т. д.-это ограниченные ресурсы, которые должны быть закрыты и утилизированы, когда вы закончите с ними-и нет никакого практического способа сделать это в вашем коде.
Встроенные запросы внутри using блоки таким образом, система будет автоматически утилизировать по мере необходимости и использовать параметризованные запросы.