Sta*_*ams 4 windows sql-server mono debian entity-framework-core
我正在使用EntityFramework 7,beta7并具有以下实体:
C#
public class Log
{
[Column(TypeName ="datetime")]
public DateTime Date { get; set; }
...
}
Run Code Online (Sandbox Code Playgroud)
SQL
CREATE TABLE [dbo].[Logs] (
[Date] [datetime] NOT NULL,
...
)
Run Code Online (Sandbox Code Playgroud)
我执行以下操作:
db.Logs.Add(new Log { Date = DateTime.UtcNow });
db.SaveChanges();
Run Code Online (Sandbox Code Playgroud)
这在Windows上是成功的,但在debian上的mono下失败了.相同的SQL服务器/数据库.生成的SQL如下.请注意为@p1以下内容呈现的类型和值的差异:
视窗
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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
Linux上的失败是:
从字符串转换日期和/或时间时转换失败.
datetime2在显式设置类型时会生成datetime?datetime在mono/linux上插入值?.NET DateTime类型比sql server的"datetime"类型具有更宽的范围.实际上,.NET DateTime与sql server的"datetime2"类型具有相同的范围,这就是为什么Entity Framework在将DateTime转换为sql日期时会在任何地方使用datetime2(如果可能)(如示例所示).在这种情况下,表列的类型无关紧要.您可以阅读此设计会议记录,其中EF团队讨论了datetime和datetime2的问题,并决定将其保留原样(以及其背后的原因).
Mono使用TDS与sql服务器一起工作(基于FreeTDS,它使用了相当过时的版本.这个版本不知道sql server的"datetime2"类型,所以不要升级到新版本的TDS(也许这太过分了)现在工作了,实现了一种hack,将datetime2从\转换为字符串.现在,datetime2的精度高于datetime,所以将datetime2转换为string然后将该字符串转换为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
Run Code Online (Sandbox Code Playgroud)
你可以在这里阅读更多相关内容.
您可能会问,是否可以在单声道上使用EF与sql server.好吧,您可以通过在EF模型中将ProviderManifestToken设置为2005来解决此问题.这将使EF与sql server 2005一起使用,并且它不会在任何地方使用datetime2.但是你会丢失在sql server 2005之后添加的其他类型,更不用说那是脏黑客.
作为旁注 - 最好不要对带有sql server的mono进行任何认真的开发.单声道的SQL服务器提供程序充满了bug,上面的bug是最无辜的.它有空值的问题,连接池的问题(这个问题非常严重 - 如果你在连接池连接上超时 - 这个连接将在整个生命周期中被破坏,并且该连接上的所有查询都将失败.Hack - 从连接中删除连接池,如果你的查询超时),等等.大多数这些错误已知多年,并没有固定.如果你有选择 - 只需使用postgresql,它是免费的,好的,我在单声道上没有问题.
| 归档时间: |
|
| 查看次数: |
1379 次 |
| 最近记录: |