Domanda

All,

I have an entity, that has several collections,- each collection is mapped lazily. When I run a criteria query, I get duplicate results for my root entity in the result set. How's that possible when all my collections are mapped lazily!

I verified, my collections, load lazily.

Here's my mapping:

Root entity 'Project':

[Bag(0, Lazy = CollectionLazy.True, Inverse = true, Cascade = "all-delete-orphan")]
    [Key(1, Column = "job_id")]
    [OneToMany(2, ClassType = typeof(ProjectPlan))]
    public virtual IList<ProjectPlan> PlanList
    {
        get { return _planList; }
        set { _planList = value; }
    }

The criteria query is:

    ICriteria criteria = session.Session.CreateCriteria<Entities.Project>()
                    .Add(Restrictions.Eq(Entities.Project.PROP_STATUS, !Entities.Project.STATUS_DELETED_FLAG));
                    .CreateAlias(Entities.Project.PROP_PLANLIST, "p")
                    .Add(Restrictions.Eq("p.County", 'MIDDLSEX'))
.setFirstResult(start).setMaxResults(pageSize)
                    .List<Entities.Project>();

I know, I can correct this problem w/ Distinct result transformer, I just want to know if this is normal behavior on lazy collections.

EDIT: I found the cause of this,- when looking at the raw SQL, the join, and where clause are correct but what baffles me is the generated Select clause,- it not only contains columns from the project entity (root entity) but also columns from the project plans entity which causes the issue I described above. I am not at work right now, but I'll try to do this: .SetProjection(Projections.RootEntity()), so I only get Project's columns in the select clause.

È stato utile?

Soluzione

One way, how to solve this (I'd say so usual scenario) is: 1) not use fetching collections inside of the query and 2) use batch fetching, as a part of the mapping

So, we will always be querying the root entity. That will give us a flat result set, which can be correctly used for paging.

To get the collection data for each recieved row, and to avoid 1 + N issue (goign for collection of each record) we will use 19.1.5. Using batch fetching

The mapping would be like this

[Bag(0, Lazy = CollectionLazy.True
      , Inverse = true
      , Cascade = "all-delete-orphan"
      , BatchSize = 25)] // Or something similar to batch-size="25"
[Key(1, Column = "job_id")]
[OneToMany(2, ClassType = typeof(ProjectPlan))]
public virtual IList<ProjectPlan> PlanList
{
   ...

Some other similar QA (with the almost same details)

And we still can filter over the collection items! but we have to use subqueries, an example Query on HasMany reference

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top