http://stackoverflow.com/questions/9042078/how-can-you-avoid-nhibernate-n1-with-composite-key

On Feb 15, 6:03 pm, Brad Laney <[email protected]> wrote:
> I'll zip and upload a full working project to show you that it doesn't
> work.
>
> On Feb 9, 11:47 am, Boris Drajer <[email protected]> wrote:
>
>
>
>
>
>
>
> > Hi,
>
> > There could be something else, then, that causes the problem... The
> > method works, I've been using it for years. Here's a couple of links,
> > this is where I got it from, maybe you'll find something I forgot to
> > mention:
>
> >http://www.ayende.com/Blog/archive/2007/06/20/Efficently-loading-deep...
>
> > (I can't reach Ayende's blog currently, but this page is available on
> > the wayback machine...)
>
> > BTW, in the latest NHibernate (3.2.0) I've been having trouble with
> > MultiQuery and Future (although they threw exceptions instead of just
> > not doing anything), it may be good to try to get things working
> > without them and go back only after everything else is performing
> > correctly.
>
> > Best regards!
>
> > On 8 феб, 17:29, Brad Laney <[email protected]> wrote:
>
> > > @boris
>
> > > I have tried what you said and it doesn't work, at all.
> > > 1) When I inner join the collections arn't loaded into the lists, it
> > > just ignores the data
> > > 2) When I run those 3 queries in a futures, it also does nothing. It
> > > populates no lists except for B inside A.
>
> > > On Feb 8, 6:13 am, Boris Drajer <[email protected]> wrote:
>
> > > > Hi Brad,
>
> > > > (Sorry for the late answer)
>
> > > > You don't have to do a full cartesian product and you don't really
> > > > have to use left join fetch... You can do something like
>
> > > > from A inner join fetch A.B where A = something
> > > > from B inner join fetch B.C where B.A = something
> > > > from C inner join fetch C.D where C.B.A = something
>
> > > > If you execute each of the three queries separately, you'l retrieve B
> > > > + C + D number of rows and still have all collections loaded.
>
> > > > The difference between left join fetch and inner join fetch is that
> > > > empty collections don't get initialized with inner, while they do with
> > > > left. For example, with
>
> > > > from A inner join fetch A.B where A = something
>
> > > > A's with no B's don't appear in query results at all and their A.B
> > > > collections remain uninitialized, which produces the lazy
> > > > initialization exception when they are accessed. If this isn't a
> > > > problem for you, then inner join is indeed a better solution.
>
> > > > Best regards!
>
> > > > On 2 феб, 17:32, Brad Laney <[email protected]> wrote:
>
> > > > > Hey,
>
> > > > > I understand that is how NH works, but you need to understand I don't
> > > > > want to do a Cartesian join for this.
>
> > > > > I have A -> B -> C -> D
>
> > > > > If I want D populated then i will be selecting the entire contents of
> > > > > A, like, 40 times.
>
> > > > > I understand it needs to know the link. And I understand I can use
> > > > > futures to efficiently populate one level deep.
> > > > > What I want is an efficient way to populate 4 levels deep, just like I
> > > > > could with TSQL then join them together at the end.
>
> > > > > I do not care the method, or technique to doing this. I just need an
> > > > > object so that my DBA does not tell me I am bringing down the server
> > > > > by having a high visited page run 500 queries every time it runs.
>
> > > > > Doing this is not an acceptable solution, specially since it requires
> > > > > left outer join:
>
> > > > > from A left outer join fetch A.B left outer join fetch B.C left outer
> > > > > join fetch C.D
>
> > > > > On Feb 2, 6:15 am, Boris Drajer <[email protected]> wrote:
>
> > > > > > Hi,
>
> > > > > > Sorry if I misunderstand, but it seems to me that the crucial point
> > > > > > you're missing is that it's not enough to load the contents of the
> > > > > > collections, NHibernate needs to load the collection as a part of 
> > > > > > its
> > > > > > owner. If you retrieve individual objects, they will all be present 
> > > > > > in
> > > > > > the session but the collections that contain them will remain
> > > > > > uninitialized. When you access such collections, NHibernate 
> > > > > > executes a
> > > > > > query and then for each row retrieved discovers that it's already
> > > > > > cached in the session, so it only adds it to the collection. What 
> > > > > > you
> > > > > > need to do is to load them *together*. This is best illustrated with
> > > > > > HQL:
>
> > > > > > from A a left join fetch a.Bs where [something]
>
> > > > > > This loads the A's along with their collections of B's, not just A's
> > > > > > and B's separately.
>
> > > > > > With QueryOver, I think it would look something like this:
>
> > > > > > var q = session.QueryOver<A>().Fetch(a =>
> > > > > > a.Bs).Eager.Where([something]);
>
> > > > > > You can execute multiple different queries of this sort to load
> > > > > > different portions of the object graph.
>
> > > > > > HTH!
>
> > > > > > On 30 јан, 21:54, Brad Laney <[email protected]> wrote:
>
> > > > > > > This relationship goes 4 deep. When it does lazy loading it ends 
> > > > > > > up
> > > > > > > running like 500+ queries.
> > > > > > > This job can easily be done in 4 queries, and then the content
> > > > > > > aggregated.
> > > > > > > I have not touched batch size, because its already set, and the 
> > > > > > > number
> > > > > > > of records coming back is not the issue.
> > > > > > > I have tried fetch but then you end up returning large amounts of
> > > > > > > unnecessary data, which is why I want to use futures.
> > > > > > > This is supposed work. It's documented as how it works. I just 
> > > > > > > don't
> > > > > > > know how to get it to do join type select with QueryOver.
> > > > > > > I'm going to try it with the criteria API.
>
> > > > > > > .SetFetchMode("Items", FetchMode.Select) <-- this is pretty much 
> > > > > > > what
> > > > > > > I want.
>
> > > > > > > What is subselect fetching?
>
> > > > > > > Is there a way to fetch an entire list of data, instead of one at 
> > > > > > > a
> > > > > > > time?
> > > > > > > x.Items.Items <-- I want to fill every single item inside that
> > > > > > > collection in one sql call instead of it lazy loading each one 
> > > > > > > that I
> > > > > > > want.
>
> > > > > > > What I want it to run is:
>
> > > > > > > select A.* from A where A.id = ?
> > > > > > > select B.* from B where B.aid = ?
> > > > > > > select C.* from C left join B where B.aid = ?
> > > > > > > select D.* from D left join C left join B where b.aid = ?
>
> > > > > > > I don't mind joining up to A instead of B. But yeah. Also notice I
> > > > > > > don't want every single column, because that's pointless.
>
> > > > > > > On Jan 30, 1:44 pm, Oskar Berggren <[email protected]> 
> > > > > > > wrote:
>
> > > > > > > > 2012/1/30 Brad Laney <[email protected]>:
>
> > > > > > > > > Hello.
>
> > > > > > > > > I am trying to avoid N+1 and cartesian product when I need to 
> > > > > > > > > do deep
> > > > > > > > > eager loads. I want to do this for performance. It is an EAV 
> > > > > > > > > type of a
> > > > > > > > > data structure.
>
> > > > > > > > Is the problem too many queries, or that you absolutely cannot 
> > > > > > > > have
> > > > > > > > more than one roundtrip to the database?
>
> > > > > > > > [...]
>
> > > > > > > > >                var r = s.QueryOver<NHMapTest1>()
> > > > > > > > >                    .Where(x => x.Id == id)
> > > > > > > > >                    .Future();
>
> > > > > > > > >                s.QueryOver<NHMapTest2>()
> > > > > > > > >                    .Where(x => x.Parent.Id == id)
> > > > > > > > >                    .Future();
> > > > > > > > > Running r.Single(); returns the entity, but if you do .Items 
> > > > > > > > > it'll
> > > > > > > > > query the DB, even tho they were selected in the 2nd future. 
> > > > > > > > > Both
> > > > > > > > > queries run correctly and return valid results.
>
> > > > > > > > When you access the collection, even though a number of objects 
> > > > > > > > of the
> > > > > > > > collection's member type has been loaded, NH doesn't know they 
> > > > > > > > are
> > > > > > > > part of the collection, that's why it needs to query again. 
> > > > > > > > Looking at
> > > > > > > > the child's Parent reference of loaded objects wouldn't be 
> > > > > > > > enough,
> > > > > > > > since it doesn't know if those are _all_ the children.
>
> > > > > > > > Have you set proper batch size on your collections and classes? 
> > > > > > > > And
> > > > > > > > possibly specify subselect fetching for the collections. With 
> > > > > > > > that you
> > > > > > > > should be able to rely on lazy fetch, but with a limited number 
> > > > > > > > of
> > > > > > > > round trips.
>
> > > > > > > > /Oskar

-- 
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