Fluent NHibernate到内存中的SQLite DB会在插入版本时抛出异常

时间:2010-11-05 10:14:43

标签: c# nhibernate concurrency fluent-nhibernate

我有一个相当大的域模型,它使用流畅的NHibernate继续使用MS SQL Server 2008.

最近我们遇到了并发问题,所以我实现了Versioning NHibernate的优秀版本,着眼于使用MSSQL的timestamp数据类型。我的所有实体子类都是狡猾命名的DomainEntity抽象类,它有以下IAutoMappingOverride

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

此外,我使用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");
    }
}

我的理解是,这应该导致始终生成版本,并检查并发问题。在我的开发和生产环境中(都使用MSSQL2008)它似乎可行,但使用SQLite的内存中测试不再有效。

现在失败的基本测试如下:

    [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));
    }

我得到了以下例外:

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

at NHibernate.Persister.Entity.AbstractEntityPersister.Insert(Object id,Object [] fields,Boolean [] notNull,Int32 j,SqlCommandInfo sql,Object obj,ISessionImplementor session)  at NHibernate.Persister.Entity.AbstractEntityPersister.Insert(Object id,Object [] fields,Object obj,ISessionImplementor session)  在NHibernate.Action.EntityInsertAction.Execute()  在NHibernate.Engine.ActionQueue.Execute(IExecutable可执行文件)  在NHibernate.Engine.ActionQueue.ExecuteActions(IList列表)  在NHibernate.Engine.ActionQueue.ExecuteActions()  在NHibernate.Event.Default.AbstractFlushingEventListener.PerformExecutions(IEventSource会话)  在NHibernate.Event.Default.DefaultFlushEventListener.OnFlush(FlushEvent事件)  在NHibernate.Impl.SessionImpl.Flush()  在NHibernate.Transaction.AdoTransaction.Commit()  FluentlyConfiguredInMemoryDatabaseTest.cs(49,0):at NOIS.Persistence.Tests.FluentlyConfiguredInMemoryDatabaseTest.saveEntity(DomainEntity entity)  InMemory \ AircraftPersistenceTest.cs(33,0):at NOIS.Persistence.Tests.InMemory.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,CommandBehavior表现)  在System.Data.SQLite.SQLiteCommand.ExecuteReader(CommandBehavior行为)  在System.Data.SQLite.SQLiteCommand.ExecuteNonQuery()  在NHibernate.AdoNet.AbstractBatcher.ExecuteNonQuery(IDbCommand cmd)  在NHibernate.AdoNet.NonBatchingBatcher.AddToBatch(IExpectation期望)  at NHibernate.Persister.Entity.AbstractEntityPersister.Insert(Object id,Object [] fields,Boolean [] notNull,Int32 j,SqlCommandInfo sql,Object obj,ISessionImplementor session)

1 个答案:

答案 0 :(得分:2)

我不确定我是否完全明白你在这里做了什么。

但据我了解,您使用的是SQL Server功能,这个时间戳在Sqlite中不可用。所以它在那里不起作用。

据我所知,时间戳是由Sql Server在插入或更新记录时设置的。他们不受NH的控制。但NH支持它们,需要权衡它在插入或更新后需要从数据库中恢复它的价值。你需要一个很好的理由在NHibernate上使用时间戳。

你不需要这个SqlServer的东西来让NH的乐观锁定机制起作用。它实际上由NH完全管理,并且不需要数据库中的任何特殊内容。只需定义一个整数列和属性,并将其映射为实体版本。其他一切都是NH。我从来没有使用过任何其他东西。