Storing TimeSpan with Entity Framework Codefirst - SqlDbType.Time overflow

后端 未结 4 787
攒了一身酷
攒了一身酷 2021-02-05 02:41

I\'m trying to seed some constants into my DB:

context.Stages.AddOrUpdate(s => s.Name,
                                   new Stage()
                                


        
相关标签:
4条回答
  • 2021-02-05 03:06

    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://docs.microsoft.com/en-us/ef/core/modeling/value-conversions

    0 讨论(0)
  • 2021-02-05 03:13

    The problem, as previously mentioned, is the fact that EF maps the TimeSpan class to Time, which is limited to 24 hours.

    If you need to store a timespan of greater than 24 hours, I would suggest one of the following two approaches:

    1) Create a TimeSpan entity with int properties for the different elements of a timespan, something like:

     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; }
    }
    

    Simply add a foreign reference in the applicable entity to your custom Timespan entity.

    2) Do some silly time-to-ticks conversion, as explained in this blog post.

    0 讨论(0)
  • 2021-02-05 03:17
        [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
        }
    

    Update

    This is now achievable since EF Core 2.1, using Value Conversion.

    builder.Entity<Stage>()
        .Property(s => s.Span)
        .HasConversion(new TimeSpanToTicksConverter()); // or TimeSpanToStringConverter
    
    0 讨论(0)
  • 2021-02-05 03:24

    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),
    
    0 讨论(0)
提交回复
热议问题