Хранение TimeSpan с помощью Entity Framework Codefirst - переполнение SqlDbType.Time - программирование
Подтвердить что ты не робот

Хранение TimeSpan с помощью Entity Framework Codefirst - переполнение SqlDbType.Time

Я пытаюсь засеять некоторые константы в моей БД:

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

Это в моей функции Seed() для EF Codefirst Migrations. Он не работает на этапе 8 со следующим:

System.Data.UpdateException: произошла ошибка при обновлении записей. Подробнее см. Внутреннее исключение. --- > System.OverflowException: переполнение SqlDbType.Time. Значение '1.00: 00: 00' вне пределов досягаемости. Должно быть между 00: 00: 00.0000000 и 23: 59:. 59,9999999

Почему я не могу хранить временные интервалы с помощью EF? Я действительно надеюсь, что мне не нужно делать какое-то глупое преобразование времени на тики на обоих концах здесь...

4b9b3361

Ответ 1

В этой строке:

Span = new TimeSpan(1, 0, 0, 0)

Вы используете этот конструктор:

public TimeSpan(int days, int hours, int minutes, int seconds);

Итак, вы фактически создаете TimeSpan больше, чем 24 часа, так как вы передаете 1 в параметр days, тогда как ваш базовый тип базы данных Time, который принимает только значения между 00: 00- 23:59.

Трудно сказать, действительно ли вы имели TimeSpan с 1 днем, или это просто опечатка.

Если вы действительно хотите TimeSpan больше 24 часов, я думаю, вам придется сопоставить свое поле с другим типом базы данных (например, SmallDateTime).

Если это просто ошибка опечатки, просто измените свою строку на:

Span = new TimeSpan(1, 0, 0),

Ответ 2

    [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<TimeSpanToTicksConverter>();

Ответ 3

Проблема, как упоминалось ранее, заключается в том, что EF отображает класс TimeSpan на Time, который ограничен 24 часами.

Если вам нужно сохранить промежуток времени более 24 часов, я бы предложил один из следующих двух способов:

1) Создайте объект TimeSpan с свойствами int для разных элементов времени, например:

 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) Сделайте некоторое глупое преобразование времени в тики, как описано в этом сообщении . p >