2010-11-05 4 views
1

j'ai un assez grand domaine modèle qui persiste en utilisant NHibernate couramment MS SQL Server 2008.Courant NHibernate à un en mémoire SQLite DB émet des exceptions sur insert avec la version

Récemment, nous avons mis en place en concurrence problèmes, j'ai donc implémenté l'excellente Versioning de NHibernate en utilisant le type de données timestamp de MSSQL. Toutes mes entités sous-classe de la classe abstraite DomainEntity astucieusement nommé, qui a les éléments suivants IAutoMappingOverride:

public class DomainEntityOverride : IAutoMappingOverride<DomainEntity> { 
    public void Override(AutoMapping<DomainEntity> mapping) { 
     mapping.OptimisticLock.Version(); 
     mapping.Version(entity => entity.Version); 
    } 
} 

De plus, je mis en place le versionnage utilise un IVersionConvention:

public class VersionConvention : IVersionConvention { 
    public void Apply(IVersionInstance instance) { 
     instance.Column("Version"); 
     instance.Generated.Always(); 
     instance.UnsavedValue("null"); 
     instance.Not.Nullable(); 
     instance.CustomSqlType("timestamp"); 
    } 
} 

Ma compréhension est que cela devrait provoquer la version pour toujours être généré, et vérifié pour les problèmes de concurrence. Dans mes environnements de développement et de production (tous deux utilisant MSSQL2008), cela semble fonctionner, mais mes tests en mémoire utilisant SQLite ne fonctionnent plus.

Un test de base qui ne maintenant est la suivante:

[Test(Description = "Can save an aircraft and it is persisted")] 
    public void PersistAircraft_NewAircraft_AircraftIsPersisted() { 
     var id = saveEntity(_aircraft); //exception thrown here 

     var persisted = getEntity<Aircraft>(id); 

     Assert.That(persisted.Registration, Is.EqualTo(_aircraftRegistration)); 
     Assert.That(persisted.Remarks, Is.EqualTo(_aircraftRemark)); 
    } 

je reçois l'exception follwing:

Test 'NOIS.Persistence.Tests.InMemory.AircraftPersistenceTest.PersistAircraft_NewAircraft_AircraftIsPersisted' failed: NHibernate.Exceptions.GenericADOException : could not insert: [NOIS.Model.Entities.AircraftType#9c2809ea-c0c5-4778-838b-9e2500a6d2ef][SQL: INSERT INTO "AircraftType" (ProducedBy, Active, Remarks, Name, Code, Category_id, Id) VALUES (?, ?, ?, ?, ?, ?, ?)] 
----> System.Data.SQLite.SQLiteException : Abort due to constraint violation 
AircraftType.Version may not be NULL 

à NHibernate.Persister.Entity.AbstractEntityPersister.Insert (id Object, Object [ ] champs, Boolean [] notNull, Int32 j, SqlCommandInfo sql, objet obj, Session ISessionImplementor) à NHibernate.Persister.Entity.AbstractEntityPersister.Insert (Object id, Object [] champs, Object obj, session ISessionImplementor) à NHibernate.Action.EntityInsertAction.Execute() à NHibernate.Engine.ActionQueue.Execute (exécutable de IExecutable) à NHibernate.Engine.ActionQueue.ExecuteActions (liste de IList) à NHibernate.Engine.ActionQueue.ExecuteActions() à NHibernate.Event.Default.AbstractFlushingEventListener.PerformExecutions (session IEventSource) à NHibernate.Event.Default.DefaultFlushEventListener.OnFlush (événement FlushEvent) à NHibernate.Impl.SessionImpl.Flush() à NHibernate.Transaction.AdoTransaction.Commit() FluentlyConfiguredInMemoryDatabaseTest.cs (49,0): à NOIS.Persistence.Tests.FluentlyConfiguredInMemoryDatabaseTest.saveEntity (entité DomainEntity) InMemory \ AircraftPersistenceTest.cs (33,0): à NOIS.Persistence.Tests.I nMemory.AircraftPersistenceTest.PersistAircraft_NewAircraft_AircraftIsPersisted() --SQLiteException à System.Data.SQLite.SQLite3.Reset (SQLiteStatement stmt) à System.Data.SQLite.SQLite3.Step (SQLiteStatement stmt) à System.Data.SQLite.SQLiteDataReader .NextResult() à System.Data.SQLite.SQLiteDataReader..ctor (SQLiteCommand cmd, comportez CommandBehavior) à System.Data.SQLite.SQLiteCommand.ExecuteReader (comportement CommandBehavior) à System.Data.SQLite.SQLiteCommand.ExecuteNonQuery () à NHibernate.AdoNet.AbstractBatcher.ExecuteNonQuery (IDbCommand cmd) à NHibernate.AdoNet.NonBatchingBatcher.AddToBatch (attente IExpectation) à NHibernate.Persister.Entity.AbstractEntityPers ister.Insert (Object id, Object [] champs, Boolean [] notNull, Int32 j, SqlCommandInfo sql, Object obj, session ISessionImplementor)

Répondre

2

Je ne suis pas sûr si je comprends parfaitement ce que vous faites ici.Mais si je comprends bien, vous utilisez une fonctionnalité SQL Server, ce timestamps, qui ne sont pas disponibles dans Sqlite. Donc ça ne marche pas là. Pour autant que je sache, les horodatages sont définis par SQL Server lors de l'insertion ou de la mise à jour des enregistrements. Ils ne sont pas sous contrôle de NH. Mais NH les soutient, avec le compromis dont il a besoin pour récupérer sa valeur de la base de données après l'insertion ou la mise à jour. Vous avez besoin d'une bonne raison d'utiliser les horodatages avec NHibernate.

Vous n'avez pas besoin de ce matériel SqlServer pour que le mécanisme de verrouillage optimiste de NH fonctionne. Il est en réalité entièrement géré par NH et ne nécessite aucun élément particulier de la base de données. Définissez simplement une colonne et une propriété entières et mappez-la en tant que version d'entités. Tout le reste est fait soit NH. Je n'ai jamais eu besoin d'autre chose.

+0

I deuxième celui-ci, selon cette discussion: http://groups.google.com/group/fluent-nhibernate/browse_thread/thread/8cc36aa83b046810/94ce8a7e92943993?lnk=gst&q=sqlite#94ce8a7e92943993 – Iain

+0

Oui, je vois que . Ce que je gagne avec un horodatage, c'est que les mises à jour de lignes provenant d'autres systèmes mettent automatiquement à jour la colonne d'horodatage. Dans mon DomainEntity la propriété Version est un octet []. – Tomas

+1

Juste pour ajouter - j'ai maintenant essayé de changer le CustomSqlType en "int", et la même erreur se produit. Je ne pense pas que cette contrainte NOT NULL provient du type de données. – Tomas

Questions connexes