如何以“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 之间。

请帮我解决这个问题。

如何以“d.hh:mm:ss”格式在数据库中保存TimeSpan值

正如@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;

或者,您可以使用相同的概念在数据库中存储秒而不是日期值。