会话的抽象问题.锁定和具有Version属性的抽象基类

本文关键字:抽象 Version 属性 基类 问题 锁定 会话 | 更新日期: 2023-09-27 18:25:13

我在使用NHibernate(和Fluent NHibernat)和尝试使用会话时遇到问题。当Version属性位于抽象基类上时锁定功能。

我已经能够将一个示例简化为以下领域模型:

public abstract class AbstractBaseClass : Entity
{
    public virtual int Version { get; protected set; }
    public virtual string Name { get; set; }
}
public class ChildOne : AbstractBaseClass
{
    public virtual string Address { get; set; }
}

我流畅的配置是:

 fluentConfiguration.Mappings(map => map.AutoMappings.Add(
                AutoMap.AssemblyOf<AbstractBaseClass>()
                    .Where(x => x.IsSubclassOf(typeof(Entity)))
                    .IncludeBase<AbstractBaseClass>()
                    .Conventions.Add(DefaultCascade.All())));

当我尝试在会话上使用Lock方法时,数据库提供程序会抛出异常:

NHibernate.Exceptions.GenericADOException:无法检索版本:[NHLockTest.ChildOne#1][SQL:SELECT version FROM"AbstractBaseClass"WHERE Id=?]-->System.Data.SQLite.SQLiteException:没有此类列的SQLite错误:AbstractBaseClass_id

以下是我用来在一个简单的例子中重现问题的单元测试:

[Test]
public void Should_Lock_Entity()
{
    using (var session = _sessionFactory.OpenSession())
    {
        var entity = new ChildOne {Address = "Some Address", Name = "Some Name"};
        session.Save(entity);
        session.Flush();
    }
    using (var session = _sessionFactory.OpenSession())
    {
        var entity = session.Query<ChildOne>().Single();
        //this is where the exception is raised
        session.Lock(entity, LockMode.Force); 
    }
}

当我将NHibernate配置为显示SQL时,我看到会话时生成了以下语句。锁定呼叫已发出:

UPDATE "AbstractBaseClass" 
SET Version = @p0 
WHERE AbstractBaseClass_id = @p1 AND Version = @p2;
@p0 = 2 [Type: Int32 (0)], @p1 = 1 [Type: Int64 (0)], @p2 = 1 [Type: Int32 (0)]

它似乎试图更新基类的表,但却从子表中获取了forign键列名,而不是基类表上的Id列。这显然与上面的异常消息所说的不一致。

我是在这里做错了什么,还是在NHibernate中发现了一个bug?

会话的抽象问题.锁定和具有Version属性的抽象基类

在非流利的NHibernate中,您必须在XML映射中设置:多态性="显式"。

它似乎在旧版本的流利nhibernate:中不起作用

fluent nhibernate约定:设置多态模式

你可以试试(我还没有测试过):

fluentConfiguration.Mappings(map => map.AutoMappings.Add(
            AutoMap.AssemblyOf<AbstractBaseClass>()
                .Where(x => x.IsSubclassOf(typeof(Entity)))
                .IncludeBase<AbstractBaseClass>()
                .Polymorphism.Explicit()
                .Conventions.Add(DefaultCascade.All())));