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

时间:2010-08-27 17:08:31

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

出现此错误:

  

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

我的实体对象全部排列到数据库对象。

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

Google result

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

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

填充了日期字段

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

数据库是SQL Server 2008。

思想?

错误的其余部分:

  

at System.Data.Mapping.Update.Internal.UpdateTranslator.Update(IEntityStateManager stateManager,IEntityAdapter adapter)   在System.Data.EntityClient.EntityAdapter.Update(IEntityStateManager entityCache)   在System.Data.Objects.ObjectContext.SaveChanges(SaveOptions选项)   在SpeciesPost.svc.cs中的SafariAdmin.Site.WebServices.SpeciesPost.SaveOrUpdateSpecies(String sid,String fieldName,String authToken):第58行   在SpeciesPostSVC_Tester.cs中的SafariAdmin.TestHarness.Tests.Site.WebServices.SpeciesPostSVC_Tester.SaveNewSpecies()中:第33行   --SqlException   在System.Data.SqlClient.SqlConnection.OnError(SqlException异常,布尔breakConnection)   在System.Data.SqlClient.SqlInternalConnection.OnError(SqlException异常,布尔breakConnection)   在System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning()   在System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior,SqlCommand cmdHandler,SqlDataReader dataStream,BulkCopySimpleResultSet bulkCopyHandler,TdsParserStateObject stateObj)   在System.Data.SqlClient.SqlDataReader.ConsumeMetaData()   在System.Data.SqlClient.SqlDataReader.get_MetaData()   在System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds,RunBehavior runBehavior,String resetOptionsString)   在System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior,RunBehavior runBehavior,Boolean returnStream,Boolean async)   在System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior,RunBehavior runBehavior,Boolean returnStream,String method,DbAsyncResult result)   在System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior,RunBehavior runBehavior,Boolean returnStream,String method)   在System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior,String method)   在System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior行为)   在System.Data.Common.DbCommand.ExecuteReader(CommandBehavior行为)   在System.Data.Mapping.Update.Internal.DynamicUpdateCommand.Execute(UpdateTranslator转换器,EntityConnection连接,字典2 identifierValues, List 1 generatedValues)   在System.Data.Mapping.Update.Internal.UpdateTranslator.Update(IEntityStateManager stateManager,IEntityAdapter adapter)

16 个答案:

答案 0 :(得分:65)

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

答案 1 :(得分:49)

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

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

答案 2 :(得分: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;

对我有用!

答案 3 :(得分:8)

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

Property(x => x.TheDateTimeField)
   .HasColumnType("datetime2");

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

答案 4 :(得分:7)

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

 [Column(TypeName = "datetime2")]
 public DateTime? PropertyName { get; set; }

答案 5 :(得分:5)

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

答案 6 :(得分:3)

首先使用Entity框架代码时,请将其声明为:

public Nullable<System.DateTime> LastLogin { get; set; }

答案 7 :(得分:2)

您的实体中是否存在ModifiedTime属性,仅在数据库端更新? 如果是这样,您必须使用DatabaseGeneratedOption.Computed(对于EF CodeFirst)。另请访问此https://stackoverflow.com/a/9508312/1317263

谢谢。

答案 8 :(得分:2)

我们遇到了同样的问题。这与mssql版本有关。 我们使用这种方法使它适用于我们所有的版本。

使用xml编辑器打开edmx文件 在文件顶部找到此行

<Schema Namespace="XXXXX.Store" Alias="Self" Provider="System.Data.SqlClient" ProviderManifestToken="2008"

在2005年之前取代2008年 保存文件,重新编译项目。

希望这将有助于未来的其他人。

我只使用dbfirst approche尝试了这个解决方案。

答案 9 :(得分:1)

日期时间适合哪种日期时间适合日期时间2数据类型,反之亦然,情况并非如此,您可以将日期1月1500日期保留在datetime2数据类型中,但日期时间只能返回1753,日期时间2列可以去一直回到一年1.我会检查你传递的最小日期是什么,以及你的表是否有datetime2或datetime数据类型列

答案 10 :(得分:1)

在尝试解决此问题几天之后,我使用DateTime?作为我的模型中的数据类型,使用了Entity Framework Code-First而不是DateTime

答案 11 :(得分:1)

确保在插入/更新时没有遗漏DB(datetime)中的任何非空字段。我有相同的错误,并且在向这些日期时间字段插入值时,问题已得到解决。如果未为空白日期时间字段分配正确的值,则会发生这种情况。

答案 12 :(得分:1)

我在ASP.Net MVC应用程序中遇到了同样的问题。

我的应用程序中有两个具有DateTime属性的模型类。

经过调查我注意到一个模型的DateTime属性可以为空,即使它成为出生日期的可选属性

另一个模型的DateTime属性具有必需的数据注释(保存此模型时出错)

我的应用程序是代码优先,所以我通过将数据类型设置为DateTime2

来解决问题
[Column(TypeName="datetime2")] 

然后我在包管理器控制台上运行了迁移。

答案 13 :(得分:0)

简单。 首先在代码中,将DateTime的类型设置为DateTime?。 因此,您可以在数据库中使用可空的DateTime类型。

答案 14 :(得分:0)

这是继stepanZ的答案之后......在Entity Framework Code FirstAutoMapper一起使用时出现此错误。

在设置AutoMapping时,我们会在createddt函数中自动设置updateddtcreatedbyupdatedbypublic override int SaveChanges()个字段。执行此操作时,您需要确保将这些字段设置为AutoMapper忽略,否则当null未提供这些字段时,数据库将使用View更新。< / p>

我的问题是我将源和目的地放错了方向,因此在设置ViewModel时尝试忽略字段,而不是在设置Model时忽略字段。

当我收到此错误时,Mapping看起来像这样(注意:第二行的cfg.CreateMap<Source, Destination>()正在将Model映射到ViewModel并设置{{ 1}})

Ignore()

对于从cfg.CreateMap<EventViewModel, Event>(); cfg.CreateMap<Event, EventViewModel>() .ForMember(dest => dest.CreatedBy, opt => opt.Ignore()) .ForMember(dest => dest.CreatedDt, opt => opt.Ignore()) .ForMember(dest => dest.UpdatedBy, opt => opt.Ignore()) .ForMember(dest => dest.UpdatedDt, opt => opt.Ignore()); ViewModel的映射,应忽略源和目标(注意:以下代码对Model放置Ignore()的映射是正确的转到ViewModel

Model

答案 15 :(得分:-1)

两种解决方案:

  • 如下所示声明类中的属性并创建update-database:

    public DateTime? MyDate {get; set;}
    
  • 或者在填充数据库的Seed方法中设置属性的日期,不需要update-database:

    context.MyClass.AddOrUpdate(y => y.MyName,new MyClass { MyName = "Random", MyDate= DateTime.Now })