Хранение 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? Я действительно надеюсь, что мне не нужно делать какое-то глупое преобразование времени на тики на обоих концах здесь...
Ответы
Ответ 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 >