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試圖將抽象基類作爲組合鍵實例化並失敗。我能以某種方式解決這個問題嗎?

UPDATE:我testcode

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

回答

2

請問你的數據庫是什麼樣子?根據您的映射,您正在使用每個子類的表映射。在這種情況下,如果在InheritingClass的表中找不到行,NHibernate將嘗試創建BaseClass的實例。

編輯:在NHibernate映射中有<class>abstract="true"屬性可以解決您的問題。但似乎這不是暴露在流利NHibernate的ClassMap,只爲SubclassMap(這不會幫助你)。

但是,也許你也可以使用一個組件爲複合ID(這樣的NHibernate並不需要爲它的EntityKey一個BaseClass對象解決問題。見here有關的相關信息。

+0

我用一個小例子。看到更新 – Firo

+0

似乎NH正在創造它的主要存儲在一個的EntityKey – Firo

+0

@Firo我已經編輯我的答案。 – cremor

0

THX到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, 
    } 
}; 
+0

您會遇到'GetHashCode'實施方面的問題。如果兩個對象的比較相等,則每個對象的GetHashCode方法必須返回相同的值。 – cremor

+0

@crew正確,實現只是爲了最小的例子。真正的實體使用關鍵部分來實現它 – Firo