2009-01-22 286 views
58

He estado utilizando este código que he escrito y está funcionando de esta manera poco clara. Deseo insertar una fila en la base de datos que incluye dos columnas de Fecha y hora:Error: desbordamiento de SqlDateTime. Debe estar entre 1/1/1753 12:00:00 AM y 12/31/9999 11:59:59 PM

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

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

SqlDateTime overflow. Must be between 1/1/1753 12:00:00 AM and 12/31/9999 11:59:59 PM.

Incluso he intentado copiar una valor insertado desde la base de datos y duro código 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 así mismo error, lo extraño es que el truco anterior trabajó para la primera inserción con el PP pero f ailed a partir de ahí en adelante. ¿Alguna idea de qué está pasando?

+0

publicar su código. Además, podría considerar simplemente inspeccionar qué está construyendo linq debajo de las coberturas. – NotMe

Respuesta

1

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

9

El código que tiene para las dos columnas se ve bien. Busque cualquier otra columna de fecha y hora en esa clase de asignación. Además, habilite el inicio de sesión en el contexto de datos para ver la consulta y los parámetros.

dc.Log = Console.Out; 

DateTime se inicializa en C# 's 0 - que es 0001-01-01. Esto es transmitido por linqtosql a la base de datos a través de sql string literal: '0001-01-01'. Sql no puede analizar un T-Sql datetime a partir de esta fecha.

Hay un par de maneras de lidiar con esto:

  • Asegúrese de inicializar todos los tiempos de la fecha con un valor que puede manejar SQL (como SQL de 0: 1900-01-01)
  • Asegúrese cualquier veces de fecha que de vez en cuando puede ser omitida son anulables datetimes
+1

Normalmente uso 1970-01-01 que es una época común para el tiempo de la computadora (unix TIME_T y JavaScript) – Tracker1

+0

Gracias por la sugerencia de redirigir el registro a Console.Out. –

68

a DateTime en 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.MinValue que está fuera del rango de los servidores Sql DATETIME tipo de datos.

Se garantiza que los tipos de valor siempre tengan un valor (predeterminado) (de cero) sin que sea necesario establecerlos explícitamente (en este caso, DateTime.MinValue).

Conclusión es probable que tenga un valor DateTime sin configurar que está tratando de 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


relacionadas con SQL Servidor

datetime
Date and time data from January 1, 1753 through December 31, 9999, to an accuracy of one three-hundredth of a second (equivalent to 3.33 milliseconds or 0.00333 seconds). Values are rounded to increments of .000, .003, or .007 seconds

smalldatetime
Date and time data from January 1, 1900, through June 6, 2079, with accuracy to the minute. smalldatetime values with 29.998 seconds or lower are rounded down to the nearest minute; values with 29.999 seconds or higher are rounded up to the nearest minute.

MSDN: Sql Server DateTime and SmallDateTime


Por último, si usted se encuentra pasando un C# DateTime como una cadena a sql, debe formatearlo de la siguiente manera para conservar 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 más tarde)

considerar el uso del tipo de datos SQL DateTime2 que se alinea mejor con el .NET DateTime con el periodo 0001-01-01 through 9999-12-31 y hora gama 00:00:00 through 23:59:59.9999999

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

MSDN datetime2 (Transact-SQL)

+5

¡Gracias por el puntero sobre 'DateTime' que no se puede anular en C#! –

3

veces con el fin de escribir menos código que se utiliza para tener campos de conjunto de servidor SQL como fecha, hora y el ID de inserción estableciendo el valor por defecto para los campos de GETDATE() o NEWID().

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

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

55

encuentro utilizando los siguientes funciona bastante bien para SQL min/fechas max después de muchos errores relacionados DB:

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

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

+1 funciona bien para mí y justo lo que estaba buscando –

+2

Esto debería haber obtenido la mayor cantidad de votos, y es la respuesta correcta también. –

+0

¡Sí! ¡Está funcionando! –

-1

Si ur utilizando NHibernate ORM comprobar ur archivos de fecha y hora sean anulables y en ur NHibernate archivos de mapas que hay establecido en Nullable.

que tenía ese problema y tryed muchos tiempo para comprobar todos los códigos y finaly encontrarlo.

+0

Por favor revise sus respuestas antes de darlas. – normanthesquid

6

Tenga cuidado cuando se compara un .Net DateTime a SqlDateTime.MinValue o MaxValue. Por ejemplo, lo siguiente será 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 su comparación y porque está fuera del rango aceptable de SqlDateTime arroja la excepción.

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

+1

+1 de advertencia sobre la excepción que acecha en una comparación. –

+0

También existe la opción de usar 'SqlDateTime.MinValue.Value' o' SqlDateTime.MaxValue.Value', ambos de tipo 'DateTime'. No sé cuándo fueron presentados. Tenga en cuenta, sin embargo, que hay algunas diferencias entre 'DateTime.MaxValue' y' SqlDateTime.MaxValue.Value'. SQL Server 2014 y SQL Server 2016 (no verificó otros) aceptan 'DateTime.MaxValue' que - lo suficientemente gracioso es más grande que' SqlDateTime.MaxValue.Value'. – Manfred

0

Estoy viendo lo mismo. El error no ocurre en la inserción de una fila, sino en una actualización. la tabla a la que me refiero tiene dos columnas de DateTime, ninguna de las cuales puede contener nulos.

He obtenido el escenario para obtener la fila y guardarla inmediatamente (no hay cambios en los datos). El get funciona bien pero la actualización falla.

Estamos utilizando NHibernate 3.3.1.4000

0

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

-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 
3

Este error se produce si está tratando de establecer variable de tipo DateTime a nula. Declare la variable como anulable, es decir, DateTime?. Esto solucionará el problema.

+0

Esta fue la respuesta a mi desbordamiento, tuve una segunda fecha en mi mesa a la que no le estaba dando un valor, así que una vez que lo configuré como nulable, el inserto funcionó. ¡Gracias! – mkimmet

0

Uso extensión método

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(); 
Cuestiones relacionadas