为什么EF5代码中插入一个可空日期时间到数据库中,当第一次使用DATETIME2?(Why does

2019-07-18 01:45发布

我保存的购物车对象,有一个为空的日期时间数据库。 这是我的错误:

一个DATETIME2数据类型为datetime数据类型的转换导致外的范围内的值。

有相当多的计算器帖子记录修复这个问题。 然而,当代码首先创建数据库,将创建字段作为一个DateTime(允许空值)。 但由于某些原因,代码首先尝试使用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 */
    }    
}

该模型:

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 */
        }

}

所以无论是OpeningDateUtcClosingDateUtc是DateTime类型?

这是怎样的数据库得到由EF代码首先产生:

OpeningDateUtcClosingDateUtc作为一个可空DateTime字段创建。

那么,为什么当我保存使用IDBContext.SaveChanges()在查询生成的SQL是:

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

有趣的部分是@4 datetime2(7),@5 datetime2(7)

我明白,我可以通过添加一个解决这个问题.HasColumnType("datetime2")的车地图,但它没有回答为什么EF5(也可能是旧版本)将它们设置可空日期时间。

Answer 1:

DateTime在.NET类型有相同的范围和精度datetime2在SQL Server中。 当EF插入或更新datetimedatetime2在SQL Server它的模型属性转换为可容纳整个范围的类型列DateTime .NET中,这就是datetime2 。 转换成datetime如果将失败DateTime财产不在范围内datetime在SQL Server中。

导致异常的,顺便说一下,不是两个可为空的问题OpeningDateUtcClosingDateUtc列,但CreatedOnUtc这是值'0001-01-01 00:00:00'在你的SQL代码段,即CreatedOnUtc显然未初始化模型中的实体。 ,最早日期datetime在SQL Server可以存储在1750年,因此0001年将不适合的类型(但它会融入datetime2 )。

因此,解决方法是设置CreatedOnUtc为有效datetime值或-如你所知-定义类型, datetime2在映射。

但我同意,会有更少的混乱,如果EF将映射DateTime为默认属性datetime2



Answer 2:

设计的一次会议期间,EF队居然讨论了这个特定项目。 该决定是离开当前行为是。 以下是会议记录 ,可以给你更多的上下文。



文章来源: Why does EF5 code first use datetime2 when inserting a nullable datetime into the database?