C# 对于内存中的SQLite DB,Fluent NHibernate在插入版本时引发异常

C# 对于内存中的SQLite DB,Fluent NHibernate在插入版本时引发异常,c#,nhibernate,concurrency,fluent-nhibernate,C#,Nhibernate,Concurrency,Fluent Nhibernate,我有一个相当大的域模型,它使用fluent NHibernate到MS SQL Server 2008进行持久化 最近我们遇到了并发问题,所以我实现了版本控制NHibernate的优秀版本,目的是使用MSSQL的timestampdatatype。“我的所有实体”都是名称巧妙的DomainEntity抽象类的子类,该类具有以下IAutoMappingOverride: public class DomainEntityOverride : IAutoMappingOverride<Doma

我有一个相当大的域模型,它使用fluent NHibernate到MS SQL Server 2008进行持久化

最近我们遇到了并发问题,所以我实现了版本控制NHibernate的优秀版本,目的是使用MSSQL的
timestamp
datatype。“我的所有实体”都是名称巧妙的
DomainEntity
抽象类的子类,该类具有以下
IAutoMappingOverride

public class DomainEntityOverride : IAutoMappingOverride<DomainEntity> {
    public void Override(AutoMapping<DomainEntity> mapping) {
        mapping.OptimisticLock.Version();
        mapping.Version(entity => entity.Version);
    }
}
我的理解是,这将导致始终生成版本,并检查并发性问题。在我的开发和生产环境中(都使用MSSQLS2008),它似乎可以工作,但我使用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));
    }
在NHibernate.Persister.Entity.AbstractEntityPersister.Insert(对象id、对象[]字段、布尔[]notNull、Int32 j、SqlCommandInfo sql、对象obj、ISessionImplementor会话) 在NHibernate.Persister.Entity.AbstractEntityPersister.Insert(对象id,对象[]字段,对象obj,ISessionImplementor会话) 在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()处 fluentlyConfiguredMemoryDatabaseTest.cs(49,0):位于NOIS.Persistence.Tests.fluentlyConfiguredMemoryDatabaseTest.saveEntity(域实体) InMemory\AircraftPersistenceTest.cs(33,0):at NOIS.Persistence.Tests.InMemory.AircraftPersistenceTest.persistenrairs\u newrairs\u 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.ExecuteOnQuery(IDbCommand cmd)中 在NHibernate.AdoNet.NonBatchingBatcher.AddToBatch(预期期望值)
在NHibernate.Persister.Entity.AbstractEntityPersister.Insert(对象id、对象[]字段、布尔[]notNull、Int32 j、SqlCommandInfo sql、对象obj、ISessionImplementor会话)

我不确定是否完全理解您在这里所做的工作

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

据我所知,时间戳是Sql Server在插入或更新记录时设置的。他们不在NH的控制之下。但是NH支持它们,需要在插入或更新后从数据库中获取其值。您需要一个很好的理由来使用NHibernate的时间戳


要使NH的乐观锁定机制正常工作,您不需要这些SqlServer的东西。它实际上完全由NH管理,不需要数据库中的任何特殊内容。只需定义一个整数列和属性,并将其映射为entities版本。其他一切都完成了。我从不需要使用其他任何东西。

根据讨论,我支持这一点:是的,我明白了。时间戳的好处是,来自其他系统的行更新会自动更新时间戳列。在我的DomainEntity中,Version属性是一个字节[]。只是为了添加-我现在尝试将CustomSqlType更改为“int”,并且出现了相同的错误。我不认为这个NOTNULL约束来自数据类型。您不应该只将数据库数据类型设置为int。它还应该是一个int属性,映射为version,而不是property。我不知道它在fluent中的外观如何,但是xml映射有一个版本标记。当然,当您从timestamp切换到int时,仍然有一个NOTNULL约束。您甚至可以在sql server上使用它,因为该列将不再获取任何值。您需要告诉NH通过将值映射为版本来填充该值。
    [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