#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 ….. и эта настройка такая же в других местах (например, в нашей инфраструктуре тестового сервера).
Итак, мой вопрос действительно таков:
-
С какой стати Linq-to-SQL внезапно создает совершенно другое представление того же самого
DateTime
для отправки на SQL Server? Есть ли какая-нибудь ручка, которую можно повернуть, чтобы управлять этим? -
И почему нельзя 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:
Я думаю, вы можете преследовать неправильную проблему.
Я бы сначала проверил:
- Ваша схема / модель базы данных LINQ to SQL является точной.
- Ваша логика проблемы заключается в том, чтобы убедиться, что новое значение DateTime никоим образом не может быть вне диапазона. В частности, убедитесь, что это не может быть ни
DateTime.MinValue
, ниDateTime.MaxValue
. - То, что вы не выполняете синтаксический анализ строки для даты в своем приложении.
- На сервере 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
и так Далее), И значение для этого параметра, по-видимому, отправляется в виде строкового представления даты — один раз в одном формате, один раз в другом….