7

null 可能な日時を持つデータベースに Cart オブジェクトを保存しています。これは私が得るエラーです:

datetime2 データ型を datetime データ型に変換すると、範囲外の値になりました。

この問題の修正を文書化したスタックオーバーフローの投稿がかなりあります。ただし、コードが最初にデータベースを作成するときは、フィールドを DateTime (null を許可) として作成します。しかし、何らかの理由で、コードは最初に 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 */
        }

}

したがって、OpeningDateUtcと はどちらもClosingDateUtcDateTime? 型です。

これは、データベースが最初に EF コードによって生成される方法です。 EF 生成テーブル

OpeningDateUtcとはClosingDateUtc、null 許容の 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)です。

カートマップにa を追加することでこの問題を解決できることは理解して.HasColumnType("datetime2")いますが、EF5 (およびおそらく古いバージョン) がそれらを null 許容の日時に設定した理由はわかりません。

4

2 に答える 2

18

.NETのDateTime型は、SQLServerと同じ範囲と精度を持っていdatetime2ます。EFがSQLServerにdatetimeまたはdatetime2列を挿入または更新すると、モデルプロパティがDateTime.NETの全範囲を保持できるタイプに変換されますdatetime2。プロパティがSQLServerの範囲内にない場合、への変換datetimeは失敗します。DateTimedatetime

ちなみに、例外の原因となる問題は、2つのnull許容列OpeningDateUtcClosingDateUtc列ではなく、SQLスニペットにあるCreatedOnUtc値です。つまり、モデルエンティティで初期化されていないようです。SQL Serverで格納できる最も早い日付は1750年であるため、0001年はタイプに適合しません(ただし、に適合します)。'0001-01-01 00:00:00'CreatedOnUtcdatetimedatetime2

したがって、解決策はCreatedOnUtc、有効なdatetime値に設定するか、ご存知のようdatetime2に、マッピングのように型を定義することです。

DateTimeしかし、EFがデフォルトでプロパティをにマップする場合は、混乱が少なくなることに同意しますdatetime2

于 2013-01-09T21:17:08.380 に答える
11

EFチームは、設計会議の1つで、この特定の項目について実際に話し合いました。決定は、現在の動作をそのままにすることでした。これがあなたにもっと文脈を与えることができる会議ノートです。

于 2013-01-09T23:05:42.190 に答える