将 datetime2 数据类型转换为 datetime 数据类型会导致值超出范围
Posted
技术标签:
【中文标题】将 datetime2 数据类型转换为 datetime 数据类型会导致值超出范围【英文标题】:Conversion of a datetime2 data type to a datetime data type results out-of-range value 【发布时间】:2009-08-26 00:39:55 【问题描述】:我有一个包含 5 列的数据表,其中一行被数据填充,然后通过事务保存到数据库中。
保存时返回错误:
将 datetime2 数据类型转换为 datetime 数据类型导致值超出范围
这意味着,如阅读,我的数据表的类型为DateTime2
,我的数据库类型为DateTime
;这是错误的。
日期列设置为DateTime
,如下所示:
new DataColumn("myDate", Type.GetType("System.DateTime"))
问题
这可以在代码中解决还是必须在数据库级别进行更改?
【问题讨论】:
【参考方案1】:如果在字段不接受 NULLDateTime 字段时没有为该字段赋值强>价值观。
这为我解决了问题!
【讨论】:
在实体框架中,如果你添加了一个非空的 Created 列,然后更新你的 EDMX,当你没有在代码中设置值时,可能会以这种方式抛出这个错误 是什么为您解决了这个问题?当您有一个将 getdate() 调用作为默认值的日期时间字段时,会出现此错误。 为什么实体框架不能忽略如果 NULL,因为在我的 SQL 端,我有一个默认值 = getdate()? 我相信它发生的是 EntityFramework 看到一个 DateTime.MinValue ,它是 0001 年,并且在 SQL 中 datetime 超出了范围值,因此它将这个值作为 DateTime2 (支持 0001 年)值发送,所以插入/更新是有效的,但是当 SQL 尝试将此 DateTime2 转换为 DateTime 时它会失败,因为这将导致不同的值。两种解决方案是:1 在模型中使用可为空的日期时间或 2. 在保存上下文更改之前将所有日期时间值初始化为正确的值。您所做的选择取决于日期时间在您的模型中的含义。 @GuillermoRuffino 的解决方案对我有用。检查所有字段并找到那些 0001 年的条目。【参考方案2】:DATETIME
和 DATETIME2
在 .NET 中都映射到 System.DateTime
- 您不能真正进行“转换”,因为它实际上是相同的 .NET 类型。
查看 MSDN 文档页面:http://msdn.microsoft.com/en-us/library/bb675168.aspx
这两个“SqlDbType
”有两个不同的值 - 您可以在 DataColumn
定义中指定这些值吗?
但是:在 SQL Server 上,支持的日期范围完全不同。
DATETIME
支持 1753/1/1 到“永恒”(9999/12/31),而DATETIME2
支持 0001/1/1 到永恒。
所以你真正需要做的是检查日期的年份 - 如果它在 1753 之前,你需要将它更改为 1753 之后的值,以便 SQL Server 中的 DATETIME
列处理它。
马克
【讨论】:
这解释了我遇到的问题。虽然很少有情况需要处理 1753/1/1 之前的实际日期,但在很多情况下获取默认值 0001/1/1 可能会导致错误。 我确认,当我尝试将 'new DateTime()' 插入到 'datetime' 数据类型时,我收到了这个异常。 我试图在写入数据库的 C# 代码中指定 DateTime.MinValue 的默认值。这解释了我遇到的错误。 +1 我使用 Entity Framework Code First 并使用具有 DateTime 属性的模型。DtInit = new System.DateTime(1492, 10, 12),
失败。
这是真正原因隐藏在补丁后面的情况之一...... +1【参考方案3】:
在我的 SQL Server 2008 数据库中,我有一个 DateTime
列标记为不可为空,但将 GetDate()
函数作为其默认值。使用 EF4 插入新对象时,我收到此错误,因为我没有明确传递对象上的 DateTime 属性。我希望 SQL 函数为我处理日期,但它没有。我的解决方案是从代码中发送日期值,而不是依赖数据库来生成它。
obj.DateProperty = DateTime.now; // C#
【讨论】:
很高兴为您提供帮助。这很烦人,因为您认为 EF 数据上下文能够在从表中创建对象时发现该字段具有默认值。 我想很多关于 EF 的事情。我正在使用 POCO 自我跟踪实体,它就是这样一个集群。我将检查代码优先模型,如果这也充满废话,我正在认真考虑回到 linq to sql 并使用对象映射器将道具映射到我自己的实体... 两周前我在 VS Live 上看到了 EF Code First 的演示,它看起来很棒,顺便说一句。 这是个好消息。我们很快将在我的办公室启动一个新项目,我在 EF-CF 和 dapper(由 SO 使用/维护)上分裂。它可能会归结为在通过 WCF 服务使用的应用程序中哪个更好。 你好,一岁的 cmets!我自己从 EF Code-First 开始,发现在我的 POCO 上我只需要将我的日期时间成员定义为Nullable<DateTime>
,并且在代码中我可以将它真正保留为空(而不是 01/01/0000)。我很惊喜地看到 EF to SQL 知道在 INSERT 上忽略这个 null 并使用来自服务器的日期 (GetDate()
)... 对我们来说这甚至更可取,因为我们需要更好的服务器一致性,而不用担心webserver 和 sql server 的时钟差异。【参考方案4】:
对我来说这是因为日期时间是..
01/01/0001 00:00:00
在这种情况下,您想将 null 分配给您的 EF DateTime 对象...以我的 FirstYearRegistered 代码为例
DateTime FirstYearRegistered = Convert.ToDateTime(Collection["FirstYearRegistered"]);
if (FirstYearRegistered != DateTime.MinValue)
vehicleData.DateFirstReg = FirstYearRegistered;
【讨论】:
我正在使用 ExcelDataReader 解析此数据,当输入无效文本时它返回 01/01/0001(不会按预期抛出异常 - 使用 .GetDateTime(columnIndex) 方法)。与 MinValue 的比较起到了防止 sql 中超出范围异常的作用。【参考方案5】:这个让我发疯。我想避免使用可为空的日期时间 (DateTime?
)。我也没有使用 SQL Server 2008 的 datetime2
类型的选项
modelBuilder.Entity<MyEntity>().Property(e => e.MyDateColumn).HasColumnType("datetime2");
我最终选择了以下:
public class MyDb : DbContext
public override int SaveChanges()
UpdateDates();
return base.SaveChanges();
private void UpdateDates()
foreach (var change in ChangeTracker.Entries<MyEntityBaseClass>())
var values = change.CurrentValues;
foreach (var name in values.PropertyNames)
var value = values[name];
if (value is DateTime)
var date = (DateTime)value;
if (date < SqlDateTime.MinValue.Value)
values[name] = SqlDateTime.MinValue.Value;
else if (date > SqlDateTime.MaxValue.Value)
values[name] = SqlDateTime.MaxValue.Value;
【讨论】:
使用[Column(TypeName = "datetime2")]
?【参考方案6】:
有时 EF 不知道正在处理计算列或触发器。按照设计,这些操作将在插入后在 EF 之外设置一个值。
解决方法是在 EF 的 edmx
中为 StoreGeneratedPattern
属性中的该列指定 Computed
。
对我来说,当列有一个插入当前日期和时间的触发器时,请参见下面的第三部分。
解决步骤
在 Visual Studio 中打开 Model Browser
页面,然后打开 Model
然后 Entity Types
-> 然后
-
选择实体和日期时间属性
选择
StoreGeneratedPattern
设置为Computed
对于这种情况,其他答案是解决方法,因为该列的目的是在创建记录时指定时间/日期,这是 SQL 执行触发器以添加正确时间的工作。比如这个 SQL 触发器:
DEFAULT (GETDATE()) FOR [DateCreated]
。
【讨论】:
请注意,我使用了GETDATE()
,我当时确实这样做了。但最近有一条评论说,我认为任何 DateTime2 操作都应该使用SYSDATETIME()
,我认为这是正确的。【参考方案7】:
我遇到了这个问题,并将以下内容添加到我的 datetime 属性中:
[Column(TypeName = "datetime2")]
public DateTime? NullableDateTimePropUtc get; set;
【讨论】:
using System.ComponentModel.DataAnnotations.Schema;
必填【参考方案8】:
如果我们不传递日期时间到日期时间字段,则会传递默认日期 1/1/0001 12:00:00 AM。
但是这个日期与实体框架不兼容,所以它会抛出 将 datetime2 数据类型转换为 datetime 数据类型导致值超出范围
如果您没有传递任何日期,只需 default DateTime.now
到日期字段。
movie.DateAdded = System.DateTime.Now
【讨论】:
我会说将 'DateTime.Now' 作为默认值传递远非正确,而且相当具有误导性。【参考方案9】:最简单的方法是将数据库更改为使用 datetime2 而不是 datetime。兼容性很好,不会出现错误。
你仍然想做一堆测试......
该错误可能是因为您尝试将日期设置为 0 年或其他内容 - 但这完全取决于您可以控制更改内容的位置。
【讨论】:
【参考方案10】:我发现这篇文章试图弄清楚为什么我不断收到以下错误,其他答案对此进行了解释。
将 datetime2 数据类型转换为 datetime 数据类型导致值超出范围。
使用可为空的 DateTime 对象。 公共日期时间?购买日期 得到;放;
如果您使用的是实体框架 将 edmx 文件中的可为空属性设置为 True
【讨论】:
【参考方案11】:正如andyuk 已经指出的那样,当将 NULL 值分配给不可为空的 DateTime 字段时,可能会发生这种情况。考虑将 DateTime 更改为 DateTime? 或 NullableDateTime>。请记住,如果您使用 Dependency Property,还应确保您的依赖属性的类型也是可为空的 DateTime 类型。
以下是不完整的 DateTime 到 DateTime? 类型调整的真实示例,该调整会引发奇怪的行为
【讨论】:
【参考方案12】:Entity Framework 4 使用 datetime2 数据类型,因此在 db 中,对于 SQL Server 2008,对应的字段必须是 datetime2。
要获得解决方案,有两种方法。
-
要在实体框架 4 中使用日期时间数据类型,您必须将 edmx 文件中的 ProviderManifestToken 切换为“2005”。
如果您将相应字段设置为 Allow Null(它将其转换为 NULLABLE),那么 EF 会自动使用日期对象作为日期时间。
【讨论】:
我了解了您对我的数据库模型(POCO 类)的第二点,并想知道如何将字段设置为可为空的类型。如果有人想知道,您可以通过在日期类型后添加问号 (?) 来做到这一点。例如公共日期时间?开始时间 得到;放;这为我解决了这个问题。我唯一需要做的就是在一行代码周围放置一个 TimeSpan 强制转换,在该代码行中我将两个可以为空的 DateTime 值相减。例如var timeTaken = (TimeSpan) (endTime - startTime);【参考方案13】:基于@sky-dev 实现创建了一个基类。所以这可以很容易地应用于多个上下文和实体。
public abstract class BaseDbContext<TEntity> : DbContext where TEntity : class
public BaseDbContext(string connectionString)
: base(connectionString)
public override int SaveChanges()
UpdateDates();
return base.SaveChanges();
private void UpdateDates()
foreach (var change in ChangeTracker.Entries<TEntity>())
var values = change.CurrentValues;
foreach (var name in values.PropertyNames)
var value = values[name];
if (value is DateTime)
var date = (DateTime)value;
if (date < SqlDateTime.MinValue.Value)
values[name] = SqlDateTime.MinValue.Value;
else if (date > SqlDateTime.MaxValue.Value)
values[name] = SqlDateTime.MaxValue.Value;
用法:
public class MyContext: BaseDbContext<MyEntities>
/// <summary>
/// Initializes a new instance of the <see cref="MyContext"/> class.
/// </summary>
public MyContext()
: base("name=MyConnectionString")
/// <summary>
/// Initializes a new instance of the <see cref="MyContext"/> class.
/// </summary>
/// <param name="connectionString">The connection string.</param>
public MyContext(string connectionString)
: base(connectionString)
//DBcontext class body here (methods, overrides, etc.)
【讨论】:
【参考方案14】:我在一个简单的控制台应用程序项目中遇到了这个问题,我的快速解决方案是通过运行此方法将任何可能的 datetime2 日期转换为可为空的日期时间:
static DateTime? ParseDateTime2(DateTime? date)
if (date == null || date.ToString() == "1/1/0001 12:00:00 AM")
return null;
else
return date;
这当然不是一个完全全面的方法,但它满足了我的需求,也许它会帮助其他人!
【讨论】:
这帮助我意识到我的审计功能没有在我的模型上运行,因为没有触及默认日期值。这可能不是答案的预期用途,但它是震撼我的线索。 DateTime 的默认值在插入时超出范围。回顾一下,我只是忘记在我们的模型类上实现一个审计信息接口......经过漫长的一天可能很难找到......【参考方案15】:在模型类的属性上添加下面提到的属性。
Attribute = [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
Reference = System.ComponentModel.DataAnnotations.Schema
一开始我忘了添加这个属性。所以在我的数据库中,约束的创建类似于
ALTER TABLE [dbo].[TableName] ADD DEFAULT (getdate()) FOR [ColumnName]
我添加了这个属性并更新了我的数据库然后它变成了
ALTER TABLE [dbo].[TableName] ADD CONSTRAINT [DF_dbo.TableName_ColumnName] DEFAULT (getdate()) FOR [ColumnName]
【讨论】:
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]【参考方案16】:在我的例子中,我们将一个日期转换为一个日期时间,我们得到了这个错误。 What happens is that Date has a "more programmer oriented" minimum of 01/01/0001, while Datetime is stuck at 1753
将它与我们的数据收集错误结合起来,您就会得到例外!
【讨论】:
America Discover 1492,如果不使用则错误 datetime2【参考方案17】:有时它在开发机器上运行良好,而不是在服务器上运行良好。就我而言,我不得不说:
<globalization uiCulture="es" culture="es-CO" />
在 web.config 文件中。
机器(服务器)中的时区是正确的(对于 CO 区域设置),但网络应用程序不正确。此设置完成,并且再次正常工作。
当然,所有日期都有价值。
:D
【讨论】:
【参考方案18】:将此代码添加到 ASP.NET 中的类对我有用:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
modelBuilder.Properties<DateTime>().Configure(c => c.HasColumnType("datetime2"));
【讨论】:
【参考方案19】:我知道这个问题,你们也应该知道:
https://en.wikipedia.org/wiki/Year_2038_problem
在 SQL 中创建了一个新的字段类型来避免这个问题 (datetime2)。
此“日期”字段类型具有与 DateTime .Net 类相同的范围值。它会解决你所有的问题,所以我认为解决它的最好方法是改变你的数据库列类型(它不会影响你的表数据)。
【讨论】:
【参考方案20】:查看以下两个: 1) 该字段没有 NULL 值。例如:
public DateTime MyDate get; set;
替换为:
public DateTime MyDate get; set; =DateTime.Now;
2) 再次新建数据库。例如:
db=new MyDb();
【讨论】:
如果您不希望该值默认为 DateTime.Now 怎么办? 如果你不想:DateTime.Now。您可以使用:new DateTime(... , ... , ...)【参考方案21】:继承日期时间属性的问题
当不可为空的日期字段在插入/更新时的值为 null 时,通常会显示此错误消息。一个原因可能是继承。
如果您的日期是从基类继承的并且您不进行映射,则 EF 将不会读取它的值。
更多信息: https://weblogs.asp.net/manavi/inheritance-mapping-strategies-with-entity-framework-code-first-ctp5-part-3-table-per-concrete-type-tpc-and-choosing-strategy-guidelines
【讨论】:
【参考方案22】:当我想编辑一个使用 ASP.Net MVC 的页面时,我看到了这个错误。创建但更新数据库时我没有问题,但我的 DateCreated 属性超出了范围!
当您不希望您的 DateTime
属性为 Nullable 并且不想检查其值是否在 sql DateTime 范围内(而 @html.HiddenFor
没有帮助!)时,只需添加一个 static DateTime
字段在相关类(控制器)中,并在 GET 运行时为其赋值,然后在 POST 运行时使用它:
public class PagesController : Controller
static DateTime dateTimeField;
UnitOfWork db = new UnitOfWork();
// GET:
public ActionResult Edit(int? id)
Page page = db.pageRepository.GetById(id);
dateTimeField = page.DateCreated;
return View(page);
// POST:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(Page page)
page.DateCreated = dateTimeField;
db.pageRepository.Update(page);
db.Save();
return RedirectToAction("Index");
【讨论】:
【参考方案23】:检查数据库中的请求格式。例如我的数据库有默认值或绑定(((1)/(1))/(1900))
System.DateTime MyDate = new System.DateTime( 1900 ,1, 1);
【讨论】:
【参考方案24】:对我来说,我有一个 Devexpress DateEdit 组件,它通过 Nullable 模型属性绑定到可为空的日期时间 MSSQL 列。我所要做的就是在 DateEdit 上设置 AllowNullInput = True。将其设置为“默认”会导致日期 1.1.0001 出现 - 仅在离开 DateEdit 之前 - 然后由于上述后续说明,我收到了此转换错误消息。
【讨论】:
【参考方案25】:在我的情况下,当为 Nullable DateTime 列显式分配 NULL 值时,然后您尝试保存更改。会弹出这个错误。
【讨论】:
【参考方案26】:您将拥有设置为小于允许的 dattime 的最小值的日期列,例如 1/1/1001。
要解决这个问题,您可以为您的属性设置正确的日期时间值,还可以设置另一个神奇的属性,例如 IsSpecified=true。
【讨论】:
以上是关于将 datetime2 数据类型转换为 datetime 数据类型会导致值超出范围的主要内容,如果未能解决你的问题,请参考以下文章
将 datetime2 数据类型转换为 datetime 数据错误
将 datetime2 数据类型转换为 datetime 数据类型会导致值超出范围
将 datetime2 数据类型转换为 datetime 数据类型导致值超出范围
哪一列导致“将 datetime2 数据类型转换为 datetime 数据类型导致值超出范围”?
如何识别列抛出 System.Data.SqlClient.SqlException? (将 datetime2 数据类型转换为 datetime 数据类型)