在VS 2010 .net 4.0中使用实体框架时出现'datetime2'错误

Kev*_*eus 60 c# sql-server entity-framework sql-server-2008

得到此错误:

System.Data.SqlClient.SqlException:将datetime2数据类型转换为日期时间数据类型会导致超出范围的值.

我的实体对象全部排列到DB对象.

我通过Google发现只有一个引用此错误:

谷歌的结果

阅读本文之后,我记得我们确实添加了2个字段,然后从VS 2010更新了实体模型.我不确定他的意思是"手工编码"差异.我没有看到任何.

我在代码中所做的就是填充实体对象,然后保存.(我还在代码中填充新字段)我用DateTime.Now... 填充了日期字段

代码的重要部分是: ctx.SaveChanges(SaveOptions.AcceptAllChangesAfterSave);

该数据库是SQL Server 2008.

思考?

其余的错误:

在System.Data.Mapping.Update.Internal.UpdateTranslator.Update(IEntityStateManager stateManager,IEntityAdapter适配器)在System.Data.EntityClient.EntityAdapter.Update(IEntityStateManager entityCache)在System.Data.Objects.ObjectContext.SaveChanges(SaveOptions选项)在SafariAdmin.Site.WebServices.SpeciesPost.SaveOrUpdateSpecies(字符串SID,字符串fieldName的,字符串的authToken)在SpeciesPost.svc.cs:管线58在SafariAdmin.TestHarness.Tests.Site.WebServices.SpeciesPostSVC_Tester.SaveNewSpecies()在SpeciesPostSVC_Tester.cs:线33 --SqlException在System.Data.SqlClient.SqlConnection.OnError(SqlException异常,布尔breakConnection)在System.Data.SqlClient.SqlInternalConnection.OnError(SqlException异常,布尔breakConnection)在System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning()在System.Data.在System.Data的System.Data.SqlClient.SqlDataReader.get_MetaData()处的System.Data.SqlClient.SqlDataReader.ConsumeMetaData()处的SqlClient.TdsParser.Run(RunBehavior runBehavior,SqlCommand cmdHandler,SqlDataReader dataStream,BulkCopySimpleResultSet bulkCopyHandler,TdsParserStateObject stateObj). System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior)上的System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior,RunBehavior runBehavior,Boolean returnStream,Boolean async)中的SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds,RunBehavior runBehavior,String resetOptionsString) cmdBehavior,runBehavior runBehavior,布尔returnStream,字符串方法,DbAsyncResult结果)在System.Data.SqlClient.SqlCommand.RunExecuteReader(的CommandBehavior cmdBehavior,runBehavior runBehavior,布尔returnStream,在System.Data.SqlClient.SqlCommand.ExecuteReader(的CommandBehavior行为,串法)在System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(的CommandBehavior行为)在System.Data.Common.DbCommand.ExecuteReader(的CommandBehavior行为)在系统串法) .Data.Mapping.Update.Internal.DynamicUpdateCommand.Execute(UpdateTranslator translator,EntityConnection connection,Dictionary2 identifierValues, ListSystem.Data.Mapping.Update.Internal.UpdateTranslator.Update(IEntityStateManager stateManager,IEntityAdapter adapter)中的1 generatedValues)

Tej*_*ejo 65

实体框架将所有日期作为Datetime2处理,因此,如果数据库中的字段是Datetime,则可能会出现问题.我们在这里遇到了同样的问题,从我们发现的,填充所有日期字段和更改数据类型,是最常见的解决方案

  • 只是为Tejo的答案添加一个更好的点.实体框架不会将_all_日期视为Datetime2,只是那些超出正常SQL日期时间范围(1753年1月1日,9999年12月31日)或未初始化的DateTime字段的日期.我知道这仍然是一个恼人的EF设计错误.选择是:初始化您的DateTime字段; 将数据类型更改为Datetime2; 使字段在数据库中可为空,在代码中为Nullable <DateTime>,这样您就可以表示未初始化的值. (28认同)
  • 我是个傻瓜.我没有填充我所有的日期字段(显然我有2个) (8认同)
  • 关于EF - 它是否更有意义的是它使用了数据库表所使用的Date类型而不是任意假设每个人都应该使用DateTime2?真的是DateTime2 ?? - 他们不能只升级DateTime,他们必须创建一个新的数据类型,并巧妙地添加了2? (8认同)
  • 我不能判断你,我们的情况也是如此......甚至是解决方案 (2认同)
  • 有没有办法找出哪个列没有从Exception中填充,我似乎无法找到列名,使调试变得痛苦 (2认同)

小智 49

如果您使用的是Code First,则必须将任何可选DateTime属性声明为DateTime?Nullable<DateTime>.未设置的DateTime对象可能会导致问题.

如果属性在数据库中是可空的而DateTime代码中是标准的(不是DateTime?),则ADO.NET将发送日期为0001-01-01(不是NULL)的插入命令,但最小SQL DateTime值为1753-01-01 ,导致错误.如果DateTime代码中的属性可以为空(例如DateTime?或者Nullable<DateTime>),则insert命令将尝试插入NULL而不是超出范围的日期.


Rom*_*kin 13

使用该SQL脚本将所有列从datetime转换为datetime2.为方便起见,它会跳过包含'aspnet'的所有表格.

DECLARE @SQL AS NVARCHAR(1024)
DECLARE @TBL AS NVARCHAR(255)
DECLARE @COL AS NVARCHAR(255)
DECLARE @NUL AS BIT

DECLARE CUR CURSOR FAST_FORWARD FOR
    SELECT  SCHEMA_NAME(t.schema_id)+'.'+t.name, c.name, c.is_nullable
    FROM    sys.tables AS t
    JOIN    sys.columns c ON t.object_id = c.object_id
    JOIN    information_schema.columns i ON i.TABLE_NAME = t.name 
                                        AND i.COLUMN_NAME = c.name
    WHERE   i.data_type = 'datetime' and t.name not like '%aspnet%'

    ORDER BY t.name, c.name

OPEN CUR
FETCH NEXT FROM CUR INTO @TBL, @COL, @NUL
WHILE @@FETCH_STATUS = 0
BEGIN
    SELECT @SQL = 'ALTER TABLE ' + @TBL 
        + ' ALTER COLUMN [' + @COL + '] datetime2' 
        + (CASE WHEN @NUL=1 THEN '' ELSE ' NOT' END) + ' NULL;'
    EXEC sp_executesql @SQL
    FETCH NEXT FROM CUR INTO @TBL, @COL, @NUL
END

CLOSE CUR;
DEALLOCATE CUR;
Run Code Online (Sandbox Code Playgroud)

这个对我有用!


Ins*_*nsI 8

另一种可能的解决方案是将字段的sql列类型设置为datetime2.这可以使用fluentapi完成.

Property(x => x.TheDateTimeField)
   .HasColumnType("datetime2");
Run Code Online (Sandbox Code Playgroud)

注意:这是sql server 2008向上的解决方案,因为datetime2不适用于sql server 2005或更低版本.


Fer*_*ehy 7

我有同样的问题并通过将[Column(TypeName = "datetime2")]属性放入相关属性来解决它,如下面的示例:

 [Column(TypeName = "datetime2")]
 public DateTime? PropertyName { get; set; }
Run Code Online (Sandbox Code Playgroud)


小智 5

我知道这是一个老问题,但是当我在这里搜索时,其他人也可以这样做;-)对于那些从DateTime更改为DateTime2的人不是一个选项(对于SQL2005用户),我认为在大多数情况下是(DateTime)System.Data.SqlTypes.SqlDateTime.MinValue
使用DateTime.now 填充字段留空的更合理 ,因为它更容易将其识别为"伪空值"(并且如果需要将其转换为父对象的部分类中的实际null)