I am attempting to use inheritance mapping with no success. In our system, we have one table called Member which holds both sponsors and their dependents connected by a one-to-many through the FK ParentID. To eliminate code duplication on our Edit page, I take a MemberID and use the Criteria API to select a member by ID hoping to get either a Sponsor class or a Dependent class based on the discriminator value. Instead I just get Object with id: 1351040 was not of the specified sublcass: DMT.Domain.Member (Discriminator was: 'True'). On our edit page, I do not care whether it's a sponsor or dependent since I am editing properties that are common to both classes.
I originally tried using session.Load and assumed that possibly the data had to be queried through either HQL or the criteria API. None of these so far have been successful, so my next assumption is that I am doing something wrong. Hopefully the below mapping document and code can help determine what I've done wrong.
Thank you!
Hibernate version: NHibernate 1.2.0 CR1
Mapping documents:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="DMT.Domain.Member, DMT.Domain" table="Members" polymorphism="implicit">
<id name="Id" column="MemberID" type="Int32" unsaved-value="0">
<generator class="identity"/>
</id>
<discriminator column="IsSponsor"/>
<property name="Social" column="SSN" type="String"/>
<many-to-one class="DMT.Domain.Name, DMT.Domain" column="NameID" name="NameInfo"/>
<many-to-one class="DMT.Domain.MilitaryInfo, DMT.Domain" column="SponsorID" name="MilitaryDetails"/>
<bag name="AddressList" table="MemberAddressMap" cascade="all" inverse="true">
<key column="MemberID"/>
<many-to-many column="AddressID" class="DMT.Domain.Address, DMT.Domain"/>
</bag>
<bag name="StatusList" table="MemberAcct_AffAreaStatusMap">
<key column="MemberID"/>
<one-to-many class="DMT.Domain.Status, DMT.Domain"/>
</bag>
<subclass name="DMT.Domain.Sponsor, DMT.Domain" discriminator-value="1">
<bag name="Dependents" table="Members" where="IsSponsor = 0" cascade="save-update" inverse="true">
<key column="ParentID"/>
<one-to-many class="DMT.Domain.Dependent, DMT.Domain"/>
</bag>
</subclass>
<subclass name="DMT.Domain.Dependent, DMT.Domain" discriminator-value="0">
<many-to-one class="DMT.Domain.Sponsor, DMT.Domain" column="ParentID" name="Sponsor"/>
</subclass>
</class>
</hibernate-mapping>
Code between sessionFactory.openSession() and session.close():
public Member FindById(int id)
{
return this.GetByCriteria(Expression.Eq("Id", id))[0];
}
public List<T> GetByCriteria(params ICriterion[] criterion)
{
DetachedCriteria criteria = DetachedCriteria.For(persitentType);
return GetByCriteria(criteria, criterion);
}
public List<T> GetByCriteria(DetachedCriteria detachedCriteria, params ICriterion[] criterion)
{
ICriteria criteria = detachedCriteria.GetExecutableCriteria(session);
foreach (ICriterion criterium in criterion)
{
criteria.Add(criterium);
}
return ConvertToGenericList(criteria.List());
}
Full stack trace of any exception that occurs:
[WrongClassException: Object with id: 1351040 was not of the specified sublcass: DMT.Domain.Member (Discriminator was: 'True')]
NHibernate.Loader.Loader.GetInstanceClass(IDataReader rs, Int32 i, ILoadable persister, Object id, ISessionImplementor session) +291
NHibernate.Loader.Loader.InstanceNotYetLoaded(IDataReader dr, Int32 i, ILoadable persister, EntityKey key, LockMode lockMode, EntityKey optionalObjectKey, Object optionalObject, IList hydratedObjects, ISessionImplementor session) +113
NHibernate.Loader.Loader.GetRow(IDataReader rs, ILoadable[] persisters, EntityKey[] keys, Object optionalObject, EntityKey optionalObjectKey, LockMode[] lockModes, IList hydratedObjects, ISessionImplementor session) +394
NHibernate.Loader.Loader.GetRowFromResultSet(IDataReader resultSet, ISessionImplementor session, QueryParameters queryParameters, LockMode[] lockModeArray, EntityKey optionalObjectKey, IList hydratedObjects, EntityKey[] keys, Boolean returnProxies) +405
NHibernate.Loader.Loader.DoQuery(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies) +641
NHibernate.Loader.Loader.DoQueryAndInitializeNonLazyCollections(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies) +83
NHibernate.Loader.Loader.DoList(ISessionImplementor session, QueryParameters queryParameters) +77
NHibernate.Loader.Loader.ListIgnoreQueryCache(ISessionImplementor session, QueryParameters queryParameters) +46
NHibernate.Loader.Loader.List(ISessionImplementor session, QueryParameters queryParameters, ISet querySpaces, IType[] resultTypes) +152
NHibernate.Loader.Criteria.CriteriaLoader.List(ISessionImplementor session) +67
NHibernate.Impl.SessionImpl.Find(CriteriaImpl criteria, IList results) +492
NHibernate.Impl.SessionImpl.Find(CriteriaImpl criteria) +65
NHibernate.Impl.CriteriaImpl.List() +34
DMT.Data.GenericNHibernateDao`2.GetByCriteria(DetachedCriteria detachedCriteria, ICriterion[] criterion) in D:\Projects\Disaster Muster Tool\DMT.Data\GenericNHibernateDao.cs:71
DMT.Data.GenericNHibernateDao`2.GetByCriteria(ICriterion[] criterion) in D:\Projects\Disaster Muster Tool\DMT.Data\GenericNHibernateDao.cs:59
DMT.Data.NHibernateMemberDao.FindById(Int32 id) in D:\Projects\Disaster Muster Tool\DMT.Data\NHibernateMemberDao.cs:14
DMT.Service.MemberService.FindMemberById(Int32 id) in D:\Projects\Disaster Muster Tool\DMT.Service\MemberService.cs:18
DMT.Presentation.Presenters.MemberEditPresenter.BindData() in D:\Projects\Disaster Muster Tool\DMT.Presentation\Presenters\MemberEditPresenter.cs:32
DMT.Presentation.Presenters.MemberEditPresenter.Initialize(Boolean IsPostBack, Int32 memberId) in D:\Projects\Disaster Muster Tool\DMT.Presentation\Presenters\MemberEditPresenter.cs:26
Muster.InitializeMemberEditView(Int32 memberId) in d:\WebSites\DMTWeb\Muster.aspx.cs:32
Muster.presenter_SelectedEvent(Object sender, DomainObjectSelectedEventArgs`1 e) in d:\WebSites\DMTWeb\Muster.aspx.cs:25
DMT.Presentation.Presenters.SearchMembersPresenter.Select() in D:\Projects\Disaster Muster Tool\DMT.Presentation\Presenters\SearchMembersPresenter.cs:36
views_SearchMembersView.SponsorGridView_SelectedIndexChanged(Object sender, EventArgs e) in d:\WebSites\DMTWeb\views\SearchMembersView.ascx.cs:48
System.Web.UI.WebControls.GridView.OnSelectedIndexChanged(EventArgs e) +105
System.Web.UI.WebControls.GridView.HandleSelect(Int32 rowIndex) +89
System.Web.UI.WebControls.GridView.HandleEvent(EventArgs e, Boolean causesValidation, String validationGroup) +221
System.Web.UI.WebControls.GridView.RaisePostBackEvent(String eventArgument) +199
System.Web.UI.WebControls.GridView.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) +7
System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +11
System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) +174
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +5102
Name and version of the database you are using:
SQL Server 2000.
The generated SQL (show_sql=true):
SELECT this_.MemberID as MemberID10_0_, this_.SSN as SSN10_0_, this_.NameID as NameID10_0_, this_.SponsorID as SponsorID10_0_, this_.ParentID as ParentID10_0_, this_.IsSponsor as IsSponsor0_ FROM Members this_ WHERE this_.MemberID = @p0; @p0 = '1351040'
Debug level Hibernate log excerpt:
11:40:01.607 [4] DEBUG NHibernate.Impl.SessionImpl - opened session
11:40:01.607 [4] DEBUG NHibernate.Impl.SessionImpl - flushing session
11:40:01.607 [4] DEBUG NHibernate.Impl.SessionImpl - Flushing entities and processing referenced collections
11:40:01.607 [4] DEBUG NHibernate.Impl.SessionImpl - Processing unreferenced collections
11:40:01.607 [4] DEBUG NHibernate.Impl.SessionImpl - scheduling collection removes/(re)creates/updates
11:40:01.607 [4] DEBUG NHibernate.Impl.SessionImpl - Flushed: 0 insertions, 0 updates, 0 deletions to 0 objects
11:40:01.607 [4] DEBUG NHibernate.Impl.SessionImpl - Flushed: 0 (re)creations, 0 updates, 0 removals to 0 collections
11:40:01.607 [4] DEBUG NHibernate.Impl.SessionImpl - dont need to execute flush
11:40:01.607 [4] DEBUG NHibernate.Impl.BatcherImpl - Opened new IDbCommand, open IDbCommands: 1
11:40:01.607 [4] DEBUG NHibernate.Impl.BatcherImpl - Building an IDbCommand object for the SqlString: SELECT this_.MemberID as MemberID10_0_, this_.SSN as SSN10_0_, this_.NameID as NameID10_0_, this_.SponsorID as SponsorID10_0_, this_.ParentID as ParentID10_0_, this_.IsSponsor as IsSponsor0_ FROM Members this_ WHERE this_.MemberID = ?
11:40:01.607 [4] DEBUG NHibernate.SQL - SELECT this_.MemberID as MemberID10_0_, this_.SSN as SSN10_0_, this_.NameID as NameID10_0_, this_.SponsorID as SponsorID10_0_, this_.ParentID as ParentID10_0_, this_.IsSponsor as IsSponsor0_ FROM Members this_ WHERE this_.MemberID = @p0; @p0 = '1351040'
11:40:01.607 [4] DEBUG NHibernate.Connection.DriverConnectionProvider - Obtaining IDbConnection from Driver
11:40:01.607 [4] DEBUG NHibernate.Impl.BatcherImpl - Opened IDataReader, open IDataReaders: 1
11:40:01.638 [4] DEBUG NHibernate.Driver.NHybridDataReader - running NHybridDataReader.Dispose()
11:40:01.638 [4] DEBUG NHibernate.Impl.BatcherImpl - Closed IDataReader, open IDataReaders :0
11:40:01.638 [4] DEBUG NHibernate.Impl.BatcherImpl - Closed IDbCommand, open IDbCommands: 0
11:40:01.638 [4] DEBUG NHibernate.Impl.ConnectionManager - aggressively releasing database connection
11:40:01.638 [4] DEBUG NHibernate.Connection.ConnectionProvider - Closing connection
11:40:03.777 [4] DEBUG NHibernate.Impl.ConnectionManager - after autocommit
11:40:03.777 [4] DEBUG NHibernate.Impl.ConnectionManager - aggressively releasing database connection
11:40:03.777 [4] DEBUG NHibernate.Impl.SessionImpl - transaction completion
_________________ Paul
|