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


379

5つの列を持つデータテーブルがあり、行にデータが入力され、トランザクションを介してデータベースに保存されます。

保存中にエラーが返されます:

datetime2データ型からdatetimeデータ型への変換の結果、範囲外の値が発生しました

これは、読んだとおり、私のデータテーブルにはのタイプがDateTime2あり、私のデータベースにはがあることを意味しますDateTime。それは間違いです。

日付列は次のDateTimeように設定されています。

new DataColumn("myDate", Type.GetType("System.DateTime"))

質問

これはコードで解決できますか、それともデータベースレベルで何かを変更する必要がありますか?

回答:


60

列にはどのような日付がありますか?

それらのすべてがタイプの範囲内に収まりますか?


余談Typeですが、DataColumnコンストラクターのオブジェクトを取得する正しい方法はtypeofキーワードです。これは桁違いに高速です。

したがって、列を作成するには、次のように記述する必要があります

new DataColumn("myDate", typeof(DateTime))

3
データ列を変更し、typeofを使用しました...さらに問題が見つかりました。エラーを引き起こし、間違った日付を、含まれている1つのDataRowがあった
Gerbrand

739

これは、フィールドがNULL値を受け入れないときに、DateTimeフィールドに値を割り当てなかった場合に発生する可能性があります。

それで解決しました!


43
Entity Frameworkで、nullでないCreated列を追加した場合、コードで値を設定していないときにEDMXを更新すると、この方法でこのエラーがスローされる可能性があります
Brad Thomas

6
何がそれを修正しましたか?このエラーは、デフォルト値としてgetdate()を呼び出す日時フィールドがある場合に表示されます。
user3046061 2014

15
SQL側にデフォルト値= getdate()があるため、Entity FrameworkがNULLの場合に無視できないのはなぜですか?
JoshYates1980 2014

33
EntityFrameworkが年0001であるDateTime.MinValueを見て、SQLのdatetimeが範囲外の値であることをEntityFrameworkが確認しているため、この値はDateTime2(年0001をサポートする)値として送信されるため、挿入/更新は有効です。 SQLがこのDateTime2をDateTimeに変換しようとすると、別の値になるため失敗します。2つの解決策は次のとおりです。1モデルでnull可能な日付時刻を使用するか、2。コンテキストの変更を保存する前に、すべての日付時刻値を正しい値に初期化します。どちらを選択するかは、モデルでの日時の意味によって異なります。
Guillermo Ruffino 2016年

1
@GuillermoRuffinoの解決策がうまくいきました。すべてのフィールドを検査し、それらの0001年のエントリを見つけます。
Francesco B.

158

両方DATETIMEDATETIME2にマップSystem.DateTime.NETで-それは本当に同じ.NET型ですので、あなたが本当に、「変換」を行うことはできません。

MSDNのドキュメントページを参照してください:http : //msdn.microsoft.com/en-us/library/bb675168.aspx

SqlDbTypeこれら2つの「」には2つの異なる値があります- DataColumn定義でそれらを指定できますか?

ただし、SQL Serverでは、サポートされる日付範囲がかなり異なります。

DATETIMEは1753/1/1から "eternity"(9999/12/31)までをDATETIME2サポートし、0001/1/1からeternity までをサポートします。

したがって、実際に行う必要があるのは、日付の年を確認することです。それが1753より前の場合DATETIMEは、SQL Server の列で処理できるように、1753以降に変更する必要があります。

マーク


7
これは私が抱えていた問題を説明しています。1753/1/1より前の実際の日付を処理する必要がある状況はほとんどありませんが、エラーになる可能性があるデフォルト値0001/1/1を取得する多くの状況があります。
Hong

「datetime」データ型に「new DateTime()」を挿入しようとしたときに、この例外を受け取ったことを確認しました。
ジョージ・オノフレ2015年

1
データベースに書き込むC#コードで、DateTime.MinValueのデフォルト値を割り当てようとしました。これは私が得ていたエラーを説明しています。+1
Mkalafut 16

私が使用してEntity Frameworkのコードファーストをし、私はDateTimeのプロパティでモデルを使用します。DtInit = new System.DateTime(1492, 10, 12),失敗します。
Kiquenet

これは...本当の理由は、パッチの背後に隠されているような状況の一つである1
エウジェニオ・ミロ

41

私のSQL Server 2008データベースでは、DateTimenull可能ではないというフラグが付けられた列がありましたGetDate()が、デフォルト値として関数がありました。EF4を使用して新しいオブジェクトを挿入すると、オブジェクトのDateTimeプロパティを明示的に渡していないため、このエラーが発生しました。SQL関数が日付を処理することを期待していましたが、処理しませんでした。私の解決策は、データベースに依存してデータを生成する代わりに、コードから日付値を送信することでした。

obj.DateProperty = DateTime.now; // C#

2
お役に立ててうれしいです。テーブルからオブジェクトが作成されたときにEFデータコンテキストがフィールドにデフォルト値があることを発見できると思うので、それは面倒です。
グラハム

EFについては多くのことを考えています。POCOセルフトラッキングエンティティを使用していますが、これはそのようなクラスターです。私はコードの最初のモデルをチェックします。それもナンセンスでいっぱいである場合は、linqからsqlに戻り、オブジェクトマッパーを使用して小道具を自分のエンティティにマップすることを真剣に考えています...

2
2週間前のVS LiveでEF Code Firstのデモを見ましたが、見た目はすごいです。
グラハム

それは朗報です。私たちのオフィスではまもなく新しいプロジェクトを開始し、EF-CFとdapper(SOが使用/保守)に分割されています。WCFサービスを介して使用されるアプリでは、どちらが優れているかがわかります。

1
こんにちは、1年前のコメント!私自身はEF Code-Firstから始めて、POCOで日付時刻メンバーをとして定義する必要があるだけNullable<DateTime>で、コードではこれを(01/01/0000の代わりに)本当にnullのままにできることを発見しました。EF to SQLがINSERTでこのnullを無視し、サーバーからの日付を使用することを知っていたことに驚きました(GetDate()...)... WebサーバーとSQLサーバーのWebサーバー。
Funka

34

私にとっては、日時がそうだったからです。

01/01/0001 00:00:00

この場合、EF DateTimeオブジェクトにnullを割り当てます...例として私のFirstYearRegisteredコードを使用します

DateTime FirstYearRegistered = Convert.ToDateTime(Collection["FirstYearRegistered"]);
if (FirstYearRegistered != DateTime.MinValue)
{
    vehicleData.DateFirstReg = FirstYearRegistered;
}  

ExcelDataReaderを使用してこのデータを解析し、無効なテキストが入力されたときに01/01/0001を返しています(.GetDateTime(columnIndex)メソッドを使用して、期待どおりに例外がスローされません)。MinValueとの比較により、SQLで範囲外の例外を防ぐトリックが行われました。
Tommy

22

これは私を夢中にさせていました。null可能な日付時刻(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;
                    }
                }
            }
        }
    }
}

1
使用して[Column(TypeName = "datetime2")]
Kiquenet 2017

21

EFは、それが計算列またはトリガーを処理していることを知らない場合があります。設計上、これらの操作は、挿入後にEFの外の値を設定します。

修正は、プロパティのその列のComputedEFで指定するedmxことStoreGeneratedPatternです。

私にとっては、列に現在の日付と時刻を挿入するトリガーがあったときでした。以下の3番目のセクションを参照してください。


解決する手順

Visual StudioでModel Browserページを開き、Model次にEntity Types->次に

  1. エンティティと日時プロパティを選択します
  2. 選択する StoreGeneratedPattern
  3. に設定 Computed

EFモデルブラウザーモデルエンティティタイプダイアログ


この状況では、他の回答は回避策です。列の目的は、レコードが作成されたときに日時を指定することです。これは、正しい時刻を追加するトリガーを実行するSQLのジョブです。このSQLトリガーなど:

DEFAULT (GETDATE()) FOR [DateCreated]


GETDATE()文字通り当時使用していたことに注意してください。しかし、SYSDATETIME()私が真実であると信じている任意のDateTime2操作に使用すべきであるという最近のコメントがありました。
ΩmegaMan

10

私はこれに遭遇し、以下をdatetimeプロパティに追加しました:

 [Column(TypeName = "datetime2")]
 public DateTime? NullableDateTimePropUtc { get; set; }

1
using System.ComponentModel.DataAnnotations.Schema; 必須
Kiquenet 2017

9

日付時刻フィールドに日付時刻を渡さない場合、デフォルトの日付{1/1/0001 12:00:00 AM}が渡されます。

ただし、この日付はエンティティフレームの動作と互換性がないため、datetime2データ型からdatetimeデータ型への変換がスローさ れ、範囲外の値になります

ただ、default DateTime.now日付フィールドに、あなたは、任意の日付を渡していない場合。

movie.DateAdded = System.DateTime.Now

'DateTime.Now'をデフォルト値として渡すことは、正確とはほど遠く、誤解を招く可能性があります。
Bartosz

6

最も簡単な方法は、データベースを変更して、datetimeではなくdatetime2を使用することです。互換性は適切に機能し、エラーは発生しません。

あなたはまだたくさんのテストをしたいでしょう...

このエラーはおそらく、日付を0年か何かに設定しようとしているためです。


4

他の回答で説明されている次のエラーが発生し続ける理由を理解しようとしているこの投稿を見つけました。

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

null可能なDateTimeオブジェクトを使用します。
public DateTime?PurchaseDate {get; セットする; }

エンティティフレームワークを使用している場合は、edmxファイルのnullableプロパティをTrueに設定します。

edmxファイルのnullableプロパティを** True **に設定します


3

以下のようandyukはすでに尖ったアウトがある場合、これが発生する可能性がNULLの値が非NULL可能に割り当てられたDateTimeフィールド。DateTimeDateTimeに変更することを検討してくださいまたはNullable < DateTime >。依存関係プロパティを使用している場合は、依存関係プロパティの型もnull許容のDateTime型であることも確認してください。

以下は、DateTimeからDateTimeへの不完全な実際の例ですか?奇妙な行動を起こすタイプ調整

ここに画像の説明を入力してください


2

Entity Framework 4はdatetime2データ型で動作するため、dbではSQL Server 2008の対応するフィールドはdatetime2である必要があります。

ソリューションを実現するには、2つの方法があります。

  1. Entity Framwork 4で日時データ型を使用するには、edmx-fileのProviderManifestTokenを「2005」に切り替える必要があります。
  2. 対応するフィールドを[Nullを許可]に設定すると(それをNULLABLEに変換します)、EFは自動的に日付オブジェクトを日時として使用します。

1
私はデータベースモデル(POCOクラス)の2つ目のポイントを取り上げ、フィールドをnull許容型として設定する方法を知りました。誰かが疑問に思った場合は、日付タイプの後に疑問符(?)を追加することでこれを行うことができます。例:パブリックDateTime?StartTime {get; セットする; }これで問題は解決しました。他に必要なのは、コード行の周りにTimeSpanキャストを配置して、null値を許容する2つのDateTime値を互いに減算することだけでした。例:var timeTaken =(TimeSpan)(endTime-startTime);
Ciaran Gallagher

1

@ 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.)
 }

1

以下の属性をモデルクラスのプロパティに追加します。

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)]
Ajith Chandran


0

サーバーではなく、開発マシンで正常に動作する場合があります。私の場合、私は置く必要がありました:

<globalization uiCulture="es" culture="es-CO" />

web.configファイル内。

マシン(サーバー)のタイムゾーンは(COロケールに対して)正しくありましたが、Webアプリは正しくありませんでした。この設定は完了し、再び正常に機能しました。

もちろん、すべての日付に価値がありました。

:D


0

このコードをASP.NETのクラスに追加すると、うまくいきました。

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Properties<DateTime>().Configure(c => c.HasColumnType("datetime2"));
}

0

私はこの問題を認識しており、皆さんもそうであるはずです。

https://en.wikipedia.org/wiki/Year_2038_problem

SQLでは、この問題を回避するために新しいフィールドタイプが作成されました(datetime2)。

この「日付」フィールドタイプには、DateTime .Netクラスと同じ範囲値があります。それはあなたのすべての問題を解決するので、私はそれを解決する最良の方法はあなたのデータベースの列のタイプを変更することだと思います(それはあなたのテーブルデータに影響しません)。


0

次の2つを確認してください。1)このフィールドにはNULL値がありません。例えば:

 public DateTime MyDate { get; set; }

交換:

public DateTime MyDate { get; set; }=DateTime.Now;

2)データベースを再度新規作成します。例えば:

db=new MyDb();

値をデフォルトでDateTime.Nowにしたくない場合はどうなりますか?
サベージ

したくない場合:DateTime.Now。使用できます:new DateTime(...、...、...)
RainyTears

0

継承された日時属性の問題

このエラーメッセージは、null不可の日付フィールドの値が挿入/更新時にnullの場合によく表示されます。1つの原因は継承です。

日付が基本クラスから継承され、マッピングを行わない場合、EFはその値を読み取りません。

詳細:https : //weblogs.asp.net/manavi/inheritance-mapping-strategies-with-entity-framework-code-first-ctp5-part-3-table-per-concrete-type-tpc-and-選択戦略ガイドライン


0

ASP.Net MVCを使用してページを編集するときに、このエラーが発生しました。データベースの作成中は問題ありませんでしたが、データベースを更新すると、DateCreatedプロパティが範囲外になりました!

あなたはしたくない場合はDateTimeプロパティがNULL可能であることと、その値は、SQLの日時範囲内にあるかどうかを確認する必要はありません(と@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");

    }
}

0

単純なコンソールアプリプロジェクトでこの問題に遭遇しました。私の簡単な解決策は、次のメソッドを実行して、datetime2の日付をnull可能な日付時刻に変換することです。

static DateTime? ParseDateTime2(DateTime? date)
    {
        if (date == null || date.ToString() == "1/1/0001 12:00:00 AM")
        {
            return null;
        }
        else
        {
            return date;
        }
    }

これは確かに完全な包括的な方法ではありませんが、私のニーズにはうまくいき、おそらく他の人を助けるでしょう!


0

DBのreq形式を確認してください。たとえば、私のDBにはデフォルト値またはバインディングがあります(((1)/(1))/(1900))

System.DateTime MyDate = new System.DateTime( 1900 ,1, 1);

ここに画像の説明を入力してください


-1

1/1/1001のように、許容されるdattimeの最小値をlesathanに設定した日付列があります。

この問題を克服するには、urプロパティに適切な日時値を設定し、IsSpecified = trueなどの別の魔法のプロパティも設定できます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.