Странное исключение SqlCommand ExecuteNonquery

Я хочу вставить запись в базу данных SQL Server, но получаю странное исключение в процессе ExecuteNonQuery(). Я получил это исключение:

ExecuteNonQuery requires an open and available Connection. 
The connection's current state is closed.

Однако моя проблема не связана с этим. Я определенно уверен, что текущее состояние моего соединения - Открыто. Моя проблема - один из моих параметров в моем запросе. Вот мой запрос:

                  sql = "update EMAIL_CONNECTIONS " +
                             "set END_DATE=@EndDate, " +
                             "STATUS=@Status, " +
                             "STATUS_DATE=@StatusDate, " +
                             "CATEGORY_CODE=@CategoryCode, " +
                             "EMAILOUT_SENTDATE=@EmailOutSentDate, " +
                             "TO_ADDRESS=@ToAddress " +
                             "where SESSIONID=@SessionId " +
                             "and STATUS = 'Inprocess'; ";
                sql += "insert into ICS_EMAIL_CONNECTIONS_TRX(SESSIONID, AGENTID, STATUS, FIELD1) " +
                       "values(@SessionId, @AgentId, @Status, 'Sended this mail')";

Вызов исключения из-за параметра @EmailOutSentDate. Он не принимает формат Datetime или что-то, чего я не знаю. Когда я даю DateTime.Now этому параметру, запрос выполняется успешно. Я также попробовал DBNull.Value, и запрос работает отлично. Проблема DateTime не связана с Exception.

   SqlConnection _cnn = new SqlConnection();
   _cnn.ConnectionString = connectionString;
   _cnn.Open();
    SqlCommand cmd = new SqlCommand(sql, _cnn);                    
   cmd.Parameters.Add(new SqlParameter("@EndDate", DateTime.Now));
   cmd.Parameters.Add(new SqlParameter("@Status", "Sent"));
   DateTime result = DateTime.MinValue;
   result = DateTime.ParseExact(result.ToString("yyyy-mm-dd HH:mm:ss.fff"), "yyyy-mm-dd HH:mm:ss.fff", null);
                DateTime newdate = DateTime.SpecifyKind(result, DateTimeKind.Local);
   cmd.Parameters.Add(new SqlParameter("@EmailOutSentDate", newdate));                   
   cmd.Parameters.Add(new SqlParameter("@ToAddress", interaction.AllAttributes["To"]));
   cmd.Parameters.Add(new SqlParameter("@StatusDate", DateTime.Now));
   cmd.Parameters.Add(new SqlParameter("@CategoryCode", long.Parse(CategoryCode)));
   cmd.Parameters.Add(new SqlParameter("@SessionId", interaction.Id));
   cmd.Parameters.Add(new SqlParameter("@AgentId", Agent.AgentId));
   cmd.CommandType = System.Data.CommandType.Text;
   cmd.ExecuteNonQuery();
   cmd.Dispose();

Как вы можете видеть, я также попробовал свойство DateTime.Kind, но все равно было выбрано то же исключение. В чем проблема? Есть предложения?


person cihadakt    schedule 07.11.2013    source источник
comment
указывает ли трассировка стека исключения на показанный здесь ExecuteNonQuery? или это исключение, возможно, связано с какой-то обработкой исключений, которую вы не показываете? Также: using. Вам должно быть using(var _cnn = ...) и using(var cmd = ...)   -  person Marc Gravell    schedule 07.11.2013
comment
Он не принимает формат даты и времени или что-то в этом роде - дата и время не отправляются на сервер sql в виде текста; это не проблема форматирования   -  person Marc Gravell    schedule 07.11.2013
comment
кстати; несвязанный - то, как вы построили значение sql - знаете ли вы, что можно сделать это проще, используя дословные строковые литералы? то есть sql = @"{your text here; can include line feeds etc just by pressing return}";   -  person Marc Gravell    schedule 07.11.2013
comment
Вы должны использовать оператор using для соединения и команды. В противном случае соединение остается открытым при ошибке.   -  person Tim Schmelter    schedule 07.11.2013
comment
Что ты здесь делаешь? Вы конвертируете DateTime.MinValue в string, затем обратно в DateTime с DateTime.ParseExact, наконец, вы используете DateTime.SpecifyKind. Результат тот же: DateTime.MinValue который не поддерживается в sql-сервере (начинается с 1 января 1753 года).   -  person Tim Schmelter    schedule 07.11.2013


Ответы (1)


Что именно ты пытаешься сделать? Похоже, вы пытаетесь вставить фиктивную дату вместо нулевого значения в БД? Если это так, вы должны придерживаться вставки нулевого значения вместо даты, которая не имеет фактического значения.

Если у вас действительно есть значение DateTime, которое вы не хотите вставлять как локализованное значение, это может вам помочь: Как создать локализованную строку даты с помощью CultureInfo

Вот метод обновления, который мы используем на нашем старом уровне БД, когда не работаем с EF, и он даст вам более безопасный код. Обратите внимание, что вам не нужно открывать соединение до тех пор, пока вам действительно не понадобится выполнить запрос, а использование оператора using гарантирует, что вы избавитесь от своего SqlCommand. Свойство _connection является закрытым и используется для всех методов этого класса и задается в конструкторе с помощью DependencyInjection.

_connection = new SqlConnection(this._connectionString);

public int Update(string query, Dictionary<string, string> commandParams)
    {
        int affectedRows = 0;
        using (SqlCommand command = new SqlCommand(query, _connection))
        {
            command.CommandType = CommandType.Text;
            foreach (var param in commandParams)
            {
                if (param.Value == null)
                    command.Parameters.AddWithValue(param.Key, DBNull.Value);
                else
                    command.Parameters.AddWithValue(param.Key, param.Value);
            }

            try
            {
                _connection.Open();
                affectedRows = command.ExecuteNonQuery();
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                _connection.Close();
                command.Parameters.Clear();
            }
        }

        return affectedRows;
    }
person Binke    schedule 07.11.2013