Entity Framework 7 no puede insertar datetime

debian entity-framework-core mono sql-server windows

Pregunta

Estoy usando EntityFramework 7, beta7 y tengo la siguiente entidad:

DO#

public class Log
{
    [Column(TypeName ="datetime")]
    public DateTime Date { get; set; }
    ...
}

SQL

CREATE TABLE [dbo].[Logs] (
    [Date] [datetime] NOT NULL,
    ...
)

Y ejecuto lo siguiente:

db.Logs.Add(new Log { Date = DateTime.UtcNow });
db.SaveChanges();

Esto es exitoso en Windows, pero falla bajo mono en debian. Mismo servidor SQL / base de datos. El SQL generado es a continuación. Note la diferencia del tipo y valor renderizado para @p1 :

Windows

exec sp_executesql N'SET NOCOUNT OFF;
INSERT INTO [Logs] ([Browser], [Date], [Exception], [HostAddress], [Level], [Logger], [Message], [Thread], [Url], [Username])
OUTPUT INSERTED.[Id]
VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9);
',N'@p0 nvarchar(max) ,@p1 datetime2(7),@p2 nvarchar(max) ,@p3 nvarchar(max) ,@p4 nvarchar(4000),@p5 nvarchar(4000),@p6 nvarchar(4000),@p7 nvarchar(4000),@p8 nvarchar(max) ,@p9 nvarchar(max) ',@p0=NULL,@p1='2015-09-28 23:02:26.0367851',@p2=NULL,@p3=NULL,@p4=N'INFO',@p5=N'Fanatics.ConsoleApp.Program',@p6=N'Console app test',@p7=N'0',@p8=NULL,@p9=NULL
go

Linux

exec sp_executesql N'SET NOCOUNT OFF;
INSERT INTO [Logs] ([Browser], [Date], [Exception], [HostAddress], [Level], [Logger], [Message], [Thread], [Url], [Username])
OUTPUT INSERTED.[Id]
VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9);
',N'@p0 nvarchar(4000), @p1 char(27), @p2 nvarchar(4000), @p3 nvarchar(4000), @p4 nvarchar(4000), @p5 nvarchar(4000), @p6 nvarchar(4000), @p7 nvarchar(4000), @p8 nvarchar(4000), @p9 nvarchar(4000)',@p0=NULL,@p1='2015-09-28T23:03:21.5561720',@p2=NULL,@p3=NULL,@p4=N'INFO',@p5=N'Fanatics.ConsoleApp.Program',@p6=N'Console app test',@p7=N'0',@p8=NULL,@p9=NULL
go

El fallo en Linux es:

La conversión falló al convertir la fecha y / o la hora de la cadena de caracteres.

Preguntas

  1. ¿Por qué Windows genera un datetime2 cuando el tipo se establece explícitamente en datetime ?
  2. La versión de Linux está generando un SQL inválido, por lo tanto la falla. ¿Cómo puedo insertar valores de datetime en mono / linux?

Respuesta aceptada

  1. El tipo .NET DateTime tiene un rango más amplio que el tipo "datetime" del servidor SQL. En realidad, .NET DateTime tiene el mismo rango que el tipo "datetime2" del servidor sql, por eso Entity Framework usará datetime2 (si es posible) en todas partes al convertir DateTime en fecha sql (como en su ejemplo). El tipo de columna de tabla no importa en este caso. Puede leer las notas de esta reunión de diseño donde el equipo de EF analiza el problema con datetime y datetime2 y decide dejar esto como está (y las razones detrás de eso).

  2. Mono usa TDS para trabajar con el servidor sql (basado en FreeTDS , y usa una versión bastante obsoleta. Esta versión no tiene idea acerca del tipo "datetime2" del servidor sql, así que en lugar de actualizar a la nueva versión de TDS (tal vez eso sea demasiado trabajo por ahora), se implementó el tipo de piratería, convirtiendo datetime2 de \ a cadena. Ahora, datetime2 tiene una precisión más alta que datetime, por lo que al convertir datetime2 en cadena y luego convertir esa cadena a datetime (lo que se hace implícitamente) causa el error que Ver. Eso es fácil de comprobar:

    select cast('2015-09-28T23:03:21.5561720' as datetime2) -- < all fine
    select cast('2015-09-28T23:03:21.5561720' as datetime) -- < error from your question
    

    Puedes leer un poco más sobre esto aquí .

Puede preguntar si puede usar EF con el servidor sql en mono. Bueno, puede solucionar el problema estableciendo ProviderManifestToken a 2005 en su modelo EF. Esto hará que EF funcione con el servidor SQL 2005, y no utilizará datetime2 en todas partes. Pero perderá otros tipos que se agregaron después del servidor SQL 2005, obviamente, sin mencionar que es un truco sucio.

Como nota al margen, mejor no hagas ningún desarrollo serio en mono con servidor SQL. El proveedor del servidor Sql en mono está lleno de errores, y el error anterior es uno de los más inocentes. Tiene problemas con valores nulos, problemas con el conjunto de conexiones (este es muy serio, si se agota el tiempo de espera en la conexión del conjunto de conexiones) esta conexión se interrumpirá durante toda la vida útil y TODAS las consultas de esa conexión fallarán. Hack: eliminar la conexión de la conexión agrupar si su consulta agotó el tiempo de espera), etc. La mayoría de estos errores se conocen desde hace años y no se han solucionado. Si tiene opciones, solo use postgresql, es gratis, bueno, y no tuve problemas con él en mono.



Related

Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué