Entity framework 为什么EF5代码在将可为空的datetime插入数据库时首先使用datetime2?

Entity framework 为什么EF5代码在将可为空的datetime插入数据库时首先使用datetime2?,entity-framework,datetime,ef-code-first,datetime2,Entity Framework,Datetime,Ef Code First,Datetime2,我正在将Cart对象保存到datetime为空的数据库中。这是我得到的错误: 将datetime2数据类型转换为datetime数据类型 导致值超出范围 有相当多的stackoverflow帖子记录了对这个问题的修复。但是,当代码第一次创建数据库时,它会将字段创建为日期时间(允许空值)。但出于某种原因,代码首先尝试使用DateTime2字段进行插入 我想知道为什么EF以一种方式创建字段,但对同一字段使用不同类型的插入 这是域对象: using System; using System.Colle

我正在将Cart对象保存到datetime为空的数据库中。这是我得到的错误:

将datetime2数据类型转换为datetime数据类型 导致值超出范围

有相当多的stackoverflow帖子记录了对这个问题的修复。但是,当代码第一次创建数据库时,它会将字段创建为日期时间(允许空值)。但出于某种原因,代码首先尝试使用DateTime2字段进行插入

我想知道为什么EF以一种方式创建字段,但对同一字段使用不同类型的插入

这是域对象:

using System;
using System.Collections.Generic;

namespace Core.Domain.Cart
{
    public partial class Cart : BaseEntity, ILocalizedEntity
    {
        private ICollection<Catalog> _catalogs;

        /// <summary>
        /// Gets or sets the name
        /// </summary>
        public virtual string Name { get; set; }

        /// <summary>
        /// Gets or sets the zone identifier
        /// </summary>
        public virtual int ZoneId { get; set; }

        /// <summary>
        /// Gets or sets the brand identifier
        /// </summary>
        public virtual int BrandId { get; set; }

        /// <summary>
        /// Gets or sets the customer type identifier
        /// </summary>
        public virtual int CustomerTypeId { get; set; }

        /// <summary>
        /// Gets or sets the date and time of the opening of a cart
        /// </summary>
        public virtual DateTime? OpeningDateUtc { get; set; }

        /// <summary>
        /// Gets or sets the date and time of the closing of a cart
        /// </summary>
        public virtual DateTime? ClosingDateUtc { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether the entity is online or not
        /// </summary>
        public virtual bool IsOnline { get; set; }

        /* Truncated for relevance */
    }    
}
有趣的部分是
@4datetime2(7),@5datetime2(7)


我知道我可以通过在购物车映射中添加一个
.HasColumnType(“datetime2”)
来解决这个问题,但它不能回答为什么EF5(可能还有更旧的版本)将它们设置为可为空的datetime。

在.NET中的
datetime
类型与SQL Server中的
datetime2
具有相同的范围和精度。当EF在SQL Server中插入或更新
datetime
datetime2
列时,它会将模型属性转换为可在.NET中保存整个
datetime
范围的类型,即
datetime2
。如果
datetime
属性不在SQL Server中的
datetime
范围内,则转换为
datetime
将失败

顺便说一句,导致异常的问题不是两个可为空的
OpeningDateUtc
ClosingDateUtc
列,而是
CreatedOnUtc
值,即SQL代码段中的
'0001-01-01 00:00:00'
,即
CreatedOnUtc
显然没有在模型实体中初始化。SQL Server中
datetime
可以存储的最早日期是1750年,因此0001年不适合该类型(但适合
datetime 2

因此,解决方案是将
CreatedOnUtc
设置为有效的
datetime
值,或者如您所知,在映射中将类型定义为
datetime2


但我同意,如果EF将默认的
DateTime
属性映射到
datetime2

,那么就不会有太多的混淆。EF团队实际上在一次设计会议上讨论了这个特定项目。决定是保持当前行为不变。以下是可以为您提供更多上下文信息的示例。

谢谢,我有一个解决方案。
using FluentValidation.Attributes;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;
using Telerik.Web.Mvc;


namespace Admin.Models.Cart
{
        [Validator(typeof(CartValidator))]
        public partial class CartModel : BaseNopEntityModel, ILocalizedModel<CartLocalizedModel>
        {            
            public CartModel()
            {
                Locales = new List<CartLocalizedModel>();
                Catalogs = new List<CatalogModel>();
                UnassociatedCatalogs = new List<CatalogModel>();
            }
            [NopResourceDisplayName("Admin.Carts.Fields.Name")]
            [AllowHtml]
            public string Name { get; set; }

            //Zone dropdown
            [NopResourceDisplayName("Admin.Carts.Fields.ZoneList")]
            public SelectList ZoneList { get; set; }        //The dropdown with zones
            public int ZoneId { get; set; }                 //The selected value of the dropdown once the form is submitted
            public string ZoneName { get; set; }            //The name of the zone to display in data-grid List view.

            //Brand dropdown
            [NopResourceDisplayName("Admin.Carts.Fields.BrandList")]
            public SelectList BrandList { get; set; }       //The dropdown with brands
            public int BrandId { get; set; }                //The selected value of the dropdown once the form is submitted
            public string BrandName { get; set; }           //The name of the brand to display in the data-grid List view. 

            //Customer type dropdown
            [NopResourceDisplayName("Admin.Carts.Fields.CustomerTypeList")]
            public SelectList CustomerTypeList { get; set; }//The dropdown with CustomerType
            public int CustomerTypeId { get; set; }         //The selected value of the dropdown once the form is submitted
            public string CustomerTypeName { get; set; }    //The name of the CustomerType to display in the data-grid List view. 

            [NopResourceDisplayName("Admin.Carts.Fields.OpeningDateUtc")]
            [UIHint("DateNullable")]
            public DateTime? OpeningDateUtc { get; set; }

            [NopResourceDisplayName("Admin.Carts.Fields.ClosingDateUtc")]
            [UIHint("DateNullable")]
            public DateTime? ClosingDateUtc { get; set; }

            [NopResourceDisplayName("Admin.Carts.Fields.IsOnline")]
            public bool IsOnline { get; set; }
            
            /* Truncated for relevance */
        }

}
exec sp_executesql N'update [dbo].[Cart]
set [Name] = @0, [ZoneId] = @1, [BrandId] = @2, [CustomerTypeId] = @3, [OpeningDateUtc] = @4, [ClosingDateUtc] = @5, [IsOnline] = @6, [IsReadonly] = @7, [IsPreviewMode] = @8, [CreatedOnUtc] = @9
where ([Id] = @10)
',N'@0 nvarchar(100),@1 int,@2 int,@3 int,@4 datetime2(7),@5 datetime2(7),@6 bit,@7 bit,@8 bit,@9 datetime2(7),@10 int',@0=N'Cart1',@1=7,@2=4,@3=5,@4='2013-01-09 00:00:00',@5='2013-01-18 00:00:00',@6=0,@7=0,@8=1,@9='0001-01-01 00:00:00',@10=1