Entity Framework 7 ne parvient pas à insérer date / heure

debian entity-framework-core mono sql-server windows

Question

J'utilise EntityFramework 7, beta7 et possède l'entité suivante:

C #

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

SQL

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

Et j'exécute ce qui suit:

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

Ceci réussit sous Windows, mais échoue sous mono sous Debian. Même serveur SQL / base de données. Le code SQL généré est ci-dessous. Notez la différence entre le type et la valeur rendue pour @p1 :

les fenêtres

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'échec sous Linux est:

La conversion a échoué lors de la conversion de la date et / ou de l'heure d'une chaîne de caractères.

Des questions

  1. Pourquoi Windows génère-t-il un datetime2 alors que le type est explicitement défini sur datetime ?
  2. La version linux génère un SQL invalide, d’où l’échec. Comment puis-je insérer datetime valeurs de date / heure sur mono / linux?

Réponse acceptée

  1. Le type .NET DateTime a une plage plus étendue que le type "datetime" de SQL Server. En fait, .NET DateTime a la même plage que le type "datetime2" de SQL Server, c’est pourquoi Entity Framework utilisera datetime2 (si possible) partout lors de la conversion de DateTime en date SQL (comme dans votre exemple). Le type de colonne de table n'a pas d'importance dans ce cas. Vous pouvez lire ces notes de la réunion de conception où l'équipe EF discute du problème rencontré avec datetime et datetime2 et décide de le laisser tel quel (ainsi que les raisons qui le sous-tendent).

  2. Mono utilise TDS pour travailler avec le serveur SQL (basé sur FreeTDS et utilise une version assez obsolète de cette dernière. Cette version n’a aucune idée du type "datetime2" du serveur SQL. Par conséquent, au lieu de passer à la nouvelle version de TDS travail pour le moment), le type de bidouillage a été implémenté, convertissant datetime2 de chaîne en chaîne.Maintenant, datetime2 a une précision supérieure à celle de datetime. C'est facile à vérifier:

    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
    

    Vous pouvez en lire un peu plus ici .

Vous pourriez vous demander si vous pouvez utiliser EF avec SQL Server sur mono. Vous pouvez contourner le problème en définissant ProviderManifestToken sur 2005 dans votre modèle EF. Cela fera que EF fonctionnera avec SQL Server 2005 et n'utilisera pas datetime2 partout. Mais vous perdrez évidemment d'autres types qui ont été ajoutés après SQL Server 2005, sans parler de leur bidouille.

En passant, mieux vaut ne pas faire de développement sérieux sur mono avec SQL Server. Le fournisseur de serveur SQL en mono est plein de bugs, et le bug ci-dessus est l’un des plus innocents. Il y a des problèmes avec les valeurs NULL, des problèmes avec le pool de connexion (celui-ci est très grave - si vous arrêtez la connexion au pool de connexions - cette connexion sera interrompue pour toute la durée de vie et TOUTES les requêtes sur cette connexion échoueront. Hack - supprimera la connexion de la connexion. pool si votre requête a expiré), etc. La plupart de ces bogues sont connus depuis des années et ne sont pas encore résolus. Si vous avez le choix - utilisez simplement postgresql, c’est gratuit, bon, et je n’ai eu aucun problème avec cela en mono.



Related

Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi