[.net] 값이 24:00:00 인 .Net Timespan을 저장하는 올바른 SQL 유형은 무엇입니까?

TimeSpanSQL Server 2008 R2에 .Net을 저장하려고합니다 .

EF Code First는 Time(7)SQL 로 저장해야한다고 제안하는 것 같습니다 .

그러나 TimeSpan.Net에서는 24 시간보다 긴 기간을 처리 할 수 ​​있습니다.

TimeSpanSQL Server에서 .Net 저장을 처리하는 가장 좋은 방법은 무엇입니까 ?



답변

데이터베이스에 a로 BIGINT저장하고 틱 수 (예 : TimeSpan.Ticks 속성)를 저장합니다.

그렇게하면 TimeSpan 객체를 검색 할 때 TimeSpan.FromTicks (value) 할 수 있습니다.


답변

충고 감사합니다. SQL 서버에는 이에 상응하는 것이 없기 때문에. TimeSpan을 틱으로 변환하여 DB에 저장하는 두 번째 필드를 만들었습니다. 그런 다음 TimeSpan을 저장하지 못했습니다.

public Int64 ValidityPeriodTicks { get; set; }

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


답변

당신이 24 시간 이상을 저장할 수없는 경우 당신은 저장할 수있는 시간을 SQL 서버 2008, 그리고 나중에 매핑입니다

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

24 시간 이하 만 저장하면 전환이 필요하지 않습니다.

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

그러나 24 시간 이상을 저장하려면 틱에 저장하고 데이터를 검색 한 다음 TimeSpan으로 변환해야합니다. 예를 들어

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


답변

직접적으로 동등한 것은 없습니다. 초 단위 또는 필요한 정확도에 적합한 것을 숫자로 저장하십시오.


답변

나는 이것이 오래된 질문이라는 것을 알고 있지만 몇 가지 다른 옵션을 주목하고 싶었습니다.

24 시간보다 큰 TimeSpan을 시간 SQL 데이터 유형 필드에 저장할 수 없으므로; 다른 몇 가지 옵션이있을 수 있습니다.

  1. varchar (xx)를 사용하여 TimeSpan의 ToString을 저장하십시오. 이것의 장점은 정밀도가 데이터 유형이나 계산에 구워 질 필요가 없다는 것입니다 (초 대 밀리 초 대 일 대 2 박) TimeSpan.Parse / TryParse를 사용하면됩니다. 이것이 내가 할 일입니다.

  2. 첫 번째 날짜 + 시간 범위의 결과를 저장하는 두 번째 날짜, 날짜 시간 또는 날짜 시간 오프셋을 사용하십시오. db에서 읽는 것은 TimeSpan x = SecondDate-FirstDate의 문제입니다. 이 옵션을 사용하면 다른 비 .NET 데이터 액세스 라이브러리가 동일한 데이터에 액세스하지만 TimeSpans를 이해하지 못하도록 보호합니다. 그런 환경이 있다면


답변

시간 범위 (두 번 또는 날짜-시간의 차이를 계산)를 생성 할 가능성이 가장 높은 소스와 일치하도록 .NET TimeSpan을 SQL Server DateTime유형 으로 저장할 수 있습니다 .

SQL 서버 2의 차이 때문이다 DateTime‘(들 Cast에 대한 FloatS’후 Cast다시 행 DateTime) 단순히 인 DateTime1 월 1 일 (1900) 예에 대하여. +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 일에 .NET DateTime형식을 추가 하여 .NET 형식으로 변환해야합니다. DateTime물론 SQL Server에서 .NET으로 읽을 때는 먼저 .NET으로 읽은 DateTime다음 1900 년 1 월 1 일에서 빼서 .NET 으로 변환하십시오 TimeSpan.

SQL Server DateTime및 SQL Server 내에서 (예 : T-SQL을 통해) 시간 범위가 생성 되고 SQL Server가 2016 년 이전 인 경우, 범위와 정밀도 요구에 따라 저장하는 것이 실용적이지 않을 수 있습니다 ~ 24 일 분의 밀리 초와 ~ 67 세 후에 ( SS 2016+에서 vs 로 반환 된 Ticks) Int유형이 오버플 로 되기 때문에 밀리 초 (분명하지 않음 ) 로 표시됩니다 . 초 반면이 솔루션은 0.1 초에서 -147에서 +8,099 년까지의 정밀도로 시간 범위를 처리합니다.DateDiffBigIntDateDiff_Big

경고 :

  1. 이것은 1900 년 1 월 1 일과의 차이로 인해 SQL Server DateTime유형 (1753 년 1 월 1 일부터 9999 년 12 월 31 일까지 -147에서 +8,099 년) 범위 내의 값이 발생하는 경우에만 작동합니다 . TimeSpan~ 29k에서 + 29kyr까지 수용 할 수 있기 때문에 .NET 측에서는 크게 걱정할 필요가 없습니다 . 나는 a) 단순을 통해 숫자로 변환 할 수 없으며 b) 범위가 충분해야 하기 때문에 SQL Server DateTime2유형에 대해 언급하지 않았습니다 (음수 측면의 범위는 SQL Server보다 훨씬 큽니다 DateTime). 대다수의 유스 케이스.CastDateTime

  2. -에서 -및-뒤로 방법 을 DateTime통해 계산 된 SQL Server 차이 는 0.1 초 이상 정확하지 않은 것으로 보입니다.CastFloat


답변

데이터베이스에 시간 범위를 표시하는 방법에는 여러 가지가 있습니다.

시각

이 데이터 형식은 SQL Server 2008부터 지원 되며를 저장하는 데 선호되는 방법TimeSpan 입니다. 매핑이 필요하지 않습니다. 또한 SQL 코드와도 잘 작동합니다.

public TimeSpan ValidityPeriod { get; set; }

그러나 원래 질문에 명시된 바와 같이이 데이터 유형은 24 시간으로 제한됩니다.

날짜 시간 오프셋

datetimeoffset데이터 형식에 직접 매핑 System.DateTimeOffset. datetime/ datetime2에서 UTC 사이의 오프셋을 나타내는 데 사용 되지만에 사용할 수도 있습니다 TimeSpan.

그러나 데이터 유형은 매우 구체적인 의미를 제안하므로 다른 옵션도 고려해야합니다.

datetime / datetime2

한 가지 방법은 datetime또는 datetime2유형 을 사용하는 것 입니다. 데이터베이스에서 직접 값을 처리해야하는 시나리오에서 가장 좋습니다. 보기, 저장 프로 시저 또는 보고서 단점은 DateTime(1900,01,01,00,00,00)비즈니스 로직에서 시간 범위를 되찾기 위해 날짜 에서 값을 빼야한다는 것 입니다.

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; }
}

bigint

다른 방법은 TimeSpan을 틱으로 변환하고 bigint데이터 유형을 사용하는 것 입니다. 그러나이 방법에는 SQL 쿼리에 사용하기가 번거 롭다는 단점이 있습니다.

public long ValidityPeriod { get; set; }

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

varchar (N)

이것은 사람이 값을 읽을 수 있어야하는 경우에 가장 좋습니다. CONVERT(datetime, ValidityPeriod)함수 를 사용하여 SQL 조회에서이 형식을 사용할 수도 있습니다 . 필요한 정밀도에 따라 8 자에서 25 자 사이가 필요합니다.

public string ValidityPeriod { get; set; }

[NotMapped]
public TimeSpan ValidityPeriodTimeSpan
{
    get { return TimeSpan.Parse(ValidityPeriod); }
    set { ValidityPeriod = value.ToString("HH:mm:ss"); }
}

보너스 : 기간 및 기간

문자열을 사용하여 NodaTime 데이터 유형, 특히 Duration및을 저장할 수도 있습니다 Period. 첫 번째는 기본적으로 TimeSpan과 동일하지만 후자는 일부 일과 월이 다른 날보다 길거나 짧다는 것을 존중합니다 (예 : 1 월은 31 일, 2 월은 28 또는 29 일, 일광 절약 시간으로 인해 일부 날은 길거나 짧음) ). 이러한 경우 TimeSpan을 사용하는 것이 잘못된 선택입니다.

이 코드를 사용하여 기간을 변환 할 수 있습니다.

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)));
    }
}

그런 다음 사용하십시오

public string ValidityPeriod { get; set; }

[NotMapped]
public Period ValidityPeriodPeriod
{
    get => ValidityPeriod.ToPeriod();
    set => ValidityPeriod = value.ToString();
}

나는 정말 좋아 NodaTime하고 종종 까다로운 버그와 많은 두통에서 나를 구해줍니다. 여기서 단점은 SQL 쿼리에서 실제로 사용할 수 없으며 메모리 내에서 계산을 수행해야한다는 것입니다.

CLR 사용자 정의 유형

사용자 정의 데이터 유형을 사용하고 사용자 정의 TimeSpan클래스를 직접 지원할 수도 있습니다. 자세한 내용은 CLR 사용자 정의 유형 을 참조하십시오.

여기서 단점은 데이터 유형이 SQL 보고서에서 제대로 작동하지 않을 수 있다는 것입니다. 또한 일부 SQL Server 버전 (Azure, Linux, Data Warehouse)은 지원되지 않습니다.

가치 전환

EntityFramework Core 2.1부터는 값 변환 을 사용할 수있는 옵션이 있습니다 .

그러나 이것을 사용할 때 EF는 많은 쿼리 를 SQL 로 변환 할 수 없으므로 쿼리가 메모리 내에서 실행됩니다. 잠재적으로 많은 양의 데이터를 애플리케이션으로 전송합니다.

적어도 지금까지는 사용하지 않는 것이 좋으며 쿼리 결과를 Automapper로 매핑하는 것이 좋습니다 .