Il existe plusieurs façons de présenter un intervalle de temps dans la base de données.
temps
Ce type de données est supporté depuis SQL Server 2008 et est le méthode préférée pour stocker un TimeSpan
. Aucun mappage n'est nécessaire. Il fonctionne également bien avec le code SQL.
public TimeSpan ValidityPeriod { get; set; }
Toutefois, comme indiqué dans la question initiale, ce type de données est limité à 24 heures.
datetimeoffset
El datetimeoffset
correspond directement au type de données System.DateTimeOffset
. Il est utilisé pour exprimer le décalage entre un datetime
/ datetime2
à UTC, mais vous pouvez également l'utiliser pour TimeSpan
.
Toutefois, comme le type de données suggère une sémantique très spécifique, vous devez également envisager d'autres options.
datetime / datetime2
Une approche pourrait consister à utiliser le datetime
o datetime2
types. C'est la meilleure solution dans les scénarios où vous devez traiter les valeurs dans la base de données directement, c'est-à-dire pour les vues, les procédures stockées ou les rapports. L'inconvénient est que vous devez soustraire la valeur DateTime(1900,01,01,00,00,00)
de la date pour récupérer la période de temps dans votre logique d'entreprise.
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
Une autre approche pourrait consister à convertir le TimeSpan en ticks et à utiliser la fonction bigint
type de données. Toutefois, cette approche présente l'inconvénient d'être lourde à utiliser dans les requêtes SQL.
public long ValidityPeriod { get; set; }
[NotMapped]
public TimeSpan ValidityPeriodTimeSpan
{
get { return TimeSpan.FromTicks(ValidityPeriod); }
set { ValidityPeriod = value.Ticks; }
}
varchar(N)
Ce format est le meilleur pour les cas où la valeur doit être lisible par les humains. Vous pouvez également utiliser ce format dans les requêtes SQL en utilisant l'attribut CONVERT(datetime, ValidityPeriod)
fonction. En fonction de la précision requise, vous aurez besoin de 8 à 25 caractères.
public string ValidityPeriod { get; set; }
[NotMapped]
public TimeSpan ValidityPeriodTimeSpan
{
get { return TimeSpan.Parse(ValidityPeriod); }
set { ValidityPeriod = value.ToString("HH:mm:ss"); }
}
Bonus : Période et durée
En utilisant une chaîne, vous pouvez également stocker NodaTime les types de données, en particulier Duration
y Period
. Le premier est fondamentalement identique à un TimeSpan, tandis que le second respecte le fait que certains jours et mois sont plus longs ou plus courts que d'autres (par exemple, le mois de janvier compte 31 jours et celui de février 28 ou 29 ; certains jours sont plus longs ou plus courts en raison de l'heure d'été). Dans de tels cas, l'utilisation d'un TimeSpan est le mauvais choix.
Vous pouvez utiliser ce code pour convertir les périodes :
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)));
}
}
Et ensuite l'utiliser comme
public string ValidityPeriod { get; set; }
[NotMapped]
public Period ValidityPeriodPeriod
{
get => ValidityPeriod.ToPeriod();
set => ValidityPeriod = value.ToString();
}
J'aime vraiment NodaTime
et cela m'évite souvent des bugs délicats et beaucoup de maux de tête. L'inconvénient est que vous ne pouvez pas vraiment l'utiliser dans des requêtes SQL et que vous devez effectuer des calculs en mémoire.
CLR Type défini par l'utilisateur
Vous avez également la possibilité d'utiliser un type de données personnalisé et de prendre en charge un modèle de données personnalisé. TimeSpan
directement. Voir Types définis par l'utilisateur dans le CLR pour les détails.
L'inconvénient ici est que le type de données peut ne pas se comporter correctement avec les rapports SQL. En outre, certaines versions de SQL Server (Azure, Linux, Data Warehouse) ne sont pas prises en charge.
Conversions de valeurs
À partir de EntityFramework Core 2.1, vous avez la possibilité d'utiliser Conversions de valeurs .
Cependant, en l'utilisant, EF ne sera pas en mesure de convertir de nombreuses requêtes en SQL, ce qui permet aux requêtes de s'exécuter en mémoire et de transférer potentiellement de très nombreuses données vers votre application.
Donc, au moins pour l'instant, il est préférable de ne pas l'utiliser, et de simplement faire correspondre le résultat de la requête avec Automapper .
15 votes
Je l'utilise pour stocker la durée des événements récurrents. Je voulais donc capturer la durée de l'événement indépendamment de la date.
0 votes
Duplicata possible de Comment faire correspondre TimeSpan avec plus de 24 heures à SQL server Code First ?
1 votes
Relié, pas en double. J'ai écrit les deux. L'un concerne le Code First et la manière de modifier le mappage pour TimeSpan. L'autre porte sur le mappage de TimeSpan de type .Net à SQL.