Странность Linq-to-SQL и DateTime

#asp.net #sql-server-2005 #linq-to-sql #datetime #update-statement

#asp.net #sql-server-2005 #linq-to-sql #datetime #sql-обновление

Вопрос:

Здесь у нас действительно странное и непоследовательное поведение с Linq-to-SQL .

Наше приложение установлено на довольно многих сайтах клиентов, и по большей части оно работает просто отлично. Один из запросов в Linq-to-SQL обновляет таблицу и присваивает DateTime столбцу новое значение.

Во всех случаях, включая наши системы разработки и тестирования, этот оператор Linq-to-SQL преобразуется во что-то вроде:

 UPDATE dbo.OurTable 
SET WorkTimeStamp = @WTS 
WHERE ID = @ID

@WTS = '2011-11-04 14:15:25', @ID = 555
  

Однако на сайте одного клиента по причинам, которые нам не ясны (пока), это обновление переводится на:

 UPDATE dbo.OurTable 
SET WorkTimeStamp = @WTS 
WHERE ID = @ID

@WTS = 'Nov  4 2011 02:15:25PM', @ID = 555
  

и по какой-то причине затем происходит сбой на SQL Server 2005.

Теперь на серверах этого клиента (веб-сервер и SQL Server) установлены англоязычные версии Windows Server 2008; язык в SQL Server установлен на us_english , формат даты установлен на mdy , учетная запись пользователя, запускающая обновление, имеет свой язык, установленный на English в SQL Server ….. и эта настройка такая же в других местах (например, в нашей инфраструктуре тестового сервера).

Итак, мой вопрос действительно таков:

  1. С какой стати Linq-to-SQL внезапно создает совершенно другое представление того же самого DateTime для отправки на SQL Server? Есть ли какая-нибудь ручка, которую можно повернуть, чтобы управлять этим?

  2. И почему нельзя ADO.NET и база данных SQL Server 2005 SP2 правильно обрабатывает это UPDATE утверждение? Мы получаем ошибку в нашем журнале, которая гласит:

Исключение SqlTypeException — переполнение SqlDateTime. Должно быть между 1/1/1753 12:00:00 утра и 12/31/9999 11:59:59 вечера.

Похоже, что это ошибка .NET (больше, чем ошибка SQL Server), и кажется, что .NET по какой-то причине не может действительно интерпретировать это Nov 4 2011 02:15:25PM как действительное DateTime . При попытке запустить сгенерированную инструкцию UPDATE в SQL Server Management Studio, мы, похоже, не можем «принудительно» вызвать эту ошибку — UPDATE к счастью, работает просто отлично…..

Обновление: некоторые дальнейшие исследования, похоже, указывают на то, что Linq-to-SQL ведет себя по-разному при переходе на SQL Server 2005 или 2008.

  • с SQL Server 2005 наши даты превращаются в: Nov 4 2011 02:15:25PM
  • с SQL Server 2008 наши даты превращаются в: 2011-11-04 02:15:25PM

Комментарии:

1. Пожалуйста, проверьте настройки вашей текущей культуры для приложений C # / VB.NET.

2. @BogdanSahlean: CurrentCulture установлено на InvariantCulture во всех системах

3. Я согласен, что это проблема .NET, а не SQL. Вероятно, ошибка в LINQ2SQL, забывающая где-то использовать инвариантную культуру. Совпадают ли настройки местоположения Windows?

4. Также: это веб-приложение? Попробуйте явно задать язык в web.config.

5. Правильно ли я понимаю, что оператор UPDATE dbo.OurTable SET WorkTimeStamp = @WTS WHERE ID = @ID @WTS = 'Nov 4 2011 02:15:25PM', @ID = 555 не завершается ошибкой при выполнении непосредственно на сервере SQL? Так эта ошибка локализована в LINQ?

Ответ №1:

Я думаю, вы можете преследовать неправильную проблему.

Я бы сначала проверил:

  1. Ваша схема / модель базы данных LINQ to SQL является точной.
  2. Ваша логика проблемы заключается в том, чтобы убедиться, что новое значение DateTime никоим образом не может быть вне диапазона. В частности, убедитесь, что это не может быть ни DateTime.MinValue , ни DateTime.MaxValue .
  3. То, что вы не выполняете синтаксический анализ строки для даты в своем приложении.
  4. На сервере SQL нет никаких триггеров (в частности, вместо триггеров, которые могут изменять инструкцию update).

Я предполагаю, что вы (или ваш клиент) начинаете с получения ‘SqlTypeException — SqlDateTime overflow. Должно быть сообщение об ошибке между 1/1/1753 12:00:00 УТРА и 31/12/9999 11:59:59 вечера, и после расследования вы заметили разницу в способе отображения дат.

Вы не упоминаете, откуда поступает информация, поэтому я предполагаю что-то вроде SQL profiler.

Однако проблема с отображением даты может быть отвлекающим маневром, поскольку это не должно быть проблемой.

с SQL Server 2005 наши даты превращаются в: 4 ноября 2011 02:15:25 ВЕЧЕРА

с SQL Server 2008 наши даты превращаются в: 2011-11-04 02:15:25 ВЕЧЕРА

Я не совсем уверен, что вы имеете в виду под этим. SQL не «превращает» даты в строку, поскольку он не хранит даты в виде строк, но внутреннее представление представляет собой число (что-то вроде количества дней с 1 января 1900 года).).

Если вы имеете в виду, что ваши даты отображаются как 4 ноября 2011 02:15: 25 вечера, то это зависит от программы, которая отображает информацию.

Кроме того, насколько я понимаю, если вы используете параметр DateTime (который LINQ to SQL должен выполнять, если модель базы данных точна), то информация, отправляемая клиентом на сервер SQL, является числовым представлением DateTime в SQL. Это должно избежать любых проблем с преобразованием datetime между клиентом и сервером. Когда вы смотрите, например, на SQL Profiler, он не показывает вам числовое представление даты, что для большинства людей будет означать очень мало, но пытается быть полезным и отображает значение в виде строки.

Важным моментом является то, что если SQL или SQL profiler удается отобразить параметр datetime как ‘4 ноября 2011 02:15:25 вечера’, то он знает, что это допустимая дата, и он точно знает, какая это дата.

Поэтому я подозреваю, что проблема с форматом отображения, вероятно, не имеет значения.

Тогда остается вопрос о том, почему ваш клиент получает сообщение об ошибке SqlTypeException — SqlDateTime overflow.

Первое, что нужно сделать, это проверить, какое значение даты вы устанавливаете, что должно быть сделано на уровне приложения, а не на сервере SQL Server, поскольку это не зайдет так далеко. (Это еще одна причина, по которой я не думаю, что это проблема конфигурации SQL.)

кажется, что .NET по какой-то причине не может интерпретировать это 4 ноября 2011 02:15:25 вечера как действительное DateTime

Я не вижу, где .NET даже пытался интерпретировать строки как дату, если у вас нет некоторых DateTime.Parse команд, и если это так, то проблема не имеет ничего общего ни с LINQ, ни с SQL.

Комментарии:

1. (2) DateTime имеет значение что-то вроде DateTime.Now.AddMinutes(5) , поэтому я почти уверен, что это не «вне диапазона»

2. он так говорит . NET преобразует дату в строковое представление для использования в запросе обновления, а не в том, что SQL превращает ее в строку. И, что это . NET выдает другой формат строки даты для SQL 2005 по сравнению с 2008 годом, и что SQL 2005 не понимает запрос, потому что формат, похоже, не является тем, что он понимает.

3. @marc_s Я знаю, что это маловероятно, но есть ли шанс, что DateTime. Теперь может быть вне диапазона, т. Е. Дата компьютера / сервера неверна?

4. @MystereMan Но .NET (или, точнее, Linq2SQL) не должен и, по моему опыту, не превращает дату в строку для инструкции update. Единственный способ, которым я могу увидеть преобразование строки в дату, было бы, если бы в переменной класса dotnet была определена строка, которая означала бы, что схема / модель неправильная.

5. @sgmoore: кажется, что это так — по крайней мере, это то, что мы видим в журналах профилировщика SQL Server; оператор отправляется на SQL Server с параметрами ( @p1 , @p2 и так Далее), И значение для этого параметра, по-видимому, отправляется в виде строкового представления даты — один раз в одном формате, один раз в другом….