I'm trying to seed some constants into my 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
});
This is within my Seed() function for EF Codefirst Migrations. It fails at Stage Eight with the following:
System.Data.UpdateException: An error occurred while updating the entries. See the inner exception for details. ---> System.OverflowException: SqlDbType.Time overflow. Value '1.00:00:00' is out of range. Must be between 00:00:00.0000000 and 23:59:59.9999999.
Why would I not be able to store a timespan using EF? I really hope I don't need to do some silly time-to-ticks conversion on both ends here...
[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
}
This is now achievable since EF Core 2.1, using Value Conversion.
builder.Entity<Stage>()
.Property(s => s.Span)
.HasConversion(new TimeSpanToTicksConverter()); // or TimeSpanToStringConverter
Doing a time-to-ticks conversion on both ends is no longer silly. Not sure when they added it, but Entity Framework will now select the appropriate built in converter if one exists (in this case TimeSpanToTicksConverter). All you need to do is add a single attribute to your entity class and Entity Framework will automagically give the column in the SQL table the same range as the TimeSpan class.
public class Stage
{
public string Name { get; set; }
[Column(TypeName = "bigint")]
public TimeSpan Span { get; set; }
public int StageId { get; set; }
}
I'm sure bigint isn't the default column type for TimeSpan for human readability and backwards compatibility, but this seems like a pretty much perfect solution.
I hope this helps anybody experiencing this issue six years later.
Documentation: https://learn.microsoft.com/en-us/ef/core/modeling/value-conversions
In this line:
Span = new TimeSpan(1, 0, 0, 0)
You're using this constructor:
public TimeSpan(int days, int hours, int minutes, int seconds);
So you're actually creating a TimeSpan
greater than 24 hours since you're passing 1
to the days
parameter, while your underlying Database type is Time
which only accepts values between 00:00-23:59.
Hard to tell whether you actually meant to have a TimeSpan
with 1 day, or it's just a typo.
If you really want a TimeSpan
greater than 24 hours, i guess you'll have to map your field to another Database type (like SmallDateTime
).
If it's just a typo error, just change your line to:
Span = new TimeSpan(1, 0, 0),
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With