Ошибка преобразования при преобразовании даты и/или времени из строки символов в хранимой процедуре

РЕДАКТИРОВАТЬ: я ответил на свой вопрос ниже, но пока не могу его принять.

Я использую С# и SQL2014. Я знаю, что этот вопрос возникает повсюду, и типичным ответом является использование универсального формата, но это не то, что я ищу. У меня есть два сценария. Один работает, а другой нет, и это то, что меня беспокоит. Оба используют одну и ту же хранимую процедуру (хотя и в разных базах данных). Если я редактирую хранимую процедуру, чтобы она была командой, и вручную устанавливаю параметры на то же самое, что и в C#, оба варианта работают. Оба сценария абсолютно одинаковы, за исключением разных баз данных, поэтому вот что я делаю.

cmd = new sqlcommand......
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandTimeout = 60;            
cmd.Parameters.AddWithValue("@date", "3/16/2015");
cmd.Parameters.AddWithValue("@startTime", "12:00 AM");
cmd.Parameters.AddWithValue("@endTime", "1:00 AM");

SqlDataAdapter da = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();

da.Fill(dt); //Error 

Что интересно, это происходит только тогда, когда для @date установлено значение «16.03.2015». Я пробовал около 6 других дат, и все работает нормально. При этом эта дата отлично работает в другой базе данных. Кто-нибудь знает, что это может быть? В хранимой процедуре этим параметрам присваивается значение SMALLDATETIME. Если нужно, я могу попробовать поместить сюда часть хранимой процедуры.

Вот часть хранимой процедуры, которая вызывает проблему:

@date SMALLDATETIME,
@startTime SMALLDATETIME,
@endTime SMALLDATETIME


 --[DATE] is a smalldatetime column in the database
 WHERE
 [DATE] = @date --ERROR HAPPENS BECAUSE OF THIS

РЕДАКТИРОВАТЬ: Извините за всю путаницу. После дополнительной отладки похоже, что реальная проблема может исходить из этого оператора в процедуре:

 SELECT 
 DATEDIFF(mi, '00:00:00', [START]) AS [START], 
 CASE WHEN [END] = '00:00:00' THEN 1440 
 ELSE DATEDIFF(mi, '00:00:00', [END]) END AS [END]  
 .
 .
 .

person user1427105    schedule 19.03.2015    source источник
comment
Вы не можете передать объект даты?   -  person Nikhil Agrawal    schedule 19.03.2015
comment
Да, я также пытался передать 3 даты и получить ту же проблему.   -  person user1427105    schedule 19.03.2015
comment
Выполняется ли процедура также с теми же значениями параметров, если вы выполняете ее напрямую из диспетчера SQL?   -  person DarrenMB    schedule 19.03.2015
comment
Нет, он отлично работает для обеих баз данных. Вот почему я застрял в отладке. Не уверен, что попробовать дальше.   -  person user1427105    schedule 19.03.2015
comment
Следующим моим шагом было бы начать добавлять команды печати в хранимую процедуру для создания вывода сообщения (чтобы попытаться получить более подробную информацию о шаге сбоя). Мне никогда не приходилось этого делать, но, по-видимому, это делается путем создания делегата SqlInfoMessageEventHandler и прослушивания события InfoMessage в классе SqlConnection.   -  person DarrenMB    schedule 19.03.2015
comment
Хорошо, я сделал что-то подобное и определил, что ошибка возникает при сравнении [DATE] = @date в предложении WHERE, которое я показываю в своем вопросе. Я отмечу это выше. Столбец [DATE] моей таблицы представляет собой smalldatetime   -  person user1427105    schedule 19.03.2015
comment
Я обновил свой вопрос. Похоже дело было в другом.   -  person user1427105    schedule 19.03.2015


Ответы (3)


Это, вероятно, основано на внутреннем формате даты, установленном для баз данных. Я бы порекомендовал вам использовать стандартные форматы ISO во всем вашем коде, поэтому передайте:

    cmd.Parameters.AddWithValue("@date", "2015-03-16");
person Gordon Linoff    schedule 19.03.2015

Строка «16.03.2015» — это то, что сломается, если вы каким-то образом жестко не запрограммировали региональные настройки в потоке на американский английский.

Вы пытались быть более конкретным с параметром SQL? Извините за синтаксис VB, но я бы предположил эквивалент С#...

Dim dt As Date = DateTime.ParseExact("3/16/2015", "M/d/yyyy", Globalization.CultureInfo.GetCultureInfo("us-en"))
cmd.Parameters.Add(New SqlClient.SqlParameter("@date", dt) With {.SqlDbType = SqlDbType.SmallDateTime})
person DarrenMB    schedule 19.03.2015
comment
Я только что видел ваш код SP, почему вы конвертируете дату и время в varchar, чтобы передать его команде, которая принимает значения даты и времени (datediff)? все это кажется очень необычным и подверженным ошибкам способом что-то сделать. - person DarrenMB; 19.03.2015
comment
Именно так это было, когда я столкнулся с проблемой. Я только что попытался передать 3 DateTimes и явно установить для SQLDBType значение SmallDateTime и получить ту же ошибку. - person user1427105; 19.03.2015

Моя проблема заключалась в использовании этого оператора в процедуре:

DATEDIFF(ми, '00:00:00', [КОНЕЦ])

Столбец [END] был nvarchar, в котором 24:00:00 было установлено как полночь вместо 00:00:00.

Спасибо всем, кто помог мне отладить это.

person user1427105    schedule 19.03.2015