TimeSpan
SQL Server 2008 R2에 .Net을 저장하려고합니다 .
EF Code First는 Time(7)
SQL 로 저장해야한다고 제안하는 것 같습니다 .
그러나 TimeSpan
.Net에서는 24 시간보다 긴 기간을 처리 할 수 있습니다.
TimeSpan
SQL 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 데이터 유형 필드에 저장할 수 없으므로; 다른 몇 가지 옵션이있을 수 있습니다.
-
varchar (xx)를 사용하여 TimeSpan의 ToString을 저장하십시오. 이것의 장점은 정밀도가 데이터 유형이나 계산에 구워 질 필요가 없다는 것입니다 (초 대 밀리 초 대 일 대 2 박) TimeSpan.Parse / TryParse를 사용하면됩니다. 이것이 내가 할 일입니다.
-
첫 번째 날짜 + 시간 범위의 결과를 저장하는 두 번째 날짜, 날짜 시간 또는 날짜 시간 오프셋을 사용하십시오. db에서 읽는 것은 TimeSpan x = SecondDate-FirstDate의 문제입니다. 이 옵션을 사용하면 다른 비 .NET 데이터 액세스 라이브러리가 동일한 데이터에 액세스하지만 TimeSpans를 이해하지 못하도록 보호합니다. 그런 환경이 있다면
답변
시간 범위 (두 번 또는 날짜-시간의 차이를 계산)를 생성 할 가능성이 가장 높은 소스와 일치하도록 .NET TimeSpan
을 SQL Server DateTime
유형 으로 저장할 수 있습니다 .
SQL 서버 2의 차이 때문이다 DateTime
‘(들 Cast
에 대한 Float
S’후 Cast
다시 행 DateTime
) 단순히 인 DateTime
1 월 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 년까지의 정밀도로 시간 범위를 처리합니다.DateDiff
BigInt
DateDiff_Big
경고 :
-
이것은 1900 년 1 월 1 일과의 차이로 인해 SQL Server
DateTime
유형 (1753 년 1 월 1 일부터 9999 년 12 월 31 일까지 -147에서 +8,099 년) 범위 내의 값이 발생하는 경우에만 작동합니다 .TimeSpan
~ 29k에서 + 29kyr까지 수용 할 수 있기 때문에 .NET 측에서는 크게 걱정할 필요가 없습니다 . 나는 a) 단순을 통해 숫자로 변환 할 수 없으며 b) 범위가 충분해야 하기 때문에 SQL ServerDateTime2
유형에 대해 언급하지 않았습니다 (음수 측면의 범위는 SQL Server보다 훨씬 큽니다DateTime
). 대다수의 유스 케이스.Cast
DateTime
-
-에서 -및-뒤로 방법 을
DateTime
통해 계산 된 SQL Server 차이 는 0.1 초 이상 정확하지 않은 것으로 보입니다.Cast
Float
답변
데이터베이스에 시간 범위를 표시하는 방법에는 여러 가지가 있습니다.
시각
이 데이터 형식은 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로 매핑하는 것이 좋습니다 .