0

我的系统首先是数据库,EF 4.3.1。

我有一个表,其中 PK 由两个 int 列和一个日期时间组成。该表是一个“评论”表,用于保留评论。

创建表 [dbo].[ArticleComments](
    [ArticleId] [int] 非空,
    [用户 ID] [int] 非空,
    [MessageText] [nvarchar](max) NOT NULL,
    [CreatedAt] [datetime] 非空,
    [外部数据] [bigint] NULL,
    约束 [PK_ArticleComments] 主键集群
    (
       [文章编号] ASC,
       [用户 ID] ASC,
       [创建时间] ASC
    )
)

在我的逻辑中,当创建评论时,我将 ArticleComment 对象发送到另一个线程,在该线程中打开另一个上下文以对对象执行其他操作,最终可以在其中保存对象。

问题是,当对象稍后被保存时,它有时会抛出一个没有保存的异常。

我打开探查器查看执行的 SQLSaveChanges()

exec sp_executesql N'update [dbo].[ArticleComments]
设置 [外部数据] = @0
其中 ((([ArticleId] = @1) 和 ([UserId] = @2)) 和 ([CreatedAt] = @3))
',N'@0 bigint,@1 int,@2 int,@3 datetime2(7)',@0=3243423,@1=6931,@2=2,@3='2012-10-11 11: 23:25.4734801'

并发现问题在于 EF 将其映射到 datetime2(7) 以代替常规日期时间,这就是为什么此更新不会更改任何内容并引发异常的原因。

我检查了 EDMX 文件,那里说类型是日期时间,精度为 3。

仅供参考:此外,日期时间在 SQL Server 中四舍五入

所以,我发现这篇文章:Round .NET DateTime milliseconds, so it can fit SQL Server milliseconds 这显示了将 .net 时间四舍五入到 SQL 时间的好方法。我认为在Microsoft® SQL Server® 2012的Microsoft® System CLR Types框架 中有一个类可以做同样的事情。System.Data.SqlTypesSqlDateTime

所以我的代码看起来像这样(使用刚刚链接的 SO 答案的扩展名):

破解时间 --> message.CreatedAt = message.CreatedAt.RoundToSqlServerDateTime();
                    db.ArticleComments.Attach(消息);
                    message.ExternalData = someNumber;
                    db.SaveChanges();

它有效。

但所有这些都是技巧,而不是解决方案。为什么 EF 在这里失败,我做错了什么?

4

0 回答 0