我正在使用EntityFramework 7,beta7并具有以下实体:
C#
public class Log { [Column(TypeName ="datetime")] public DateTime Date { get; set; } ... }
SQL
CREATE TABLE [dbo].[Logs] ( [Date] [datetime] NOT NULL, ... )
我执行以下操作:
db.Logs.Add(new Log { Date = DateTime.UtcNow }); db.SaveChanges();
这在Windows上是成功的,但在debian下单声道失败。 相同的SQL服务器/数据库。 下面是生成的SQL。 请注意@p1
呈现的types和值的差异:
视窗
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
Linux上的故障是:
从string转换date和/或时间时转换失败。
datetime2
types被明确设置为datetime
时生成? datetime
值? .NET DateTime类型比sql server的“datetime”类型有更广的范围。 实际上,.NET DateTime与sql server的“datetime2”类型具有相同的范围,这就是为什么实体框架在将DateTime转换为sql日期的任何地方都会使用datetime2(如果可能的话)(如你的例子)。 表格列的类型在这种情况下并不重要。 您可以阅读本设计会议记录 ,EF小组讨论datetime和datetime2问题,并决定保留原样(以及原因)。
单声道使用TDS与SQL服务器(基于FreeTDS ,它使用相当过时的版本,这个版本不知道关于SQL服务器的“日期时间2”类型,所以而不是升级到新版本的TDS(也许这是太多现在工作,类型的黑客实施,将\ datetime2从\转换为字符串。现在,datetime2具有比datetime更高的精度,所以当datetime2转换为字符串,然后将该字符串转换为datetime(这是隐式完成)看,这很容易检查:
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
你可以在这里阅读更多。
你可能会问,如果你可以在单声道的sql服务器上使用EF。 那么,你可以通过在EF模型中将ProviderManifestToken设置为2005来解决这个问题。 这将使EF工作与SQL server 2005,它不会使用datetime2到处。 但是你会失去其他类型的显然是在sql server 2005之后添加的,更不用说那是肮脏的破解了。
作为一个方面的说明 – 更好的不要做任何严重的发展与SQL server单声道。 单声道的sql服务器提供程序充满了bug,而上面的bug是最无辜的。 它有空值的问题,连接池的问题(这是一个非常严重的问题 – 如果你在连接池连接超时 – 这个连接将在整个生命周期中断, 所有在该连接上的查询将失败。如果你的查询超时了),等等。大多数这些错误是已知的多年,而不是固定的。 如果你有选择 – 只要使用postgresql,它是免费的,好,我没有在单声道的问题。