我有一个包含 5 列的数据表,其中一行被数据填充,然后通过事务保存到数据库中。
保存时,返回错误:
将 datetime2 数据类型转换为 datetime 数据类型导致值超出范围
这意味着,如阅读,我的数据表的类型是 DateTime2
,我的数据库是 DateTime
;那是错的。
日期列设置为 DateTime
,如下所示:
new DataColumn("myDate", Type.GetType("System.DateTime"))
问题
这可以在代码中解决还是必须在数据库级别进行更改?
简答
如果您未将值初始化为 DateTime 字段,则可能会发生这种情况;该字段不接受 NULL 值,它是一个值类型,因此将使用不可为空的 DateTime 类型的默认值。
设置值为我修复了它!
长答案
default(DateTime)
的值为 DateTime.MinValue
(或 new DateTime(1, 1, 1)
或 01/01/0001),它不是有效的 SQL datetime
值。
由于使用公历,SQL Server 日期时间的最低有效值为 01/01/1753
。但是,SQL Server DateTime2 支持从 01/01/0001 开始的日期。默认情况下,实体框架使用 DateTime2 来表示日期,因此生成的 SQL 会隐式地将生成的 DateTime2 值强制转换为 SQL Server 端的 DateTime 值。
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
列处理它。
马克
DtInit = new System.DateTime(1492, 10, 12),
失败。
在我的 SQL Server 2008 数据库中,我将 DateTime
列标记为不可为空,但将 GetDate()
函数作为其默认值。使用 EF4 插入新对象时,我收到此错误,因为我没有明确传递对象上的 DateTime 属性。我希望 SQL 函数为我处理日期,但它没有。我的解决方案是从代码中发送日期值,而不是依赖数据库来生成它。
obj.DateProperty = DateTime.now; // C#
Nullable<DateTime>
,在代码中我可以将其保留为空(而不是 01/01/0000)。我很惊喜地看到 EF 到 SQL 知道在 INSERT 上忽略这个 null 并使用来自服务器的日期 (GetDate()
)... 对我们来说这甚至更可取,因为我们需要在服务器上更好的一致性,而不用担心webserver 和 sql server 之间的时钟差异。
对我来说,这是因为日期时间是..
01/01/0001 00:00:00
在这种情况下,您想将 null 分配给您的 EF DateTime 对象...以我的 FirstYearRegistered 代码为例
DateTime FirstYearRegistered = Convert.ToDateTime(Collection["FirstYearRegistered"]);
if (FirstYearRegistered != DateTime.MinValue)
{
vehicleData.DateFirstReg = FirstYearRegistered;
}
这让我快疯了。我想避免使用可为空的日期时间 (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")]
?
有时 EF 不知道正在处理计算列或触发器。按照设计,这些操作将在插入后在 EF 之外设置一个值。
修复方法是在 EF 的 edmx
中为 StoreGeneratedPattern
属性中的该列指定 Computed
。
对我来说,当列有一个插入当前日期和时间的触发器时,请参见下面的第三部分。
解决步骤
在 Visual Studio 中打开 Model Browser
页面,然后打开 Model
,然后打开 Entity Types
->然后
选择实体和日期时间属性 Select StoreGeneratedPattern Set to Computed
https://i.stack.imgur.com/EOSuR.png
对于这种情况,其他答案是解决方法,该列的目的是在创建记录时指定时间/日期,这是 SQL 执行触发器以添加正确时间的工作。比如这个 SQL 触发器:
DEFAULT (GETDATE()) FOR [DateCreated]
。
GETDATE()
,我当时确实这样做了。但是最近有一条评论说,我认为应该将 SYSDATETIME()
用于任何 DateTime2 操作。
我遇到了这个并将以下内容添加到我的 datetime 属性中:
[Column(TypeName = "datetime2")]
public DateTime? NullableDateTimePropUtc { get; set; }
using System.ComponentModel.DataAnnotations.Schema;
必填
如果我们不传递日期时间字段,则默认日期 {1/1/0001 12:00:00 AM} 将被传递。
但是此日期与实体框架不兼容,因此它会将 datetime2 数据类型转换为 datetime 数据类型导致超出范围的值
如果您没有传递任何日期,只需 default DateTime.now
到日期字段。
movie.DateAdded = System.DateTime.Now
最简单的方法是将数据库更改为使用 datetime2 而不是 datetime。兼容性很好,你不会得到你的错误。
你仍然想做一堆测试......
该错误可能是因为您尝试将日期设置为 0 年或其他内容 - 但这完全取决于您可以控制更改内容的位置。
我发现这篇文章试图弄清楚为什么我不断收到以下错误,其他答案对此进行了解释。
将 datetime2 数据类型转换为 datetime 数据类型导致值超出范围。
使用可为空的 DateTime 对象。公共日期时间?购买日期 { 得到;放; }
如果您使用实体框架 将 edmx 文件中的可为空属性设置为 True
https://i.stack.imgur.com/JCCA3.png
正如 andyuk 已经指出的,当将 NULL 值分配给不可为空的 DateTime 字段时,可能会发生这种情况。考虑将 DateTime 更改为 DateTime? 或 Nullable<DateTime>。请记住,如果您使用 Dependency Property,还应确保您的依赖项属性的类型也是可为空的 DateTime 类型。
下面是一个不完整的 DateTime 到 DateTime 的真实示例?引发奇怪行为的类型调整
https://i.stack.imgur.com/2lR6K.png
Entity Framework 4 使用 datetime2 数据类型,因此在 db 中,对于 SQL Server 2008,相应的字段必须是 datetime2。
要获得解决方案,有两种方法。
要在实体框架 4 中使用日期时间数据类型,您必须将 edmx 文件中的 ProviderManifestToken 切换为“2005”。如果您将相应的字段设置为 Allow Null(它将其转换为 NULLABLE),那么 EF 会自动将日期对象用作日期时间。
在模型类的属性上添加下面提到的属性。
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]
基于@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.)
}
我在一个简单的控制台应用程序项目中遇到了这个问题,我的快速解决方案是通过运行此方法将任何可能的 datetime2 日期转换为可为空的日期时间:
static DateTime? ParseDateTime2(DateTime? date)
{
if (date == null || date.ToString() == "1/1/0001 12:00:00 AM")
{
return null;
}
else
{
return date;
}
}
这当然不是一个完全全面的方法,但它可以满足我的需求,也许它会帮助其他人!
在我的情况下,当为 Nullable DateTime 列显式分配 NULL 值时,然后您尝试保存更改。会弹出这个错误。
在我的例子中,我们将一个日期转换为一个日期时间,我们得到了这个错误。 What happens is that Date has a "more programmer oriented" minimum of 01/01/0001, while Datetime is stuck at 1753
将它与我们的数据收集错误结合起来,您就会得到例外!
有时它在开发机器上运行良好,而不是在服务器上运行良好。就我而言,我不得不说:
<globalization uiCulture="es" culture="es-CO" />
在 web.config 文件中。
机器(服务器)中的时区是正确的(对于 CO 区域设置),但 Web 应用程序没有。此设置完成,并且再次正常工作。
当然,所有日期都有价值。
:D
将此代码添加到 ASP.NET 中的类对我有用:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Properties<DateTime>().Configure(c => c.HasColumnType("datetime2"));
}
我知道这个问题,你们也应该是:
https://en.wikipedia.org/wiki/Year_2038_problem
在 SQL 中创建了一个新的字段类型来避免这个问题 (datetime2)。
此“日期”字段类型具有与 DateTime .Net 类相同的范围值。它会解决你所有的问题,所以我认为解决它的最好方法是改变你的数据库列类型(它不会影响你的表数据)。
检查以下两个:1)该字段没有NULL值。例如:
public DateTime MyDate { get; set; }
替换为:
public DateTime MyDate { get; set; }=DateTime.Now;
2) 再次新建数据库。例如:
db=new MyDb();
继承日期时间属性的问题
当不可为空的日期字段在插入/更新时的值为 null 时,通常会显示此错误消息。一个原因可能是继承。
如果您的日期是从基类继承的并且您没有进行映射,则 EF 将不会读取它的值。
当我想编辑一个使用 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");
}
}
检查数据库中的请求格式。例如我的数据库有默认值或绑定 (((1)/(1))/(1900))
System.DateTime MyDate = new System.DateTime( 1900 ,1, 1);
https://i.stack.imgur.com/J3a9Z.png
对我来说,我有一个 Devexpress DateEdit 组件,它通过 Nullable 模型属性绑定到可为空的日期时间 MSSQL 列。我所要做的就是在 DateEdit 上设置 AllowNullInput = True。将其设置为“默认”会导致日期 1.1.0001 出现 - 仅在离开 DateEdit 之前 - 然后由于上述后续说明,我收到了此转换错误消息。
对于代码优先上下文:
从此走
public DateTime Created { get; set; }
对此。添加 [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
属性。
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime Created { get; set; }
在你的模型中。
确保也将其添加到顶部
using System.ComponentModel.DataAnnotations.Schema;
您将拥有日期列,该列设置为小于允许的 dattime 的最小值,例如 1/1/1001。
为了克服这个问题,您可以为您的属性设置正确的日期时间值,还可以设置另一个神奇的属性,例如 IsSpecified=true。
不定期副业成功案例分享