web-dev-qa-db-ja.com

エラー-SqlDateTimeオーバーフロー。 1/1/1753 12:00:00 AMから12/31/9999 11:59:59 PMの間でなければなりません

私が書いたこのコードを使用してきましたが、この最も不明瞭な方法で動作しています。 DateTimeの2つの列を含む行をデータベースに挿入したい:

myrow.ApprovalDate = DateTime.Now
myrow.ProposedDate = DateTime.Now

それでも、データベースを更新すると、次のエラーが表示されます。

SqlDateTimeオーバーフロー。 1/1/1753 12:00:00 AMから12/31/9999 11:59:59 PMの間でなければなりません。

挿入された値をデータベースからコピーして、更新されるオブジェクトにハードコードすることさえ試みました:

// I copied this value from the DB
myrow.ApprovalDate =  Convert.ToDateTime("2008-12-24 00:00:00.000");

やはり同じエラーですが、奇妙な部分は、上記のトリックがDBへの最初の挿入では機能したが、それ以降は失敗したことです。何が起こっているのでしょうか?

69
vondiplo

C#のDateTimeは値型であり、参照型ではないため、nullにすることはできません。ただし、SQLサーバーDATETIMEデータ型の範囲外の定数DateTime.MinValueを使用できます。

値の型は、常に明示的に設定する必要なく(この場合はDateTime.MinValue)、常に(デフォルトの)値(ゼロ)を持つことが保証されています。

結論としては、おそらくデータベースに渡そうとしている未設定のDateTime値があります。

DateTime.MinValue = 1/1/0001 12:00:00 AM
DateTime.MaxValue = 23:59:59.9999999, December 31, 9999, 
                    exactly one 100-nanosecond tick 
                    before 00:00:00, January 1, 10000

MSDN: DateTime.MinValue


SQL Serverについて

日付時刻
1753年1月1日から9999年12月31日までの日付と時刻のデータ。精度は100分の1秒(3.33ミリ秒または0.00333秒に相当)です。値は、.000、.003、または.007秒の増分に丸められます

小さい
1900年1月1日から2079年6月6日までの日付と時刻のデータ、分単位の精度。 29.998秒以下のsmalldatetime値は、最も近い分に切り捨てられます。 29.999秒以上の値は、最も近い分に切り上げられます。

MSDN: Sql Server DateTimeおよびSmallDateTime


最後に、C#DateTimeを文字列としてsqlに渡すことに気付いた場合は、最大精度を維持し、sqlサーバーが同様のエラーをスローしないように、次のようにフォーマットする必要があります。

string sqlTimeAsString = myDateTime.ToString("yyyy-MM-ddTHH:mm:ss.fff");

更新(8年後)

日付範囲DateTime2および時間範囲0001-01-01 through 9999-12-31の.net DateTimeとより整合するsql 00:00:00 through 23:59:59.9999999データ型の使用を検討してください

string dateTime2String = myDateTime.ToString("yyyy-MM-ddTHH:mm:ss.fffffff");

MSDN datetime2(Transact-SQL)

74
Robert Paulson

DB関連のエラーが多数発生した後、SQLの最小/最大日付に対して以下を使用すると非常にうまく機能します。

DateTime rngMin = (DateTime)System.Data.SqlTypes.SqlDateTime.MinValue;

DateTime rngMax = (DateTime)System.Data.SqlTypes.SqlDateTime.MaxValue;
70
Chrismean

2列のコードは問題ないようです。そのマッピングクラスで他の日時列を探します。また、データコンテキストのログを有効にして、クエリとパラメーターを表示します。

dc.Log = Console.Out;

DateTimeはc#の0-0001-01-01に初期化されます。これは、linqtosqlによってSQL文字列リテラル「0001-01-01」を介してデータベースに送信されます。 SQLは、この日付からT-Sql日時を解析できません。

これに対処するには、いくつかの方法があります。

  • SQLが処理できる値(Sqlの0:1900-01-01など)ですべての日付時刻を必ず初期化してください
  • 時折省略される可能性のある日付時刻がnullable datetimesであることを確認してください
9
Amy B

.Net DateTimeをSqlDateTime.MinValueまたはMaxValueと比較するときは注意してください。たとえば、次の場合は例外がスローされます。

DateTime dte = new DateTime(1000, 1, 1);
if (dte >= SqlDateTime.MinValue)
    //do something

理由は、MinValueがDateTimeではなくSqlDateTimeを返すためです。したがって、.Netは比較のためにdteをSqlDateTimeに変換しようとしますが、許容されるSqlDateTimeの範囲外にあるため、例外をスローします。

これに対する1つの解決策は、DateTimeとSqlDateTime.MinValueを比較することです。Value

9
Phil Haselden

このエラーは、タイプDateTimeの変数をnullに設定しようとすると発生します。変数をNULL可能、つまりDateTime?として宣言します。これで問題が解決します。

6
Altaf Patel

少ないコードを記述するために、SQLサーバーがフィールドのデフォルト値をGETDATE()またはNEWID()に設定して、挿入時に日付、時刻、IDなどのフィールドを設定することがあります。

そのような場合、自動生成値エンティティクラスのこれらのフィールドのプロパティをtrueに設定する必要があります。

この方法では、コードに値を設定する必要がなく(エネルギー消費を防止!!!)、その例外を確認する必要がありません。

3
Haghpanah

拡張メソッドを使用

 public static object ToSafeDbDateDBnull(this object objectstring)
    {
        try
        {
            if ((DateTime)objectstring >= SqlDateTime.MinValue)
            {
                return objectstring;
            }
            else
            {
                return DBNull.Value;
            }
        }
        catch (Exception)
        {

            return DBNull.Value;
        }

    }

DateTime objdte = new DateTime(1000, 1, 1);
dte.ToSafeDbDateDBnull();
1
MSTdev

これは通常、希望する値ではなくnullがクエリにポストされることを意味します。SQLプロファイラを実行して、linqからSQL Serverに何が渡されるかを正確に確認することができます。

1
Turnkey

NHibernateを使用している場合、null許容の適切なDateTimeプロパティがマッピングでnull可能に設定されていることを確認してください。

0
arash

通常、この種のエラーは、DateTime変換または解析を行うときに発生します。アプリケーションがホストされているサーバーのカレンダー設定(主にタイムゾーンと短い日付形式)を確認し、場所に適したタイムゾーンに設定されていることを確認します。これで問題が解決することを願っています。

0

私は同じことを見ています。エラーは、行の挿入ではなく更新時に発生します。私が参照しているテーブルには2つのDateTime列があり、どちらもNULLにはできません。

行を取得してすぐに保存する(データの変更なし)シナリオを作成しました。 getは正常に機能しますが、更新は失敗します。

NHibernate 3.3.1.4000を使用しています

0
Tevya