私は5つの列を持つデータテーブルを持っています、そこで行はデータでいっぱいにされていてそれからトランザクションを通してデータベースに保存されています。
保存中にエラーが返されます。
Datetime2データ型をdatetimeデータ型に変換した結果、値が範囲外になりました
読んだように、私のdatatableはDateTime2
の型を持ち、私のデータベースはDateTime
を持ちます。それは間違いです。
Dateカラムは次のようにDateTime
に設定されています。
new DataColumn("myDate", Type.GetType("System.DateTime"))
質問
これはコードで解決できますか、それともデータベースレベルで何か変更する必要がありますか?
コラムにはどのような日程がありますか。
それらのすべてがタイプの範囲内に収まりますか?
余談ですが、Type
コンストラクタのDataColumn
オブジェクトを取得する正しい方法は、typeof
キーワードです。これは桁違いに高速です。
したがって、列を作成するには、次のように書く必要があります。
new DataColumn("myDate", typeof(DateTime))
これは、フィールドが受け入れないときにDateTimeフィールドに値を割り当てないと発生する可能性があります。 NULLの値。
それは私のためにそれを修正しました!
DATETIME
とDATETIME2
はどちらも.NETのSystem.DateTime
にマップします。実際には同じ.NET型なので、「変換」はできません。
MSDNのドキュメントページを参照してください。 http://msdn.Microsoft.com/ja-jp/library/bb675168.aspx
これら2つの "SqlDbType
"には2つの異なる値があります。DataColumn
の定義でそれらを指定できますか?
しかし、SQL Serverでは、サポートされている日付範囲はまったく異なります。
DATETIME
は1753/1/1から "eternity"(9999/12/31)までをサポートしていますが、DATETIME2
は0001/1/1からeternityまでをサポートしています。
そのため、本当に必要なのは日付の年をチェックすることです - 1753年より前の場合は、SQL ServerのDATETIME
列で処理するために、1753年以降に変更する必要があります。
マーク
私のSQL Server 2008データベースでは、null値ではないとしてフラグ付けされたDateTime
カラムを持っていましたが、デフォルト値としてGetDate()
関数がありました。 EF4を使用して新しいオブジェクトを挿入するときに、オブジェクトのDateTimeプロパティを明示的に渡していないため、このエラーが発生しました。 SQL関数が日付を処理すると思っていましたが、処理しませんでした。私の解決策はそれを生成するためにデータベースに頼るのではなくコードから日付の値を送ることでした。
obj.DateProperty = DateTime.now; // C#
私にとっては、日時が..だったからでした。
01/01/0001 00:00:00
この場合、あなたはあなたにnullを代入したいですEF DateTime Object ...例として私のFirstYearRegisteredコードを使って
DateTime FirstYearRegistered = Convert.ToDateTime(Collection["FirstYearRegistered"]);
if (FirstYearRegistered != DateTime.MinValue)
{
vehicleData.DateFirstReg = FirstYearRegistered;
}
EFは、それが計算列またはトリガーを処理していることを知らないことがあります。設計上、これらの操作は挿入後にEFの範囲外の値を設定します。
この問題を解決するには、Computed
プロパティのその列に対してEFのedmx
にStoreGeneratedPattern
を指定します。
私にとっては、列に現在の日付と時刻を挿入するトリガーがあるときでした。下記の3番目のセクションを参照してください。
解決するためのステップ
Visual StudioでModel Browser
ページを開き、次にModel
を開き、次にEntity Types
- > thenを開きます。
StoreGeneratedPattern
を選択してくださいComputed
に設定このような状況で他の答えは回避策です、列の目的はレコードが作成されたときに指定された時間/日付を持つことであり、それは正しい時間を追加するためにトリガーを実行するSQLの仕事です。このSQLトリガのように:
DEFAULT (GETDATE()) FOR [DateCreated]
。
これは私を夢中にさせていました。 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;
}
}
}
}
}
}
私はこれに遭遇し、私のdatetimeプロパティに以下を追加しました:
[Column(TypeName = "datetime2")]
public DateTime? NullableDateTimePropUtc { get; set; }
日付時刻フィールドに日付時刻を渡さないと、デフォルトの日付{1/1/0001 12:00:00 AM}が渡されます。
しかし、この日付はエンティティフレームワークと互換性がないため、datetime2データ型からdatetimeデータ型への変換がスローされ、範囲外の値になります
日付を渡さない場合は、日付フィールドにdefault DateTime.now
を入力してください。
movie.DateAdded = System.DateTime.Now
最も簡単な方法は、datetimeの代わりにdatetime2を使用するようにデータベースを変更することです。互換性はうまく機能し、そしてあなたはあなたのエラーを得ることはありません。
あなたはまだテストの束をしたいと思うでしょう...
エラーはおそらくあなたが0年か何かに日付を設定しようとしていることが原因です - しかしそれはすべてあなたがものを変更するための制御権を持っている場所に依存します。
Entity Framework 4はdatetime2データ型を処理するため、dbではSQL Server 2008の対応するフィールドはdatetime2である必要があります。
解決策を実現するには2つの方法があります。
@ 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.)
}
時にはそれは開発マシンではなくサーバーではうまく動作します。私の場合は、次のように書きました。
<globalization uiCulture="es" culture="es-CO" />
Web.configファイル内。
マシン(サーバー)のタイムゾーンは(COロケールに対して)正しいのですが、Webアプリは正しくありませんでした。この設定は完了し、それは再びうまくいきました。
もちろん、すべての日付に価値がありました。
:D
私はこの問題を認識しており、皆さんもそうすべきです:
https://en.wikipedia.org/wiki/Year_2038_problem
SQLでは、この問題を回避するために新しいフィールドタイプが作成されました(datetime2)。
この「日付」フィールドタイプには、DateTime .Netクラスと同じ範囲値があります。それはすべての問題を解決するので、それを解決する最良の方法は、データベースの列タイプを変更することだと思います(テーブルデータには影響しません)。
私の場合は、DateをDatetimeにキャストしていましたが、このエラーが発生しました。 Datetimeは1753に固定されていますが、Dateには "プログラマより指向"の最小01/01/0001があります
私たちの側でデータ収集エラーとそれを組み合わせると、あなたはあなたの例外を得ます!
次の2つを確認してください。1)このフィールドにはNULL値がありません。例えば:
public DateTime MyDate { get; set; }
置換先:
public DateTime MyDate { get; set; }=DateTime.Now;
2)データベースを再度新規作成します。例えば:
db=new MyDb();
このコードをASP.NETのクラスに追加することは私にとっては大変でした。
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Properties<DateTime>().Configure(c => c.HasColumnType("datetime2"));
}