如何更改实体框架为日期时间生成 SQL 精度的方式

Posted

技术标签:

【中文标题】如何更改实体框架为日期时间生成 SQL 精度的方式【英文标题】:How to change how Entity Framework generates SQL precision for Datetime 【发布时间】:2018-03-05 09:09:49 【问题描述】:

我有一个表使用 id 和 DateTime 列作为 pk,但是当我尝试通过 Entity Framework 更新数据时:

using (Entities context = new Entities())

    var item = (from item in context.BatchData
                where item.Id == 2
                select item ).FirstOrDefault();

    item.Title = "EF6TEST";

    context.SaveChanges();

我收到一个错误

存储更新、插入或删除语句影响了意外的行数 (0)。

记录SQL后,我现在知道原因了。

SQL 是这样的

'update [dbo].[BatchData]
set [BatchData_Title] = @0
where (([BatchData_Id] = @1) and ([BatchData_CreatedDateTime] = @2))

select [BatchData_Rowversion]
from [dbo].[BatchData]BatchUploadData
where @@ROWCOUNT > 0 and [BatchData_Id] = @1 and [BatchData_CreatedDateTime]     = @2',
N'@0 varchar(30),@1 tinyint,@2 datetime2(7)',
@0='EF6TEST',@1=1,@2='2017-09-16 11:29:35.3720000'

所以,原因是SQL中的BatchData_CreatedDateTime参数是@2='2017-09-16 11:29:35.3720000',精度是7,应该是@2='2017-09-16 11:29:35.372'

这是我的问题,如何解决?

【问题讨论】:

你的 sql server 使用什么数据类型? DateTime 还是 DateTime2? 我的 sql server 使用 DateTime SQL Server 中 DateTime 的精度为毫秒 (.fff)。所以 .372 在 sql server 端是正确的但是,.NET DateTime 会返回 7 的精度,你可以将你的数据类型更新为 DateTime2 吗? 我怕改不了,能改生成器sql吗? 【参考方案1】:

我认为这是 SQL 2016 或 Azure SQL 数据库。

请参阅此 SO 问题 Entity Framework formats DateTime SQL parameter without milliseconds for optimistic concurrency

SQL 2016 改变了 datetime 和 datetime2 之间的转换方式。要用于乐观并发,最好使用 datetime2(7)。

【讨论】:

【参考方案2】:

您可以使用IDbInterceptor 来更改所需的数据,这里是一个拦截器示例,它将参数类型从DateTime2 更改为DateTime,您可以将其扩展为在您的DB / DbCommand 的特定字段上使用它参数。

public class DateInterceptor : IDbInterceptor, IDbCommandInterceptor

    public void ReaderExecuting(DbCommand command, 
        DbCommandInterceptionContext<DbDataReader> interceptionContext)
    
        var dateParameters = command.Parameters.OfType<DbParameter>()
            .Where(p => p.DbType == DbType.DateTime2);
        foreach (var parameter in dateParameters)
        
            parameter.DbType = DbType.DateTime;
        
    

要使用它,请将 DbInterception.Add(new DateInterceptor()); 添加到您的 dbContext 类的 OnModelCreating 的末尾

生成的 SQL 将从

更改

@2 datetime2(7)',@0=0,@1=1,@2='2017-09-24 14:41:33.7950485'

@2 日期时间',@0=0,@1=1,@2='2017-09-24 14:40:32.327'

【讨论】:

非常感谢,我试过 DateInterceptor 。它奏效了

以上是关于如何更改实体框架为日期时间生成 SQL 精度的方式的主要内容,如果未能解决你的问题,请参考以下文章

如何获取实体框架生成的sql [重复]

如何更改实体框架项目以使用 Microsoft SQL Server

将实体框架连接字符串转换为 SQL Server Express

实体框架更改生成的多对多表的名称

实体框架,如何将 IQueryable 与多个 where 转换为 SQL 一起使用?

带有 Sql 视图的实体框架在生成 .sql 文件中显示为表