Entity Framework DateTime et UTC
Est-il possible d'avoir Entity Framework (je suis en utilisant la Première Approche de Code avec CTP5 actuellement) stocker toutes les valeurs DateTime que l'UTC dans la base de données?
Ou est-il peut-être une façon de le spécifier dans la cartographie, par exemple dans celui-ci pour la last_login colonne:
modelBuilder.Entity<User>().Property(x => x.Id).HasColumnName("id");
modelBuilder.Entity<User>().Property(x => x.IsAdmin).HasColumnName("admin");
modelBuilder.Entity<User>().Property(x => x.IsEnabled).HasColumnName("enabled");
modelBuilder.Entity<User>().Property(x => x.PasswordHash).HasColumnName("password_hash");
modelBuilder.Entity<User>().Property(x => x.LastLogin).HasColumnName("last_login");
Vous devez vous connecter pour publier un commentaire.
Ici est une approche que vous pourriez envisager:
Tout d'abord, définissez cet attribut suivant:
Maintenant crochet qui attribut à votre contexte EF:
Maintenant sur toute
DateTime
ouDateTime?
propriétés, vous pouvez appliquer cet attribut:Dans ce lieu, chaque fois que Entity Framework charge d'une entité à partir de la base de données, il va mettre le
DateTimeKind
que vous spécifiez, telles que l'UTC.Noter que ce n'est pas faire n'importe quoi lors de l'enregistrement. Vous devrez toujours avoir la valeur correctement converti à l'UTC avant d'essayer de le sauver. Mais il ne vous permet pas de définir le type lors de la récupération, ce qui lui permet d'être sérialisé que l'UTC, ou convertis en d'autres temps, les zones avec
TimeZoneInfo
.IObjectContextAdapter.ObjectContext
déclenche extrêmement coûteux code. J'ai été le profilage d'une application à l'aide de cette solution, et 400 appels à créer un DbContext a fallu plus de 6 secondes d'actifs fil du temps: pas exactement de la lumière-poids.'System.Array' does not contain a definition for 'Where'
record.CreatedTS = DateTime.SpecifyKind(record.CreatedTS.Value, DateTimeKind.Utc);
il n'a pas montré le fuseau horaire local, de plus ne pas afficher n'importe quel fuseau horaire. Est-il censé travailler de cette façon?DateTimeOffset
. Ce code est spécifiquement sur la façon de définirDateTimeKind.Utc
si récupérer une valeur à partir de la base de données. Il ne fait rien sur les économies de côté.DateTimeKind
attributs. Pourquoi ne pas simplement faire tous lesDateTime
etDateTime?
sortes au stackoverflow.com/a/11682982/511144 ?J'aime vraiment Matt Johnson approche, mais dans mon modèle TOUS mes DateTime membres sont l'UTC et je ne veux pas avoir à décorer le tout avec un attribut. J'ai donc généralisée de Matt approche pour permettre au gestionnaire d'événement à utiliser par défaut un Type de valeur, sauf si un membre est explicitement décoré avec de l'attribut.
Le constructeur de la ApplicationDbContext classe comprend ce code:
DateTimeKindAttribute
ressemble à ceci:DateTIme
attribut sans (public) méthode d'initialisation. Edit suggéré. Voir aussi stackoverflow.com/a/3762475/2279059La accepté de répondre ne fonctionne pas pour les prévisions ou objet Anonyme. La Performance pourrait être un problème aussi.
Pour atteindre cet objectif, nous avons besoin d'utiliser un
DbCommandInterceptor
, un objet fourni par EntityFramework.Créer Intercepteur:
interceptionContext.Result
est DbDataReader, qui nous remplacer par le nôtreRegistre de l'intercepteur dans votre
DbConfiguration
Enfin, enregistrer la configuration sur votre
DbContext
Que c'est. Des acclamations.
Pour des raisons de simplicité, ici, c'est l'ensemble de la mise en œuvre de DbReader:
Dispose
etGetData
?Je crois que j'ai trouvé une solution qui ne nécessite pas de coutume UTC vérification ou DateTime manipulation.
Fondamentalement, vous avez besoin de changer votre EF entités d'utiliser DateTimeOffset (PAS DateTime) type de données. Cette option permet de stocker le fuseau horaire, la date de valeur dans la base de données (SQL Server 2015 dans mon cas).
EF Base des demandes de données de la DB, elle recevra le fuseau horaire des informations aussi bien.
Lorsque vous transmettez des données à une application web (Angular2 dans mon cas) la date est automatiquement converti en le fuseau horaire local du navigateur, qui est ce que j'attends.
Et quand il est passé à mon serveur, il est converti à l'UTC de nouveau automatiquement, également comme prévu.
Je suis à la recherche de ce droit maintenant, et la plupart de ces réponses ne sont pas exactement grand. De ce que je peux voir, il n'y a aucun moyen de dire EF6 que les dates à venir de la base de données sont au format UTC. Si c'est le cas, le moyen le plus simple pour vous assurer que votre modèle DateTime propriétés sont en UTC serait de les vérifier et de les convertir dans l'incubateur.
Voici quelques c# comme le pseudo-code qui décrit l'algorithme
Les deux premières branches sont évidentes. Les derniers détient le secret de la sauce.
Quand EF6 crée un modèle à partir des données chargées à partir de la base de données, DateTimes sont
DateTimeKind.Unspecified
. Si vous connaissez vos dates sont toutes UTC dans la base de données, puis de la dernière branche sera parfait pour vous.DateTime.Now
est toujoursDateTimeKind.Local
, de sorte que l'algorithme ci-dessus fonctionne très bien pour les dates généré dans le code. La plupart du temps.Vous devez être prudent, cependant, comme il existe d'autres moyens
DateTimeKind.Unspecified
peut se faufiler dans votre code. Par exemple, vous pourriez désérialiser vos modèles de données JSON, et votre deserializer de la saveur les valeurs par défaut de ce genre. C'est à vous prémunir contre les dates localisées marquéDateTimeKind.Unknown
d'arriver au poseur de personne, mais EF.DateTimeKind.Utc
après vos résultats sont générés. Exemple:from o in myContext.Records select new DTO() { BrokenTimestamp = o.BbTimestamp };
jeux de toutes Sortes pourDateTimeKind.Unspecified
.Il n'y a aucun moyen de spécifier le DataTimeKind dans le Cadre de l'Entité. Vous pouvez décider de convertir les valeurs de date et heure utc avant de les stocker dans la base de données et de toujours assumer les données récupéré à partir de db que l'UTC. Mais les objets DateTime materalized pendant requête sera toujours "non spécifié". Vous pouvez également evalualte à l'aide de DateTimeOffset un objet de type DateTime.
Si vous êtes prudent de bien passer dans les dates UTC lorsque vous définissez les valeurs et tout ce qui vous intéresse est de s'assurer que le DateTimeKind est correctement réglé lorsque les entités sont extraites de la base de données, voir ma réponse ici: https://stackoverflow.com/a/9386364/279590
Pour ceux qui en ont besoin pour atteindre @MattJohnson solution .net framework 4, comme moi, de réflexion, de syntaxe, de méthode, de limitation , il nécessite un peu de modification comme indiqué ci-dessous:
Une autre approche serait de créer une interface avec le datetime propriétés, de les mettre en œuvre partielle classes d'entité. Et puis utiliser le SavingChanges événement pour vérifier si l'objet est du type d'interface, définir ces valeurs datetime tout ce que vous voulez. En effet, si ceux-ci sont createdon/modifiedon genre de dates, vous pouvez utiliser cet événement pour les remplir.
Dans mon cas, j'ai eu une seule table avec UTC datetimes. Voici ce que j'ai fait: