views:

212

answers:

1

Consider the following Class structure...

public class ListViewControl
{
    public int SystemId {get; set;}
    public List<ControlAction> Actions {get; set;}
    public List<ControlAction> ListViewActions {get; set;}
}

public class ControlAction
{
    public string blahBlah {get; set;}
}

I want to load class ListViewControl eagerly using NHibernate. The mapping using Fluent is as shown below

public UIControlMap()
    {
        Id(x => x.SystemId);
        HasMany(x => x.Actions)
            .KeyColumn("ActionId")
            .Cascade.AllDeleteOrphan()
            .AsBag()
            .Cache.ReadWrite().IncludeAll();
        HasMany(x => x.ListViewActions)
            .KeyColumn("ListViewActionId")
            .Cascade.AllDeleteOrphan()
            .AsBag()
            .Cache.ReadWrite().IncludeAll();
    }

This is how I am trying to load it eagerly

var baseActions = DetachedCriteria.For<ListViewControl>()
            .CreateCriteria("Actions", JoinType.InnerJoin)                
            .SetFetchMode("BlahBlah", FetchMode.Eager)
            .SetResultTransformer(new DistinctRootEntityResultTransformer());

var listViewActions = DetachedCriteria.For<ListViewControl>()
            .CreateCriteria("ListViewActions", JoinType.InnerJoin)
            .SetFetchMode("BlahBlah", FetchMode.Eager)
            .SetResultTransformer(new DistinctRootEntityResultTransformer());

var listViews = DetachedCriteria.For<ListViewControl>()
            .SetFetchMode("Actions", FetchMode.Eager)
            .SetFetchMode("ListViewActions",FetchMode.Eager)
            .SetResultTransformer(new DistinctRootEntityResultTransformer());

var result = _session.CreateMultiCriteria()
                .Add("listViewActions", listViewActions)
                .Add("baseActions", baseActions)
                .Add("listViews", listViews)
                .SetResultTransformer(new DistinctRootEntityResultTransformer())
                .GetResult("listViews");

Now, my problem is that the class ListViewControl get the correct records in both Actions and ListViewActions, but there are multiple entries of the same record. The number of records is equal to the number of joins made to the ControlAction table, in this case two.

How can I avoid this? If I remove the SetFetchMode from the listViews query, the actions are loaded lazily through a proxy which I don't want.

I also tried creating aliases ...

.SetFetchMode("Actions", FetchMode.Eager)
.CreateAlias("Actions","actions",JoinType.RightOuterJoin)
.SetFetchMode("ListViewActions",FetchMode.Eager)
.CreateAlias("ListViewActions", "liactions", JoinType.RightOuterJoin)

This removed the duplicate entries, but did not eagerly load

A: 

That's an extremely inefficient way to eager load collections. Here's a better way:

http://ayende.com/Blog/archive/2010/01/16/eagerly-loading-entity-associations-efficiently-with-nhibernate.aspx

Diego Mijelshon
I thought I was using the same mechanism... http://blogs.hibernatingrhinos.com/nhibernate/archive/2008/04/06/eager-loading-aggregate-with-many-child-collections.aspxThe URL you provided and the one I gave load collections for a single entity object. I want to retrieve all objects.Have a look at this URL as wellhttp://stackoverflow.com/questions/2839357/load-collections-eagerly-in-nhibernate-using-criteria-api
Zuber