2

我有以下类和映射

abstract class BaseClass
{
    public virtual int Keypart1 { get; set; }
    public virtual int Keypart2 { get; set; }

    // overridden Equals() and GetHashCode()
}

class InheritingClass : BaseClass
{
}

class BaseClassMap : ClassMap<BaseClass>
{
    public BaseClassMap()
    {
        CompositeId()
            .KeyProperty(x => x.Keypart1)
            .KeyProperty(x => x.Keypart2);
    }
}

class InheritingClassMap : SubclassMap<InheritingClass>
{
    public InheritingClassMap()
    {
        KeyColumn("Keypart1");
        KeyColumn("Keypart2");
    }
}

插入、更新和 session.Get() 工作正常,但查询如

var result = session.CreateCriteria<InheritingClass>().List<InheritingClass>();

投掷

NHibernate.InstantiationException: Cannot instantiate abstract class or interface: ConsoleApplication1.BaseClass
   bei NHibernate.Tuple.PocoInstantiator.Instantiate()
   bei NHibernate.Tuple.Component.AbstractComponentTuplizer.Instantiate()
   bei NHibernate.Type.ComponentType.Instantiate(EntityMode entityMode)
   bei NHibernate.Type.ComponentType.Instantiate(Object parent, ISessionImplementor session)
   bei NHibernate.Type.EmbeddedComponentType.Instantiate(Object parent, ISessionImplementor session)
   bei NHibernate.Type.ComponentType.ResolveIdentifier(Object value, ISessionImplementor session, Object owner)
   bei NHibernate.Type.ComponentType.NullSafeGet(IDataReader rs, String[] names, ISessionImplementor session, Object owner)
   bei NHibernate.Loader.Loader.GetKeyFromResultSet(Int32 i, IEntityPersister persister, Object id, IDataReader rs, ISessionImplementor session)
   bei NHibernate.Loader.Loader.GetRowFromResultSet(IDataReader resultSet, ISessionImplementor session, QueryParameters queryParameters, LockMode[] lockModeArray, EntityKey optionalObjectKey, IList hydratedObjects, EntityKey[] keys, Boolean returnProxies)
...

似乎 NH 试图将抽象基类实例化为复合键并失败。我能以某种方式解决这个问题吗?

更新:我的测试代码

var config = Fluently.Configure()
    .Database(SQLiteConfiguration.Standard.InMemory().ShowSql().FormatSql())
    .Mappings(m => m.FluentMappings
        .Add<BaseClassMap>()
        .Add<InheritingClassMap>()
    )
    .BuildConfiguration();

var sf = config.BuildSessionFactory();

using (var session = sf.OpenSession())
{
    new SchemaExport(config).Execute(false, true, false, session.Connection, null);

    var obj = new InheritingClass
    {
        Keypart1 = 1,
        Keypart2 = 2,
    };

    session.Save(obj);
    session.Flush();
    session.Clear();

    // throws here
    var result = session.CreateCriteria<InheritingClass>().List<InheritingClass>();
}
4

2 回答 2

2

你的数据库是什么样子的?根据您的映射,您正在使用每个子类的表映射。在这种情况下,NHibernate 将尝试创建一个实例,BaseClass如果在InheritingClass.

编辑:NHibernate 映射中有一个abstract="true"属性可以解决您的问题。<class>但似乎这并没有在 Fluent NHibernate 中为 a 公开ClassMap,只是为了SubclassMap(这对你没有帮助)。

但也许您也可以通过使用复合 ID 的组件来解决问题(这样 NHibernate 就不需要BaseClass为其 EntityKey 创建对象。有关此信息,请参见此处。

于 2011-10-17T06:08:10.200 回答
0

thx to cremor 这就是我最终的结果

abstract class BaseClass
{
    public virtual BaseClassId Key { get; set; }
}

class BaseClassId
{
    public virtual int Keypart1 { get; set; }
    public virtual int Keypart2 { get; set; }

    public override bool Equals(object obj)
    {
        var other = obj as BaseClassId;
        return (other != null) && (Keypart1 == other.Keypart1) && (Keypart2 == other.Keypart2);
    }

    public override int GetHashCode()
    {
        unchecked
        {
            return Keypart1 + Keypart2;
        }
    }
}

// mapping
CompositeId(b => b.Key)
    .KeyProperty(x => x.Keypart1)
    .KeyProperty(x => x.Keypart2);


var obj = new InheritingClass
{
    Key = new BaseClassId
    {
        Keypart1 = 1,
        Keypart2 = 2,
    }
};
于 2011-10-19T09:32:46.707 回答