私はいくつかの定数を私のDBにシードしようとしています:
context.Stages.AddOrUpdate(s => s.Name,
new Stage()
{
Name = "Seven",
Span = new TimeSpan(2, 0, 0),
StageId = 7
});
context.Stages.AddOrUpdate(s => s.Name,
new Stage()
{
Name = "Eight",
Span = new TimeSpan(1, 0, 0, 0),
StageId = 8
});
これは、EF Codefirst MigrationsのSeed()関数内にあります。次のようにステージ8で失敗します。
System.Data.UpdateException:エントリの更新中にエラーが発生しました。詳細については、内部の例外を参照してください。 ---> System.OverflowException:SqlDbType.Timeオーバーフロー。値「1.00:00:00」は範囲外です。 00:00:00.0000000から23:59:59.9999999の間でなければなりません。
EFを使用してタイムスパンを保存できないのはなぜですか?ここで両端で愚かな時間からティックへの変換を行う必要がないことを本当に願っています...
この行では:
Span = new TimeSpan(1, 0, 0, 0)
次のコンストラクタを使用しています:
public TimeSpan(int days, int hours, int minutes, int seconds);
つまり、TimeSpan
パラメータに1
を渡してから24時間を超えるdays
を実際に作成していますが、基になるデータベースタイプはTime
です。 00:00-23:59の値のみを受け入れます。
実際にTimeSpan
を1日で使用するつもりだったのか、それとも単なるタイプミスであるのかを判断するのは困難です。
本当に24時間を超えるTimeSpan
が必要な場合は、フィールドを別のデータベースタイプ(SmallDateTime
など)にマップする必要があると思います。
タイプミスだけの場合は、行を次のように変更します。
Span = new TimeSpan(1, 0, 0),
[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete("Property '" + nameof(Duration) + "' should be used instead.")]
public long DurationTicks { get; set; }
[NotMapped]
public TimeSpan Duration
{
#pragma warning disable 618
get { return new TimeSpan(DurationTicks); }
set { DurationTicks = value.Ticks; }
#pragma warning restore 618
}
これは、EF Core 2.1以降、 値の変換 を使用して実現可能です。
builder.Entity<Stage>()
.Property(s => s.Span)
.HasConversion(new TimeSpanToTicksConverter()); // or TimeSpanToStringConverter
前述のように、問題はEFがTimeSpanクラスを24時間に制限されているTimeにマップするという事実です。
24時間を超えるタイムスパンを保存する必要がある場合は、次の2つの方法のいずれかをお勧めします。
1)次のように、タイムスパンのさまざまな要素のintプロパティを使用してTimeSpanエンティティを作成します。
public class Timespan
{
public Int64 Id { get; set; }
public Int16 Years { get; set; }
public int Months { get; set; }
public Int64 Days { get; set; }
public Int64 Hours { get; set; }
public Int64 Minutes { get; set; }
}
該当するエンティティの外部参照をカスタムTimespanエンティティに追加するだけです。
2)この ブログ投稿 で説明されているように、愚かな時間からティックへの変換を行います。