如何以“d.hh:mm:ss”格式在数据库中保存TimeSpan值
本文关键字:格式 数据库 TimeSpan 保存 ss mm hh | 更新日期: 2023-09-27 18:35:16
TimeSpan timeInDays= new TimeSpan(2,8,8,8);
我想使用 EF 在数据库中保存"时间在天"。表列的类型为"时间"。它给了我运行时异常,
"SqlDbType.Time overflow。 值"2.08:08:08"超出范围。 必须 介于 00:00:00.0000000 和 23:59:59.9999999 之间。
请帮我解决这个问题。
正如@Mainul所说,time
类型最多有 24 小时的范围。为了存储更长的时间段,我建议使用 bigint
(64 位整数),它可用于直接表示时间跨度值。有关更多详细信息,请参阅此 QA:存储值> 24:00:00 的 .Net 时间跨度的正确 SQL 类型是什么?
如果您无法更改表架构,则必须截断数据,一种方法是在保存到数据库之前通过向右移动(然后在加载时向左移动)来丢失不太重要的位,但这将很混乱:
默认情况下,SQL Server 中的time
类型是使用 5 个字节的 time(7)
(精度为 7 位十进制数字),请参阅此处:https://msdn.microsoft.com/en-us/library/bb677243.aspx - 因此我们需要将使用 8 个字节的时间跨度("ticks")的二进制表示形式向右移动 3 个字节(得到 5),即 24 位。如下图所示:
TimeSpan tick value (64-bits): 0x01 0x23 0x45 0x67 0x89 0xAB 0xCD 0xEF
SQL Server time field : 0x01 0x23 0x45 0x67 0x89
由于TimeSpan Tick将其最重要的位存储在左侧,这意味着我们将丢失的三个字节(0xAB 0xCD 0xEF
)代表我们可以承受的不值得担心的一小部分秒。当我们从数据库加载数据并将其保留 3 个字节时,它将如下所示(请注意丢失其值的三个 0x00 0x00 0x00
个字节):
TimeSpan tick value (64-bits): 0x01 0x23 0x45 0x67 0x89 0x00 0x00 0x00
储蓄:
TimeSpan tooBig = new TimeSpoan( 2, 8, 8, 8 );
Int64 tooBigBits = tooBig.Ticks;
Int64 truncated = tooBigBits >> 24;
TimeSpan temp = TimeSpan.FromTicks ( truncated );
yourDbEntity.timeValue = temp;
装载:
TimeSpan temp = yourDbEntity.timeValue;
Int64 truncated = temp.Ticks;
Int64 adjusted = truncated << 24;
TimeSpan actual = TimeSpan.FromTicks( adjusted );
yourDbEntity.timeValue = actual;
在 T-SQL 中的"时间类型"列 定义一天中的时间。时间没有 时区感知,基于 24 小时制。 https://msdn.microsoft.com/en-us/library/bb677243.aspx
TimeSpan()
方法返回时间,包括大于 24 小时值的日值。您可以做的是保存时间值而不保存日期值。
编辑:如果要从当前时间跨度中减去日值。
new TimeSpan(timeInDays.Hours, timeInDays.Minutes, timeInDays.Seconds)
您可以将时间存储为数据库中的DateTime
(02.01.0001 08:08:08),并且仍然可以将时间用于项目
public class Task
{
[NotMapped]
public TimeSpan Duration
{
get { return Duration2 - DateTime.MinValue; }
set { Duration2 = DateTime.MinValue + value; }
}
public DateTime Duration2 { get; set; }
}
这样做的缺点是无法根据Duration
进行数据库查询
var tasks = from t in tasks where t.Duration > TimeSpan.FromHours(50);
但你必须使用
var duration = DateTime.MinValue + TimeSpan.FromHours(50);
var tasks = from t in tasks where t.Duration2 > duration;
或者,您可以使用相同的概念在数据库中存储秒而不是日期值。