简体   繁体   English

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

[英]How to change how Entity Framework generates SQL precision for Datetime

I have a table use id & DateTime column be the pk, but when I try to update data by Entity Framework like this: 我有一个使用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();
}

I get an error 我得到一个错误

Store update, insert, or delete statement affected an unexpected number of rows (0). 存储更新,插入或删除语句影响了意外的行数(0)。

After I recorded the SQL, I know the reason now. 记录完SQL之后,现在知道原因了。

The SQL looks like this 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'

So, the reason is BatchData_CreatedDateTime parameter in the SQL is @2='2017-09-16 11:29:35.3720000' , the precision is 7 and it should be @2='2017-09-16 11:29:35.372' . 因此,原因是SQL中的BatchData_CreatedDateTime参数为@2='2017-09-16 11:29:35.3720000' ,精度为7且​​应为@2='2017-09-16 11:29:35.372'

And here is my question, How to fix it? 这是我的问题,如何解决?

You can use IDbInterceptor to change required data, here is an example of interceptor that changes type of parameters from DateTime2 to DateTime , you can extend it to use it on a specific fields of your DB / DbCommand parameters. 您可以使用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;
        }
    }

To use it add DbInterception.Add(new DateInterceptor()); 要使用它,请添加DbInterception.Add(new DateInterceptor()); into the end of OnModelCreating of your dbContext class 进入dbContext类的OnModelCreating的末尾

Generated SQL will be changed from 生成的SQL将从

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

to

@2 datetime',@0=0,@1=1,@2='2017-09-24 14:40:32.327' @ 2 datetime',@ 0 = 0,@ 1 = 1,@ 2 ='2017-09-24 14:40:32.327'

I presume this is SQL 2016 or Azure SQL Database. 我认为这是SQL 2016或Azure SQL数据库。

See this SO Question Entity Framework formats DateTime SQL parameter without milliseconds for optimistic concurrency 请参阅此SO问题实体框架格式(不带毫秒)的DateTime SQL参数以实现乐观并发

SQL 2016 has changed the way conversions work between datetime and datetime2. SQL 2016更改了datetime和datetime2之间的转换工作方式。 To use for optimistic concurrency, you it's better to use datetime2(7). 要用于乐观并发,最好使用datetime2(7)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM