我试图在SQL server 2008 R2中存储. net TimeSpan。

EF Code First似乎建议它应该存储为SQL中的时间(7)。

然而。net中的TimeSpan可以处理超过24小时的时间。

在SQL server中存储。net TimeSpan的最佳方法是什么?


当前回答

现在,使用EF Core,您可以在AppDbContext中透明地转换数据类型

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
      // i.e. Store TimeSpan as string (custom)
      modelBuilder
        .Entity<YourClass>()
        .Property(x => x.YourTimeSpan)
        .HasConversion(
            timeSpan => timeSpan.ToString(), // To DB
            timeSpanString => TimeSpan.Parse(timeSpanString) // From DB
        );

    // i.e. Store TimeSpan as string (using TimeSpanToStringConverter)
    modelBuilder
        .Entity<YourClass>()
        .Property(x => x.YourTimeSpan)
        .HasConversion(new TimeSpanToStringConverter());

      // i.e. Store TimeSpan as number of ticks (custom)
      modelBuilder
        .Entity<YourClass>()
        .Property(x => x.YourTimeSpan)
        .HasConversion(
            timeSpan => timeSpan.Ticks, // To DB
            timeSpanString => TimeSpan.FromTicks(timeSpanString) // From DB
        );

    // i.e. Store TimeSpan as number of ticks (using TimeSpanToTicksConverter)
    modelBuilder
        .Entity<YourClass>()
        .Property(x => x.YourTimeSpan)
        .HasConversion(new TimeSpanToTicksConverter());
}

其他回答

我知道这是一个老问题,但我想确保注意到一些其他选项。

由于您不能在time sql datatype字段中存储大于24小时的TimeSpan;其他一些选择可能是。

Use a varchar(xx) to store the ToString of the TimeSpan. The benefit of this is the precision doesn't have to be baked into the datatype or the calculation, (seconds vs milliseconds vs days vs fortnights) All you need to to is use TimeSpan.Parse/TryParse. This is what I would do. Use a second date, datetime or datetimeoffset, that stores the result of first date + timespan. Reading from the db is a matter of TimeSpan x = SecondDate - FirstDate. Using this option will protect you for other non .NET data access libraries access the same data but not understanding TimeSpans; in case you have such an environment.

如果你不需要存储超过24小时,你可以只存储时间,因为SQL Server 2008和以后的映射是

time (SQL Server) <-> TimeSpan(.NET)

不需要转换,如果你只需要存储24小时或更少。

来源:http://msdn.microsoft.com/en-us/library/cc716729 (v = vs.110) . aspx

但是,如果您希望存储超过24小时的时间,则需要以tick为单位存储它,检索数据,然后转换为TimeSpan。例如

int timeData = yourContext.yourTable.FirstOrDefault();
TimeSpan ts = TimeSpan.FromMilliseconds(timeData);

为了与最可能生成时间跨度(计算2倍或date-times的差异)的来源保持一致,您可能希望将. net TimeSpan存储为SQL Server DateTime类型。

这是因为在SQL Server中,2个DateTime的差值(转换为Float's,然后转换回DateTime)只是相对于1900年1月1日的DateTime。例:+0.1秒就是1900年1月1日00:00:00.100,-0.1秒就是1899年12月31日23:59:59.900。

要将. net TimeSpan转换为SQL Server DateTime类型,首先要将其添加到1900年1月1日的DateTime中,从而将其转换为. net DateTime类型。当然,当你把它从SQL Server读入。net时,你会先把它读入。net DateTime,然后减去1900年1月1日,将它转换成。net TimeSpan。

For use cases where the time spans are being generated from SQL Server DateTime's and within SQL Server (i.e. via T-SQL) and SQL Server is prior to 2016, depending on your range and precision needs, it may not be practical to store them as milliseconds (not to mention Ticks) because the Int Type returned by DateDiff (vs. the BigInt from SS 2016+'s DateDiff_Big) overflows after ~24 days worth of milliseconds and ~67 yrs. of seconds. Whereas, this solution will handle time spans with precision down to 0.1 seconds and from -147 to +8,099 yrs..

警告:

This would only work if the difference relative to Jan. 1, 1900 would result in a value within the range of a SQL Server DateTime Type (Jan. 1, 1753 to Dec. 31, 9999 aka -147 to +8,099 yrs.). We don't have to worry near as much on the .NET TimeSpan side, since it can hold ~29 k to +29 k yrs. I didn't mention the SQL Server DateTime2 Type (whose range, on the negative side, is much greater than SQL Server DateTime's), because: a) it cannot be converted to a numeric via a simple Cast and b) DateTime's range should suffice for the vast majority of use cases. SQL Server DateTime differences computed via the Cast - to - Float - and - back method does not appear to be accurate beyond 0.1 seconds.

谢谢你的建议。因为在SQL server中没有对等的。我简单地创建了第二个字段,将TimeSpan转换为tick并将其存储在DB中。然后,我阻止存储TimeSpan

public Int64 ValidityPeriodTicks { get; set; }

[NotMapped]
public TimeSpan ValidityPeriod
{
    get { return TimeSpan.FromTicks(ValidityPeriodTicks); }
    set { ValidityPeriodTicks = value.Ticks; }
}

我将它作为BIGINT存储在数据库中,我将存储tick的数量(例如。时间间隔。蜱虫属性)。

这样,如果我想在检索时获得一个TimeSpan对象,我只需执行TimeSpan. fromticks (value),这很简单。