私が書いたこのコードを使用してきましたが、この最も不明瞭な方法で動作しています。 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への最初の挿入では機能したが、それ以降は失敗したことです。何が起こっているのでしょうか?
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");
DB関連のエラーが多数発生した後、SQLの最小/最大日付に対して以下を使用すると非常にうまく機能します。
DateTime rngMin = (DateTime)System.Data.SqlTypes.SqlDateTime.MinValue;
DateTime rngMax = (DateTime)System.Data.SqlTypes.SqlDateTime.MaxValue;
2列のコードは問題ないようです。そのマッピングクラスで他の日時列を探します。また、データコンテキストのログを有効にして、クエリとパラメーターを表示します。
dc.Log = Console.Out;
DateTimeはc#の0-0001-01-01に初期化されます。これは、linqtosqlによってSQL文字列リテラル「0001-01-01」を介してデータベースに送信されます。 SQLは、この日付からT-Sql日時を解析できません。
これに対処するには、いくつかの方法があります。
.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。
このエラーは、タイプDateTimeの変数をnullに設定しようとすると発生します。変数をNULL可能、つまりDateTime?として宣言します。これで問題が解決します。
少ないコードを記述するために、SQLサーバーがフィールドのデフォルト値をGETDATE()
またはNEWID()
に設定して、挿入時に日付、時刻、IDなどのフィールドを設定することがあります。
そのような場合、自動生成値エンティティクラスのこれらのフィールドのプロパティをtrueに設定する必要があります。
この方法では、コードに値を設定する必要がなく(エネルギー消費を防止!!!)、その例外を確認する必要がありません。
拡張メソッドを使用
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();
これは通常、希望する値ではなくnullがクエリにポストされることを意味します。SQLプロファイラを実行して、linqからSQL Serverに何が渡されるかを正確に確認することができます。
NHibernateを使用している場合、null許容の適切なDateTimeプロパティがマッピングでnull可能に設定されていることを確認してください。
通常、この種のエラーは、DateTime変換または解析を行うときに発生します。アプリケーションがホストされているサーバーのカレンダー設定(主にタイムゾーンと短い日付形式)を確認し、場所に適したタイムゾーンに設定されていることを確認します。これで問題が解決することを願っています。
私は同じことを見ています。エラーは、行の挿入ではなく更新時に発生します。私が参照しているテーブルには2つのDateTime列があり、どちらもNULLにはできません。
行を取得してすぐに保存する(データの変更なし)シナリオを作成しました。 getは正常に機能しますが、更新は失敗します。
NHibernate 3.3.1.4000を使用しています