Entity Framework 7 non riesce a inserire datetime

debian entity-framework-core mono sql-server windows

Domanda

Sto usando EntityFramework 7, beta7 e ho la seguente entità:

C #

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

SQL

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

E io eseguo il seguente:

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

Questo ha successo su Windows, ma fallisce sotto mono su debian. Stesso server / database SQL. L'SQL generato è sotto. Nota la differenza tra il tipo e il valore visualizzato per @p1 :

finestre

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

L'errore su Linux è:

Conversione non riuscita durante la conversione di data e / o ora dalla stringa di caratteri.

Domande

  1. Perché Windows genera un datetime2 quando il tipo è impostato esplicitamente su datetime ?
  2. La versione di Linux sta generando SQL non valido, quindi l'errore. Come posso inserire valori datetime su mono / linux?

Risposta accettata

  1. Il tipo DateTime di .NET ha un intervallo più ampio del tipo "datetime" del server sql. In realtà, .NET DateTime ha lo stesso intervallo del tipo "datetime2" di sql server, motivo per cui Entity Framework utilizzerà datetime2 (se possibile) ovunque durante la conversione di DateTime in data sql (come nell'esempio). Il tipo di colonna della tabella non ha importanza in questo caso. Puoi leggere queste note di incontro di design in cui il team EF discute del problema con datetime e datetime2 e decide di lasciare questo come è (e le ragioni dietro a questo).

  2. Mono usa TDS per lavorare con sql server (basato su FreeTDS , e ne usa una versione abbastanza obsoleta. Questa versione non ha idea del tipo "datetime2" di sql server, quindi invece di aggiornare alla nuova versione di TDS (forse è troppo lavoro per ora), è stata implementata una sorta di hack, convertendo datetime2 da \ a stringa. Ora, datetime2 ha maggiore precisione di datetime, quindi quando si converte datetime2 in string e quindi si converte quella stringa in datetime (che viene eseguita implicitamente) causa l'errore vedi. È facile controllare:

    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
    

    Puoi leggere un po 'di più qui .

Potresti chiedere se puoi usare EF con sql server su mono. Bene, è possibile aggirare il problema impostando ProviderManifestToken sul 2005 nel modello EF. Ciò renderà EF cosa funziona con sql server 2005, e non utilizzerà datetime2 ovunque. Ma perderete altri tipi che sono stati aggiunti dopo sql server 2005 ovviamente, senza contare che è un hack sporco.

Come nota a margine - meglio non fare alcun serio sviluppo su mono con SQL Server. Il provider di servizi Sql in mono è pieno di bug e il bug sopra è uno dei più innocenti. Ha problemi con valori nulli, problemi con il pool di connessioni (questo è molto serio - se si esegue il timeout sulla connessione del pool di connessioni - questa connessione verrà interrotta per l'intera durata e TUTTE le query su quella connessione avranno esito negativo. pool se la tua query è scaduta su di esso), ecc. La maggior parte di questi bug sono noti da anni e non sono ancora stati risolti. Se hai scelta, usa solo postgresql, è gratis, buono, e non ho avuto problemi con il mono.



Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché