Проблема даты / времени вне допустимого диапазона при использовании LINQtoSQL - PullRequest
3 голосов
/ 06 мая 2010

Это действительно смущает меня. Вот фрагмент моей модели:

* SQL Server *

Event
-----
Id (int, PK) NOT NULL
Title (varchar(100)) NULL
LastModified (datetime) NULL

EventDates
----------
Id (int, PK) NOT NULL
StartDate (datetime) NULL
EndDate (datetime) NULL

* C# *

Event
-----
public int Id
public string Title
public DateTime LastModified

EventDates
----------
public int Id
public DateTime StartDate
public Datetime EndDate

Поле LastModified находится в базе данных с момента его создания. Я сохранял его значение при сохранении события, но хочу отобразить его в таблице, поэтому я изменил возвращаемое значение GetEvents хранилища событий:

return (from e in GetDbEvents()
                select new Event
                {
                    // Miscellaneous fields..
                    LastModified = e.LastModified.GetValueOrDefault() // Shiny new code
                });

Когда я звоню сейчас, меня кричат:

The conversion of a char data type to a datetime data type 
resulted in an out-of-range datetime value.

Если я приведу приведенный выше код к этому, это все равно не поможет, и я получу ту же ошибку, если попытаюсь перечислить результат:

var test = (from e in _db.Events
                    select e.LastModified.GetValueOrDefault());

В качестве теста я сделал то же самое для своей таблицы EventDates (опять же, с 2 столбцами даты и времени):

 var test4 = (from ed in _db.EventDates
                     select new EventDate
                     {
                         StartDate = ed.StartDate.GetValueOrDefault(),
                         EndDate = ed.EndDate.GetValueOrDefault()
                     });

Это прекрасно работает, конечно. Нет ошибок при перечислении, все значения верны.

Следует отметить, что некоторые значения LastModified в таблице Events равны NULL, тогда как все значения в EventDates заполнены данными.

Я что-то упустил? Заранее спасибо!

EDIT Мой главный вопрос: почему Events дает мне проблемы вне диапазона, а EventDates - нет, хотя модель очень похожа?

Ответы [ 4 ]

4 голосов
/ 06 мая 2010

Проблема связана с GetValueOrDefault (). Это вернет DateTime.MinValue (01-01-0001) в случае «по умолчанию», и sqlserver не примет это (он отклоняет даты до 1753).

Если вы используете Nullable<DateTime>, то sql будет доволен полученным null.

1 голос
/ 06 мая 2010

Возможно это связано?

Одно из возможных исправлений (если вы не хотите менять LastModified на DateTime?, требуя от вас пометить ваш код .Value везде ..) будет означать получение значений из базы данных как DateTime?, но переведите их в DateTime в вашем коде. Например:

return from e in GetDbEvents()
       select new Event(e.LastModified);

...

//In Event class:
public Event(DateTime? lastModified)
{
    LastModified = lastModified.GetValueOrDefault();
}

Это приведет к тому, что GetValueOrDefault() будет вызываться на стороне клиента, а не быть частью SQL.

Обратите внимание, что у этого подхода есть собственных проблем ...

1 голос
/ 06 мая 2010

Если вы измените объявление вашей переменной C # LastModified на public DateTime? LastModified, это должно решить вашу проблему. Добавление знака вопроса указывает на то, что это тип, который можно обнулять.

0 голосов
/ 05 июня 2019

Чтобы расширить ответ Ханса Кеинга и помочь людям, которые сталкиваются с этой проблемой, в условии фильтрации / WHERE, а не в предложении SELECT:

Проблема связана с GetValueOrDefault()вызов.LINQ to SQL (несколько тупо IMO) переводит это в реальный SQL, используя выражение COALESCE (аналогично ISNULL), например:

COALESCE(LastModified, '1/1/0001 12:00:00 AM')

К сожалению, тип данных SQL Server datetime не поддерживаетне принимают даты до 1753 года. Таким образом, SQL Server возвращает ошибку обратно в LINQ to SQL, которая возвращает ее вам.

Если вы используете Nullable, то SQL Server будет счастлив с нулевым значением, которое будетполучить.Но если вы все еще хотите использовать GetValueOrDefault(), например, в запросе для фильтрации результатов у вас есть пара вариантов:

  1. LastModified.GetValueOrDefault(System.Data.SqlTypes.SqlDateTime.MinValue.Value)
  2. LastModified.HasValue && LastModified > DateTime.Now
...