Помилка - переповнення SqlDateTime. Повинна бути між 1/1/1753 00:00:00 і 31.12.999 23:59:59


82

Я використовую цей фрагмент коду, який я написав, і він працює таким незрозумілим чином. Я хочу вставити рядок у базу даних, що включає два стовпці DateTime:

myrow.ApprovalDate = DateTime.Now
myrow.ProposedDate = DateTime.Now

І все ж, коли я оновлюю базу даних, я отримую таку помилку:

Переповнення SqlDateTime. Повинна бути між 1/1/1753 00:00:00 і 31.12.999 23:59:59.

Я навіть спробував скопіювати вставлене значення з бази даних і ввести його в об'єкт, що оновлюється:

// I copied this value from the DB
myrow.ApprovalDate =  Convert.ToDateTime("2008-12-24 00:00:00.000");

Все така ж помилка, дивна частина полягає в тому, що вищевказаний фокус спрацював для першої вставки в БД, але з цього часу не вдався. Будь-які ідеї, що відбувається?


Опублікуйте свій код. Крім того, ви можете просто розглянути, що Linq будує під ковдрою.
NotMe

Відповіді:


87

A DateTimeв C # є типом значення, а не посилальним типом, і тому не може бути нульовим. Однак це може бути константа, DateTime.MinValueяка виходить за межі діапазону DATETIMEтипу даних Sql Servers .

Гарантовано, що типи значень завжди матимуть значення (за замовчуванням) (дорівнює нулю), не завжди потребуючи явного встановлення (у цьому випадку DateTime.MinValue).

Висновок: у вас, мабуть, не встановлено значення DateTime, яке ви намагаєтесь передати базі даних.

DateTime.MinValue = 1/1/0001 12:00:00 AM
DateTime.MaxValue = 23:59:59.9999999, December 31, 9999, 
                    exactly one 100-nanosecond tick 
                    before 00:00:00, January 1, 10000

MSDN: DateTime.MinValue


Щодо Sql Server

дата, час
Дати та дані з 1 січня 1753 р. по 31 грудня 9999 р. з точністю до однієї три сотих секунди (що еквівалентно 3,33 мілісекунди або 0,00333 секунди). Значення округлюються з кроком .000, .003 або .007 секунд

невеликий час
Дані та час з 1 січня 1900 р. до 6 червня 2079 р. з точністю до хвилин. значення малого часу з 29,998 секунди або менше округлюються до найближчої хвилини; значення з 29,999 секунди або вище округляються до найближчої хвилини.

MSDN: Sql Server DateTime і SmallDateTime


Нарешті, якщо ви виявите, що передаєте C # DateTimeяк рядок в sql, вам потрібно відформатувати його наступним чином, щоб зберегти максимальну точність і не допустити, щоб сервер sql видавав подібну помилку.

string sqlTimeAsString = myDateTime.ToString("yyyy-MM-ddTHH:mm:ss.fff");

Оновлення (через 8 років)

Подумайте про використання DateTime2типу даних sql, який краще узгоджується з .net DateTimeіз діапазоном дат 0001-01-01 through 9999-12-31та діапазоном часу00:00:00 through 23:59:59.9999999

string dateTime2String = myDateTime.ToString("yyyy-MM-ddTHH:mm:ss.fffffff");

MSDN datetime2 (Transact-SQL)


6
Дякуємо за вказівник про DateTimeте, що він не має дозволу на C #!
Томас Ашан,

80

Я вважаю, що використання наступного працює досить добре для мінімальних / максимальних дат SQL після багатьох помилок, пов'язаних з БД:

DateTime rngMin = (DateTime)System.Data.SqlTypes.SqlDateTime.MinValue;

DateTime rngMax = (DateTime)System.Data.SqlTypes.SqlDateTime.MaxValue;

2
Це мало набрати найбільше голосів, і це правильна відповідь.
Taha Rehman Siddiqui

Однак майте на увазі, що між DateTime.MaxValueі є кілька відмінностей SqlDateTime.MaxValue.Value. SQL Server 2014 та SQL Server 2016 (не перевіряли інших) приймають, DateTime.MaxValueщо - досить смішно - більше, ніж SqlDateTime.MaxValue.Value.
Манфред

10

Обережно, порівнюючи .Net DateTime із SqlDateTime.MinValue або MaxValue. Наприклад, наступне видасть виняток:

DateTime dte = new DateTime(1000, 1, 1);
if (dte >= SqlDateTime.MinValue)
    //do something

Причина в тому, що MinValue повертає SqlDateTime, а не DateTime. Отже .Net намагається перетворити dte у SqlDateTime для порівняння, і оскільки він знаходиться поза допустимим діапазоном SqlDateTime, він видає виняток.

Одним із рішень цього є порівняння вашого DateTime із SqlDateTime.MinValue. Значення .


1
Існує також можливість використовувати SqlDateTime.MinValue.Valueабо SqlDateTime.MaxValue.Valueобидва типи DateTime. Не знаю, коли вони були введені. Однак майте на увазі, що між DateTime.MaxValueі є кілька відмінностей SqlDateTime.MaxValue.Value. SQL Server 2014 та SQL Server 2016 (не перевіряли інших) приймають те, DateTime.MaxValueщо - досить смішно більше, ніж SqlDateTime.MaxValue.Value.
Манфред

9

Код для двох стовпців виглядає нормально. Шукайте будь-які інші стовпці дати та часу у цьому класі зіставлення. Також увімкніть реєстрацію в контексті даних, щоб побачити запит та параметри.

dc.Log = Console.Out;

DateTime ініціалізується значенням c #, тобто 0001-01-01. Це передається linqtosql до бази даних за допомогою рядкового літералу sql: '0001-01-01'. Sql не може проаналізувати дату T-Sql з цієї дати.

Є кілька способів вирішити це:

  • Переконайтеся, що ви ініціалізуєте всі дати, використовуючи значення, яке може обробляти SQL (наприклад, Sql 0: 1900-01-01)
  • Переконайтеся , що всі дати часів , які іноді можуть бути опущені в обнуляє DateTimes

1
Зазвичай я використовую 01.01.1970, що є звичною епохою для комп'ютерного часу (unix TIME_T та JavaScript)
Tracker1

Дякуємо за підказку щодо перенаправлення журналу на Console.Out.
Ян Аагаард

8

Ця помилка виникає, якщо ви намагаєтесь встановити для змінної типу DateTime значення null . Оголосити змінну як нульову, тобто DateTime? . Це вирішить проблему.


1
Це була відповідь на мій переповнення, у мене в таблиці була друга дата, якій я не надав значення, і тому одного разу, встановивши її як нульову, вставка працювала. Дякую!
mkimmet

3

Іноді для того, щоб писати менше коду, використовується, щоб сервер SQL встановлював поля, такі як дата, час та ідентифікатор при вставці, встановлюючи значення полів за замовчуванням на GETDATE()або NEWID().

У таких випадках для властивості Auto Generated Value цих полів у класах сутності слід встановити значення true.

Таким чином, вам не потрібно встановлювати значення в коді (запобігаючи споживанню енергії !!!) і ніколи не бачити цього винятку.


2

Використовуйте метод розширення

 public static object ToSafeDbDateDBnull(this object objectstring)
    {
        try
        {
            if ((DateTime)objectstring >= SqlDateTime.MinValue)
            {
                return objectstring;
            }
            else
            {
                return DBNull.Value;
            }
        }
        catch (Exception)
        {

            return DBNull.Value;
        }

    }

DateTime objdte = new DateTime(1000, 1, 1);
dte.ToSafeDbDateDBnull();

1

Це, як правило, означає, що в запит публікується нуль замість бажаного значення, ви можете спробувати запустити SQL Profiler, щоб точно побачити, що саме передається на SQL Server від linq.


1

Зазвичай такий тип помилок виникає, коли ви виконуєте перетворення або аналіз DateTime. Перевірте налаштування календаря на сервері, де розміщена програма, головним чином часовий пояс і формат короткої дати, і переконайтеся, що для нього встановлено правильний часовий пояс для розташування. Сподіваюся, це вирішить проблему.


0

Я бачу те саме. Помилка трапляється не під час вставки рядка, а під час оновлення. таблиця, на яку я посилаюся, має два стовпці DateTime, жоден з яких не може бути обнулений.

Я отримав сценарій до отримання рядка та негайного його збереження (без змін даних). Отримати працює нормально, але оновлення не вдається.

Ми використовуємо NHibernate 3.3.1.4000


0

Якщо ви використовуєте NHibernate, переконайтесь, що відповідні властивості DateTime, які мають нульовий статус, встановлені як значення, що мають значення NULL у відображеннях.


0

Якщо ви ставите Datetime як нульовий, як DateTime? у вашій моделі це не виняток. я вирішив проблеми, як це у моєму випадку


0

У моєму випадку ця помилка виникла, оскільки стовпець дати таблиці не може мати значення null

Як нижче:

Create Table #TempTable(
 ...
 ApprovalDate datatime not null.
 ...)

Щоб уникнути цієї помилки, просто зробіть її нульовою

 Create Table #TempTable(
 ...
 ApprovalDate datatime null.
 ...)

-3

DateTime.MinValue та DateTime.MaxValue

DateTime.MinValue = 1/1/0001 12:00:00 AM

DateTime.MaxValue = 23:59:59.9999999, December 31, 9999, 

                exactly one 100-nanosecond tick 

                before 00:00:00, January 1, 10000 
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.