Gra*_*ler 185 .net sql-server timespan
我试图TimeSpan在SQL Server 2008 R2中存储.Net .
EF Code First似乎建议它应该存储为Time(7)SQL中的一个.
但是TimeSpan.Net可以处理比24小时更长的时间.
TimeSpan在SQL服务器中处理存储.Net的最佳方法是什么?
Tom*_*ler 211
我将它作为a存储在数据库中,BIGINT并存储刻度数(例如TimeSpan.Ticks属性).
这样,如果我想在检索时获取TimeSpan对象,我可以做一些简单的TimeSpan.FromTicks(value).
Gra*_*ler 62
感谢您的建议.因为SQL服务器中没有等效的.我只是创建了一个第二个字段,它将TimeSpan转换为刻度并将其存储在数据库中.然后我阻止了存储TimeSpan
public Int64 ValidityPeriodTicks { get; set; }
[NotMapped]
public TimeSpan ValidityPeriod
{
get { return TimeSpan.FromTicks(ValidityPeriodTicks); }
set { ValidityPeriodTicks = value.Ticks; }
}
Run Code Online (Sandbox Code Playgroud)
Ale*_*Río 31
如果您不必存储超过24小时,则可以只存储时间,因为SQL Server 2008及更高版本的映射是
time (SQL Server) <-> TimeSpan(.NET)
如果您只需要24小时或更短时间存储,则无需转换.
来源:http://msdn.microsoft.com/en-us/library/cc716729(v = vs1010).aspx
但是,如果要存储超过24小时,则需要将其存储在刻度线中,检索数据然后转换为TimeSpan.例如
int timeData = yourContext.yourTable.FirstOrDefault();
TimeSpan ts = TimeSpan.FromMilliseconds(timeData);
Run Code Online (Sandbox Code Playgroud)
There are multiple ways how to present a timespan in the database.
time
This datatype is supported since SQL Server 2008 and is the prefered way to store a TimeSpan. There is no mapping needed. It also works well with SQL code.
public TimeSpan ValidityPeriod { get; set; }
Run Code Online (Sandbox Code Playgroud)
However, as stated in the original question, this datatype is limited to 24 hours.
datetimeoffset
The datetimeoffset datatype maps directly to System.DateTimeOffset. It's used to express the offset between a datetime/datetime2 to UTC, but you can also use it for TimeSpan.
However, since the datatype suggests a very specific semantic, so you should also consider other options.
datetime / datetime2
One approach might be to use the datetime or datetime2 types. This is best in scenarios where you need to process the values in the database directly, ie. for views, stored procedures, or reports. The drawback is that you need to substract the value DateTime(1900,01,01,00,00,00) from the date to get back the timespan in your business logic.
public DateTime ValidityPeriod { get; set; }
[NotMapped]
public TimeSpan ValidityPeriodTimeSpan
{
get { return ValidityPeriod - DateTime(1900,01,01,00,00,00); }
set { ValidityPeriod = DateTime(1900,01,01,00,00,00) + value; }
}
Run Code Online (Sandbox Code Playgroud)
bigint
Another approach might be to convert the TimeSpan into ticks and use the bigint datatype. However, this approach has the drawback that it's cumbersome to use in SQL queries.
public long ValidityPeriod { get; set; }
[NotMapped]
public TimeSpan ValidityPeriodTimeSpan
{
get { return TimeSpan.FromTicks(ValidityPeriod); }
set { ValidityPeriod = value.Ticks; }
}
Run Code Online (Sandbox Code Playgroud)
varchar(N)
This is best for cases where the value should be readable by humans. You might also use this format in SQL queries by utilizing the CONVERT(datetime, ValidityPeriod) function. Dependent on the required precision, you will need between 8 and 25 characters.
public string ValidityPeriod { get; set; }
[NotMapped]
public TimeSpan ValidityPeriodTimeSpan
{
get { return TimeSpan.Parse(ValidityPeriod); }
set { ValidityPeriod = value.ToString("HH:mm:ss"); }
}
Run Code Online (Sandbox Code Playgroud)
Bonus: Period and Duration
Using a string, you can also store NodaTime datatypes, especially Duration and Period. The first is basically the same as a TimeSpan, while the later respects that some days and months are longer or shorter than others (ie. January has 31 days and February has 28 or 29; some days are longer or shorter because of daylight saving time). In such cases, using a TimeSpan is the wrong choice.
You can use this code to convert Periods:
using NodaTime;
using NodaTime.Serialization.JsonNet;
internal static class PeriodExtensions
{
public static Period ToPeriod(this string input)
{
var js = JsonSerializer.Create(new JsonSerializerSettings());
js.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb);
var quoted = string.Concat(@"""", input, @"""");
return js.Deserialize<Period>(new JsonTextReader(new StringReader(quoted)));
}
}
Run Code Online (Sandbox Code Playgroud)
And then use it like
public string ValidityPeriod { get; set; }
[NotMapped]
public Period ValidityPeriodPeriod
{
get => ValidityPeriod.ToPeriod();
set => ValidityPeriod = value.ToString();
}
Run Code Online (Sandbox Code Playgroud)
I really like NodaTime and it often saves me from tricky bugs and lots of headache. The drawback here is that you really can't use it in SQL queries and need to do calculations in-memory.
CLR User-Defined Type
You also have the option to use a custom datatype and support a custom TimeSpan class directly. See CLR User-Defined Types for details.
The drawback here is that the datatype might not behave well with SQL Reports. Also, some versions of SQL Server (Azure, Linux, Data Warehouse) are not supported.
Value Conversions
Starting with EntityFramework Core 2.1, you have the option to use Value Conversions.
However, when using this, EF will not be able to convert many queries into SQL, causing queries to run in-memory; potentially transfering lots and lots of data to your application.
So at least for now, it might be better not to use it, and just map the query result with Automapper.
我知道这是一个老问题,但我想确保注意到其他几个选项.
由于您无法在sql数据类型字段中存储超过24小时的TimeSpan; 可能还有其他两种选择.
使用varchar(xx)存储TimeSpan的ToString.这样做的好处是不必将精度烘焙到数据类型或计算中(秒与毫秒相比,天与星期四)所有你需要的是使用TimeSpan.Parse/TryParse.这就是我要做的.
使用第二个日期,日期时间或日期时间偏移,存储第一个日期+时间跨度的结果.从db读取是TimeSpan x = SecondDate - FirstDate的问题.使用此选项将保护您,以便其他非.NET数据访问库访问相同的数据,但不了解TimeSpans; 如果你有这样的环境.
现在,使用 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());
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
93450 次 |
| 最近记录: |