如何更改Entity Framework为Datetime生成SQL精度的方式

时间:2017-09-24 07:14:10

标签: c# sql-server entity-framework datetime

我有一张表使用id& DateTime列是pk,但是当我尝试按照以下实体框架更新数据时:

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'

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

2 个答案:

答案 0 :(得分:6)

您可以使用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)&#39;,@ 0 = 0,@ 1 = 1,@ 2 =&#39; 2017-09-24 14:41:33.7950485&#39;

  

@ 2 datetime&#39;,@ 0 = 0,@ 1 = 1,@ 2 =&#39; 2017-09-24 14:40:32.327&#39;

答案 1 :(得分:1)

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

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

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