Error: desbordamiento de SqlDateTime. Debe ser entre el 1/1/1753 12:00:00 AM y el 31/12/9999 11:59:59 PM

82

He estado usando este fragmento de código que escribí y funciona de la manera más confusa. Deseo insertar una fila en la base de datos que incluye dos columnas de DateTime:

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

Y, sin embargo, cuando actualizo la base de datos, recibo este error:

Desbordamiento de SqlDateTime. Debe ser entre el 1/1/1753 12:00:00 AM y el 31/12/9999 11:59:59 PM.

Incluso intenté copiar un valor insertado de la base de datos y codificarlo en el objeto que se actualiza:

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

Aún el mismo error, la parte extraña es que el truco anterior funcionó para la primera inserción en la base de datos, pero falló a partir de ahí. ¿Alguna idea de qué está pasando?

Dibujó Noakes
fuente
Publica tu código. Además, podría considerar simplemente inspeccionar lo que linq está construyendo bajo las sábanas.
NotMe

Respuestas:

87

A DateTimeen C # es un tipo de valor, no un tipo de referencia y, por lo tanto, no puede ser nulo. Sin embargo, puede ser la constante DateTime.MinValueque está fuera del rango del DATETIMEtipo de datos de Sql Servers .

Se garantiza que los tipos de valor siempre tendrán un valor (predeterminado) (de cero) sin necesidad de establecer siempre explícitamente (en este caso, DateTime.MinValue).

La conclusión es que probablemente tenga un valor DateTime no establecido que está intentando pasar a la base de datos.

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


Respecto al servidor SQL

datetime
Datos de fecha y hora desde el 1 de enero de 1753 hasta el 31 de diciembre de 9999, con una precisión de tres centésimas de segundo (equivalente a 3,33 milisegundos o 0,00333 segundos). Los valores se redondean a incrementos de .000, .003 o .007 segundos

smalldatetime
Datos de fecha y hora desde el 1 de enero de 1900 hasta el 6 de junio de 2079, con precisión al minuto. los valores de smalldatetime con 29,998 segundos o menos se redondean al minuto más cercano; los valores con 29,999 segundos o más se redondean al minuto más cercano.

MSDN: Sql Server DateTime y SmallDateTime


Por último, si se encuentra pasando un C # DateTimecomo una cadena a sql, debe formatearlo de la siguiente manera para mantener la máxima precisión y evitar que el servidor SQL arroje un error similar.

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

Actualización (8 años después)

Considere usar el DateTime2tipo de datos sql que se alinea mejor con el .net DateTimecon rango de fecha 0001-01-01 through 9999-12-31y rango de tiempo00:00:00 through 23:59:59.9999999

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

MSDN datetime2 (Transact-SQL)

Robert Paulson
fuente
6
¡Gracias por el puntero sobre DateTimeno ser anulable en C #!
Tomas Aschan
80

Encuentro que usar lo siguiente funciona bastante bien para las fechas mínimas / máximas de SQL después de muchos errores relacionados con la base de datos:

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

DateTime rngMax = (DateTime)System.Data.SqlTypes.SqlDateTime.MaxValue;
Chrismean
fuente
2
Esta debería haber obtenido la mayor cantidad de votos y también es la respuesta correcta.
Taha Rehman Siddiqui
Sin embargo, tenga en cuenta que hay algunas diferencias entre DateTime.MaxValuey SqlDateTime.MaxValue.Value. SQL Server 2014 y SQL Server 2016 (no marcaron otros) aceptan DateTime.MaxValuecuál, lo suficientemente curioso, es mayor que SqlDateTime.MaxValue.Value.
Manfred
10

Tenga cuidado al comparar un .Net DateTime con SqlDateTime.MinValue o MaxValue. Por ejemplo, lo siguiente generará una excepción:

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

La razón es que MinValue devuelve un SqlDateTime, no un DateTime. Entonces .Net intenta convertir dte a SqlDateTime para comparar y, debido a que está fuera del rango aceptable de SqlDateTime, lanza la excepción.

Una solución a esto es comparar su DateTime con SqlDateTime.MinValue. Valor .

Phil Haselden
fuente
1
También existe la opción de utilizar SqlDateTime.MinValue.Valueo SqlDateTime.MaxValue.Valueambos son de tipo DateTime. No sé cuándo se introdujeron. Sin embargo, tenga en cuenta que hay algunas diferencias entre DateTime.MaxValuey SqlDateTime.MaxValue.Value. SQL Server 2014 y SQL Server 2016 (no marcaron otros) aceptan DateTime.MaxValuecuál - lo suficientemente divertido es más grande que SqlDateTime.MaxValue.Value.
Manfred
9

El código que tiene para las dos columnas parece correcto. Busque cualquier otra columna de fecha y hora en esa clase de mapeo. Además, habilite el registro en el contexto de datos para ver la consulta y los parámetros.

dc.Log = Console.Out;

DateTime se inicializa en el 0 de c #, que es 0001-01-01. Esto es transmitido por linqtosql a la base de datos a través del literal de cadena sql: '0001-01-01'. Sql no puede analizar una fecha y hora T-Sql a partir de esta fecha.

Hay un par de formas de lidiar con esto:

  • Asegúrese de inicializar todas las fechas y horas con un valor que SQL pueda manejar (como Sql's 0: 1900-01-01)
  • Asegúrese de que las fechas y horas que ocasionalmente se pueden omitir sean fechas que admitan nulos
Amy B
fuente
1
Normalmente uso 1970-01-01, que es una época común para el tiempo de la computadora (unix TIME_T y JavaScript)
Tracker1
Gracias por el consejo de redirigir el registro a Console.Out.
Jan Aagaard
8

Este error se produce si intenta establecer una variable de tipo DateTime en nulo . Declare la variable como anulable, es decir, DateTime? . Esto solucionará el problema.

Altaf Patel
fuente
1
Esta fue la respuesta a mi desbordamiento, tenía una segunda fecha en mi mesa a la que no le estaba dando un valor, y una vez que la configuré como anulable, la inserción funcionó. ¡Gracias!
mkimmet
3

A veces, para escribir menos código, se usa para que el servidor SQL establezca campos como fecha, hora e ID en la inserción estableciendo el valor predeterminado para los campos en GETDATE()o NEWID().

En tales casos, la propiedad de valor generado automáticamente de esos campos en clases de entidad debe establecerse en verdadero.

De esta manera no es necesario establecer valores en el código (¡¡¡evitando el consumo de energía !!!) y nunca ver esa excepción.

Haghpanah
fuente
2

Usar método de extensión

 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();
MSTdev
fuente
1

Eso generalmente significa que se publica un nulo en la consulta en lugar del valor deseado, puede intentar ejecutar el Analizador de SQL para ver exactamente qué se pasa a SQL Server desde linq.

Llavero
fuente
1

Por lo general, este tipo de error se produce cuando realiza la conversión o el análisis de DateTime. Verifique la configuración del calendario en el servidor donde está alojada la aplicación, principalmente la zona horaria y el formato de fecha corta, y asegúrese de que esté configurado en la zona horaria correcta para la ubicación. Espero que esto resuelva el problema.

Sushil Kumar Naik
fuente
0

Veo lo mismo. El error no ocurre al insertar una fila sino en una actualización. la tabla a la que me refiero tiene dos columnas DateTime, ninguna de las cuales es anulable.

He bajado el escenario para obtener la fila y guardarla inmediatamente (sin cambios de datos). El get funciona bien pero la actualización falla.

Estamos usando NHibernate 3.3.1.4000

Tevya
fuente
0

Si está utilizando NHibernate, compruebe que las propiedades de DateTime adecuadas que admiten nulos estén configuradas como nulos en las asignaciones.

arash
fuente
0

Si pones Datetime anulable como DateTime? en su modelo no lanza una excepción. Resolví el problema así en mi caso

baptiste baume
fuente
0

En mi caso, este error se generó porque la columna de fecha de la tabla no es nula

Como a continuación:

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

Para evitar este error, simplemente hágalo nulo

 Create Table #TempTable(
 ...
 ApprovalDate datatime null.
 ...)
Ravi Makwana
fuente
-3

DateTime.MinValue y 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 
Cindrella
fuente