Hi all

I have a parent class which has a list of versions (one-to-many), and the
version has a collection of associations (many-to-many). The basic idea is
that the parent has versions over time, and within each version there will
be different associations. I've included the classes and mappings below, an
attempt by me to distil the idea of what i'm trying to do into the simplest
case possible.

I've been trying to reduce the number of queries fired. When getting many of
the type I'd like to keep the lazy loading, when getting the individual by
id I'd like to get as much as possible in one select (there are small
numbers of each of the children, and they are guaranteed to be used). I'm
using Criteria. The problem is that the version list contains duplicates due
to the join via the many-to-many. I've read Ken's recent post on removing
duplicates, the FAQ, and have pored over many other posts. I understand why
the duplicates are there, and have seen the various options for removing
them, I just can't get them to work on the "child collection". I'm sure what
I'm trying to do is possible, I'm just going round in circles, in the dark,
without much certainty of what direction i should head.

I've tried the following criteria, which successfully execute in one sql
statement, but return a parent that has duplicated versions:
            Parent parent = session.CreateCriteria(typeof(Parent))
                .SetFetchMode("Versions", FetchMode.Join)
                .SetFetchMode("Versions.Associations", FetchMode.Join)
                .SetResultTransformer(new
DistinctRootEntityResultTransformer())
                .Add(Restrictions.IdEq(id))
                .UniqueResult<Parent>();

            Parent parent = session.CreateCriteria(typeof(Parent))
                .CreateAlias("Versions", "version", JoinType.LeftOuterJoin)
                .CreateAlias("version.Associations", "association",
JoinType.LeftOuterJoin)
                .SetResultTransformer(new
DistinctRootEntityResultTransformer())
                .Add(Restrictions.IdEq(id))
                .UniqueResult<Parent>();

And various combinations of the above. I've also attempted to use a detached
criterion for the version collection, but I'm really not sure how to wire it
in. I've also tried creating more criteria inline
(.CreateCriteria("Versions..), but this seems to execute the same query
twice. I am happy to remove the duplicates in the version collection after
the query if this is necessary, but i suspect that it is not (which is what
I understand the DictinctRootEntityResultTransformer does, I just want it to
work it's magic against a child collection).

Thanks in advance for any advice.

Ben


If of use, the distilled model looks something like this:

    public class Parent
    {
        public virtual int Id { get; set; }
        public virtual string Name { get; set; }
        public virtual IList<ParentVersion> Versions { get; set; }

        public Parent()
        {
            Versions = new List<ParentVersion>();
        }
    }

    public class ParentVersion
    {
        public virtual int Id { get; set; }
        public virtual string Address { get; set; }
        public virtual Parent Parent { get; set; }
        public virtual IList<Association> Associations { get; set; }

        public ParentVersion()
        {
            Associations = new List<Association>();
        }
    }

    public class Association
    {
        public virtual int Id { get; set; }
        public virtual Parent Parent { get; set; }
        public virtual string Name { get; set; }
    }

Mappings:

  <class name="TestNHJoin.Parent, TestNHJoin" table="Parent">
    <id name="Id" type="System.Int32" column="Id" unsaved-value="0">
      <generator class="hilo">
        <param name="table">hibernate_unique_key</param>
        <param name="column">next_hi</param>
        <param name="max_lo">1</param>
      </generator>
    </id>
    <property name="Name" type="System.String" />

    <bag name="Versions" cascade="save-update">
      <key>
        <column name="ParentId" not-null="true" />
      </key>
      <one-to-many class="TestNHJoin.ParentVersion, TestNHJoin" />
    </bag>

  </class>

  <class name="TestNHJoin.ParentVersion, TestNHJoin" table="ParentVersion">
    <id name="Id" type="System.Int32" column="Id" unsaved-value="0">
      <generator class="hilo">
        <param name="table">hibernate_unique_key</param>
        <param name="column">next_hi</param>
        <param name="max_lo">1</param>
      </generator>
    </id>

    <many-to-one name="Parent" class="TestNHJoin.Parent, TestNHJoin">
      <column name="ParentId" not-null="false" />
    </many-to-one>

    <property name="Address" type="System.String" />

    <bag name="Associations" table="ParentVersionAssociations"
cascade="all">
      <key column="ParentVersionId" />
      <many-to-many class="TestNHJoin.Association, TestNHJoin"
column="AssociationId" />
    </bag>

  </class>

  <class name="TestNHJoin.Association, TestNHJoin" table="Association">
    <id name="Id" type="System.Int32" column="Id" unsaved-value="0">
      <generator class="hilo">
        <param name="table">hibernate_unique_key</param>
        <param name="column">next_hi</param>
        <param name="max_lo">1</param>
      </generator>
    </id>
    <property name="Name" type="System.String" />

    <many-to-one name="Parent" class="TestNHJoin.Parent, TestNHJoin">
      <column name="ParentId" not-null="false" />
    </many-to-one>

  </class>


Simple test:
       public void SaveParent()
        {

            using (ISession session = _factory.OpenSession())
            {
                Parent parent;
                Association association1 = new Association();
                association1.Name = "Assoc1";
                Association association2 = new Association();
                association2.Name = "Assoc2";

                parent = new Parent();
                parent.Name = "Test";

                ParentVersion version1 = new ParentVersion();
                version1.Address = "1st Address";
                version1.Parent = parent;
                version1.Associations.Add(association1);
                version1.Associations.Add(association2);
                parent.Versions.Add(version1);

                session.Save(parent);
                session.Flush();
            }
            ISession session = _factory.OpenSession();
            Parent parent = session.CreateCriteria(typeof(Parent))
                .CreateAlias("Versions", "version", JoinType.LeftOuterJoin)
                .CreateAlias("version.Associations", "association",
JoinType.LeftOuterJoin)
                .SetResultTransformer(new
DistinctRootEntityResultTransformer())
                .Add(Restrictions.IdEq(id))
                .UniqueResult<Parent>();

            Assert.AreEqual(1, parent.Versions.Count);
        }

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"nhusers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/nhusers?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to