These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 3 posts ] 
Author Message
 Post subject: Help needed (please) with creating a Custom Dictionary.
PostPosted: Mon Sep 10, 2007 9:27 am 
Newbie

Joined: Thu Aug 02, 2007 11:20 am
Posts: 4
I'm trying to create a IUserCollectionType to map a custom generic dictionary without much success:

The custom interface:
Code:
    /// <summary>
    /// Simple extension of an <see cref="IDictionary{TKey,TValue}"/>.  This is pretty much as per
    /// http://www.martinfowler.com/eaaDev/TemporalProperty.html, with the only deviation being that I am extending an
    /// <see cref="IDictionary{TKey,TValue}"/>
    /// </summary>
    /// <typeparam name="TKey">The type of the key.</typeparam>
    /// <typeparam name="TValue">The type of the value.</typeparam>
    public interface IMilestoneCollection<TKey, TValue> : IDictionary<TKey, TValue> where TKey : IComparable<TKey>
    {
        /// <summary>
        /// Finds the item that is relevant for the <paramref name="value"/>.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <returns></returns>
        TValue FindItemFor(TKey value);
    }


In my concrete implementation of this interface I am basically decorating (i.e wrapping) a Dictionary, to allow me to cache the milestones in reverse order whenever it is updated.

I've created an implementation of IUserCollectionType & PersistentGenericMap to allow me to map this:

Code:
public class MilestoneCollectionType<TKey, TValue> : IUserCollectionType
        where TKey : IComparable<TKey>
    {
        #region IUserCollectionType Members

        public IPersistentCollection Instantiate(ISessionImplementor session, ICollectionPersister persister)
        {
            return new PersistentMilestoneCollection<TKey, TValue>(session);
        }

        public IPersistentCollection Wrap(ISessionImplementor session, object collection)
        {
            return new PersistentMilestoneCollection<TKey, TValue>(session, (IMilestoneCollection<TKey, TValue>) collection);
        }

        public IEnumerable GetElements(object collection)
        {
            return (IEnumerable) collection;
        }

        public bool Contains(object collection, object entity)
        {
            return ((IMilestoneCollection<TKey, TValue>)collection).Contains((KeyValuePair<TKey, TValue>)entity);
        }

        public object IndexOf(object collection, object entity)
        {
            throw new NotImplementedException();
        }

        public object ReplaceElements(object original, object target, ICollectionPersister persister, object owner, IDictionary copyCache, ISessionImplementor session)
        {
            throw new NotImplementedException();
        }

        public object Instantiate()
        {
            return new MilestoneCollection<TKey, TValue>();
        }

        #endregion
    }

    public class HistoricAddressCollectionType : MilestoneCollectionType<DateTime, Address>{}

public class PersistentMilestoneCollection<TKey, TValue> : PersistentGenericMap<TKey, TValue>, IMilestoneCollection<TKey, TValue>
        where TKey : IComparable<TKey>
    {
        public PersistentMilestoneCollection(ISessionImplementor session) : base(session){}
        public PersistentMilestoneCollection(ISessionImplementor session, IMilestoneCollection<TKey, TValue> map) : base(session, map){}

        #region IMilestoneCollection<TValue> Members

        public TValue FindItemFor(TKey value)
        {
            Read();
            return ((IMilestoneCollection<TKey, TValue>) map).FindItemFor(value);
        }

        #endregion
    }


and my mapping file is :

Code:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping default-cascade="none"
                   xmlns="urn:nhibernate-mapping-2.2"
                   assembly="UserTypeExample.Domain"
                   namespace="UserTypeExample.Domain">
  <class name="Person" table="People" lazy="false">
    <id name="Id" column="PersonId">
      <generator class="identity" />
    </id>

    <version name="_version" column="Version" access="field" />
   
    <property name="Name" column="Name" />
    <map name="_addresses"
         access="field"
         generic="true"
         table="HistoricAddresses"
         collection-type="UserTypeExample.Persistence.HistoricAddressCollectionType, UserTypeExample.Persistence"
         cascade="all-delete-orphan">
      <key column="PersonId" />
      <index column="StartDate" type="System.DateTime"/>
      <one-to-many class="Address"/>
    </map>
  </class>
</hibernate-mapping>


However, when I call ISession.SaveOrUpdate I get the following exception:

Quote:
NHibernate.MappingException was unhandled
Message="Unknown entity class: System.Collections.Generic.KeyValuePair`2[[System.DateTime, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[UserTypeExample.Domain.Address, UserTypeExample.Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]"
Source="NHibernate"
StackTrace:
at NHibernate.Impl.SessionFactoryImpl.GetEntityPersister(Type theClass)
at NHibernate.Impl.SessionImpl.GetClassPersister(Type theClass)
at NHibernate.Impl.SessionImpl.GetEntityPersister(Object obj)
at NHibernate.Impl.SessionImpl.SaveOrUpdate(Object obj)
at NHibernate.Engine.Cascades.CascadingAction.ActionSaveUpdateClass.Cascade(ISessionImplementor session, Object child, Object anything)
at NHibernate.Engine.Cascades.Cascade(ISessionImplementor session, Object child, IType type, CascadingAction action, CascadeStyle style, CascadePoint cascadeTo, Object anything)
at NHibernate.Engine.Cascades.CascadeCollection(CascadingAction action, CascadeStyle style, CollectionType collectionType, IType elemType, Object child, CascadePoint cascadeVia, ISessionImplementor session, Object anything)
at NHibernate.Engine.Cascades.Cascade(ISessionImplementor session, Object child, IType type, CascadingAction action, CascadeStyle style, CascadePoint cascadeTo, Object anything)
at NHibernate.Engine.Cascades.Cascade(ISessionImplementor session, IEntityPersister persister, Object parent, CascadingAction action, CascadePoint cascadeTo, Object anything)
at NHibernate.Impl.SessionImpl.DoSave(Object theObj, EntityKey key, IEntityPersister persister, Boolean replicate, Boolean useIdentityColumn, CascadingAction cascadeAction, Object anything)
at NHibernate.Impl.SessionImpl.DoSave(Object obj, Object id, IEntityPersister persister, Boolean useIdentityColumn, CascadingAction cascadeAction, Object anything)
at NHibernate.Impl.SessionImpl.SaveWithGeneratedIdentifier(Object obj, CascadingAction action, Object anything)
at NHibernate.Impl.SessionImpl.Save(Object obj)
at NHibernate.Impl.SessionImpl.SaveOrUpdate(Object obj)
at SevenIM.Persistence.NHibernateHelper`2.SaveOrUpdate(TPersistableObject toSaveOrUpdate)
at SevenIM.Persistence.NHibernateRepository`2.SaveOrUpdate(TPersistableObject toSaveOrUpdate)
at UserTypeExample.ConsoleApp.Runner.CreateBaseDate() in C:\vs 2005\main\Test\UserTypeExample\UserTypeExample.ConsoleApp\Runner.cs:line 43
at UserTypeExample.ConsoleApp.Runner.Main(String[] args) in C:\vs 2005\main\Test\UserTypeExample\UserTypeExample.ConsoleApp\Runner.cs:line 22
at System.AppDomain.nExecuteAssembly(Assembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()


any ideas?... should I be using IUserCollectionType for a custom Dictionary.

N.B. I was getting an exception when the SessionFactory was being built, when I had collection-type="MilestoneCollectionType" which went away when I changed to collection-type="HistoricAddressCollectionType"


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 11, 2007 12:00 pm 
Beginner
Beginner

Joined: Fri Sep 08, 2006 2:55 am
Posts: 21
Interesting, we've got cases where this sort of mapping would be useful...didn't even know it was possible so I'll be interested in seeing if you get it fixed.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Sep 19, 2007 4:40 am 
Newbie

Joined: Thu Aug 02, 2007 11:20 am
Posts: 4
Iv'e created an issue with this here http://jira.nhibernate.org/browse/NH-1136 (updated source code located there) as it appears that I can create the correct mapping when I need an <element />, but can't when I need a <many-to-many> association... unless I have the mapping wrong?


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 3 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.