DateTime précision dans NHibernate et de soutien pour DateTime2 dans NHibernate SchemeExport
Je suis alors à l'aide de Fluent NHibernate et ses mappant automatiquement la fonctionnalité de la carte de l'simplifiée suivante POCO classe:
public class Foo
{
public virtual int Id { get; set; }
public virtual datetime CreatedDateTime { get; set; }
}
La CreatedDateTime champ de la carte à un DateTime de SQL par défaut. Cependant si je fais un test pour vérifier que l'entité est créée correctement, il échoue. C'est parce que la précision du champ DateTime n'est pas maintenue par le biais de la base de données SQL. Je undersatnd la raison derrière ce qu'un Serveur MS SQL DateTime ne peut contenir milisecond précision par arrondi à incréments de, 000, 003 ou .007 (voir http://msdn.microsoft.com/en-us/library/ms187819.aspx). Pour cette raison, NHibernate tronque le millisecondes lors de l'enregistrement dans le magasin. Cela se traduit dans mon test en échec lors de la vérification que les champs où ont persisté correctement comme mon .NET DateTime tient ses milisecondes mais DateTime récupéré après la sauvegarde a perdu son milisecondes et, par conséquent, les deux ne sont pas vraiment égaux.
Pour surmonter ce problème, j'ai ajouté le mappage suivant à l'objet Foo:
public class FooMap : IAutoMappingOverride<Foo>
{
public void Override(AutoMapping<Foo> mapping)
{
mapping.Map(f => f.CreatedDateTime).CustomType("datetime2");
}
}
Je comprends que cette cartographie fait NHibernate persister le CreatedDateTime à un type SQL de datetime2, qui peut stocker toute la précision qu'un .NET DateTime peut.
Cela fonctionne un régal et le test passe maintenant.
Cependant, avec un passage vient d'un autre échec: Mon test qui vérifie le schéma d'exportation maintenant échoue avec l'erreur suivante:
System.ArgumentException : Dialect does not support DbType.DateTime2
Parameter name: typecode
avec une trace de la pile d':
at NHibernate.Dialect.TypeNames.Get(DbType typecode)
at NHibernate.Dialect.Dialect.GetTypeName(SqlType sqlType)
at NHibernate.Mapping.Column.GetDialectTypeName(Dialect dialect, IMapping mapping)
at NHibernate.Mapping.Table.SqlCreateString(Dialect dialect, IMapping p, String defaultCatalog, String defaultSchema)
at NHibernate.Cfg.Configuration.GenerateSchemaCreationScript(Dialect dialect)
at NHibernate.Tool.hbm2ddl.SchemaExport..ctor(Configuration cfg, IDictionary`2 configProperties)
at NHibernate.Tool.hbm2ddl.SchemaExport..ctor(Configuration cfg)
Le code utilise la NHibernate.Outil de.hbm2ddl.SchemaExport objet de l'appel de la méthode Execute.
J'utilise Couramment v1 et NHibernate v2.1.
J'ai aussi essayé de cartographie de mon DateTime
à un TimeStamp, mais ne pouvait même pas obtenir la cartographie de travail que l'insertion échoue en déclarant:
Impossible d'insérer une valeur explicite dans une colonne de type timestamp. Utilisation INSERT
avec une liste de colonne d'exclure la colonne timestamp, ou d'insérer un DEFAULT
dans la colonne timestamp.
Personne ne sait non plus comment obtenir le SchemeExport de travail avec un datetime2
OU comment obtenir le timestamp de la cartographie de travail pour un datetime
propriété?
- NHibernate ne pas tronquer les millisecondes en raison de sql-server. Vérifier ma réponse
- La spécification d'un client, le temps travaille pour moi aussi tant que j'utilise SQL Server. Je vous en remercie! Il ne fonctionne pas avec PostgreSQL, cependant, avec "le Système de.InvalidCastException : ne Pouvez pas jeter DateTime2 en tout valide DbType"
Vous devez vous connecter pour publier un commentaire.
Fait le NHibernate référence indique que le DateTime nhibernate type de magasin les .NET DateTime de SQL datetime tronqué au deuxième niveau (pas de la granularité de l'ordre de la milliseconde)
En tant que tel, il fournit la
Timestamp
NHibernate type (type="Timestamp"
dans le mapping) qui permet de stocker un .NETDateTime
SQLdatetime
sans troncature. Noter ici que d'une SQLtimestamp
type de données est pas nécessaire et permettra en effet de se briser si vous avez plus d'untimestamp
colonne dans une table. Il est donc important de faire la distinction entre lessql-type
ettype
attributs dans le NHibernate cartographie.En outre, notez que si vous travaillez avec des filtres, la même règle s'applique à la définition du filtre: Si vous spécifiez un
DateTime
paramètre, la valeur du paramètre sera tronquée sans millisecondes.Découvrez chapitre 5.2.2. De base les types de valeur, Le Tableau 5.3 Système.ValueType Types De Mapping.
type="Timestamp"
dans NHibernate?timestamp
limites. Merci!Pour ceux qui cherchent à préserver l'ordre de la nanoseconde partie de la date, vous devrez utiliser DateTime2 que le sql-type de colonne ainsi que le Nhibernate DateTime2 type.
Voici ma convention pour cette mise en place (à l'aide de fluent)
Et pour activer la convention:
À l'aide de ce que vous pourrez garder nanosecondes lors de l'entreposage de votre datetimes.
J'ai rencontré le même problème avec un CreatedDate champ de vérification sur mes classes d'affaires. J'ai travaillé autour d'elle par la mise à l'heure à l'aide de la valeur à partir d'une méthode utilitaire. Espérons que cette aide.
Dans mon domaine, il est acceptable de perdre les millisecondes de datetimes dans SQL Server. J'ai donc permettre une tolérance dans mon persistance des testeurs à l'aide de cette assistance statique (nunit mise en œuvre):
J'ai pu obtenir mon verrouillage optimiste travaillé à l'aide de la ci-dessous:
(à l'aide de datetime2).
Remarque, j'ai utilisé le nom (et le cas du type de données-nom) ici:
http://msdn.microsoft.com/en-us/library/system.data.dbtype.aspx
"DateTime2" est à mon code de mappage (sous CustomType) et pas de données Sql Server-type de cas ("datetime2"). Je ne sais pas si cela fait une différence, mais je voulais le signaler.
Couramment Cartographie:
La colonne Sql Server est créé à:
Et mes tests de base de travail et j'ai (bien) recevoir une exception comme ça (quand quelqu'un d'autre a updted la ligne)
Ligne a été mis à jour ou supprimé par une autre transaction (ou unsaved-value mapping a été incorrect): [DogBreed#abcabc1d-abc4-abc9-abcb-abca01140a27]
à NHibernate.Persister.De l'entité.AbstractEntityPersister.Mise à jour(id de l'Objet, Object[] champs, Object[] oldFields, Objet rowId, Boolean[] includeProperty, Int32 j, Objet oldVersion, Object obj, SqlCommandInfo sql, ISessionImplementor session)
au NHibernate.Persister.De l'entité.AbstractEntityPersister.UpdateOrInsert(id de l'Objet, Object[] champs, Object[] oldFields, Objet rowId, Boolean[] includeProperty, Int32 j, Objet oldVersion, Object obj, SqlCommandInfo sql, ISessionImplementor session)
au NHibernate.Persister.De l'entité.AbstractEntityPersister.Mise à jour(id de l'Objet, Object[] champs, Int32[] dirtyFields, Boolean hasDirtyCollection, Object[] oldFields, Objet oldVersion, Object obj, Objet rowId, ISessionImplementor session)
au NHibernate.D'Action.EntityUpdateAction.Execute()
au NHibernate.Moteur.ActionQueue.Execute(IExecutable exécutable)
au NHibernate.Moteur.ActionQueue.ExecuteActions(IList liste)
au NHibernate.Moteur.ActionQueue.ExecuteActions()
au NHibernate.De l'événement.Par défaut.AbstractFlushingEventListener.PerformExecutions(IEventSource session)
au NHibernate.De l'événement.Par défaut.DefaultFlushEventListener.OnFlush(FlushEvent événement)
au NHibernate.Impl.SessionImpl.Flush()
au NHibernate.Des transactions.AdoTransaction.Commit()