Forgot to add the sometimes the best thing is to forego mapping the
collection altogether and access the children or the many using a
query instead.

So your parent object will have no Children property which returns the
list of children.

instead what you will have is a query. Something like
IList<Child> getChildrenForParent(Parent parent)
{
    var session = ....;
    return session.CreateCriteria<Child>()..........;
}


On Feb 10, 12:50 am, JideO <[email protected]> wrote:
> You're not crazy for seeing the inconsistency. Unfortunately casual
> conversation like this is dogged with this kind of inconsistency.
>
> First with regards to having to load the entire object graph before
> before adding a single note, nhibernate provides a Session.Load(id)
> method which doesn't actually issue any queries as opposed to
> Session.Get(id). Session'Load just creates a proxy which can be used
> for creating the associations required.
>
> var parent = Session.Load<Parent>(parentId);
> var child = new Child();
> child.Parent = parent;
>
> The example I showed just exposed the internals of what would be going
> on to establish a bi-directional relationship.
>
> parent.AddChild(child);
> child.Parent = parent;
>
> You should probably encapsulate this two step activity in a single
> helper method on one of the objects that establishes both
> associations.
>
> You also mentioned that you had seen in most examples that
> child.Parent must be set. Yes this is true but it is a side effect of
> using the inverse=true attribute on the collection mapping in the
> parent. As you know in Nhibernate one of the ends of a bidirectional
> association must be chosen as the owner/manager of the relationship.
> If not nhibernate will do two updates of the entity (I think it will
> do one insert & one update) for each entity you add to the collection.
> So one end opts out of managing the association by indicating it is
> the inverse. The inverse is usually on the collection mapping (bag,
> etc)
>
> As a result adding the child to the parent is not required for
> nhibernate to correctly insert the newly created object into the db.
> All that is required is just
>
> child.Parent = parent.
>
> but then you'll have to manually save the newly created child with
> session.Save(child); Next time you load the parent from the database
> the new child will appear in its children collection.
> Parent.AddChild(child) is done for two reasons
> 1. to ensure in-memory consistency.
> 2. so you don't have to manually do session.Save(child). Instead you
> set cascade=save...etc and nhibernate will follow all cascaded
> associations of any persistent entity and ensure any newly attached or
> updated object it finds is saved as well. cascade=delete-orphan will
> also ensure that objects that are removed from a persistent objects
> collection when it was fetched will be deleted.
>
> I think this also addresses the other issue you raised about loading
> the entire collection of a parent before you can add an item to it.
> Nhibernate collections can be mapped as Set, List, Bag, Idbag etc.
> Nhibernate will load entire collections mapped with Set or List as
> soon as they are accessed so it can maintain their invariants of
> uniqueness for set & order for list. Bag on the other hand which
> allows duplicate items does not require the loading the entire
> collection before you can add to it. I'm not sure if this is standard
> or you have to use lazy="extra" or some other thing but it does exist.
>
> So you can probably do something like
>
> parent = Session.Load<ParentClass>(parentid);
> parent.children.add(child);
>
> without triggering a load of the entire parents children collection.
>
> As you can see I'm basically just running through the issues you've
> raised and writing out what I can remember about it. This kind of
> rambling behaviour inevitably leads to the inconsistency you earlier
> observed.
>
> Let me add that although your questions seem very simple they are very
> fundamental questions that everyone learning to use nhibernate
> encounters from time to time. Usually what I do then is study the
> options and decide on some "compromise" strategy for handing the issue
> or standardise on some conventions that avoid some of these difficult
> areas (like not trying to do one-to-one associations), then I happily
> forget the reason I arrived at the strategy. That is, until you come
> along asking questions and I'm left scratching my head trying to
> remember why I just use bag mapping and not bother with other exotic
> mapping until absolutely necessary.
>
> Once again I'm sure I left a lot out but I just hope it helps.
>
> Jide Ogundipe
>
> On Feb 9, 4:56 pm, Joe Brockhaus <[email protected]> wrote:
>
>
>
> > Thanks for your reply.
>
> > A lot of the frustration has been because of the direction of the advice.
> > i.e. from a database-to-purist Object model POV. that was further
> > complicated by perhaps my failure to elaborate on the specific requirements
> > that RIA brought to the table (which i knew were not that big of a deal, but
> > something i just had to work around). only after repeated attempts did i
> > become terse. I had constantly affirmed my understanding that i _didn't
> > need_ the FK, and was understandably frustrated by the response of no
> > instead of why not.
>
> > anyway ..
>
> > In short, cascade settings mean that I MUST *always* act (CUD) on items in
> > collections through the parent?
> > -- if my client-side code is optimized NOT to send the entire entity graph
> > back over the wire to add a single, new Note, in order to save that note to
> > the database, i MUST re-build that entity graph from either the session or
> > the database, then save the parent?
>
> > in your example:
>
> >    parent.addChild(child);             // or
> >    parent.children.add(child);
> >    child.Parent = parent;              // for bidirectionality
>
> > was it your intention to imply that the method addChild() MIGHT NOT be
> > setting child.Parent, and might only be adding the child to the collection?
> > In my experience, and based on what everyone here has already said about
> > object references not key associations, child.Parent is required to be set.
> > Or is the rule more like: it either has to be set, or be in a collection of
> > a parent, and NHib will set it for me? Your 'for bidirectionality' leads me
> > to believe the rule is not like that (it's optional) -- so why would I get
> > errors if i DON'T set child.Parent?
>
> > ----> just FYI :: Here's a very good example of a great clearly-explained
> > response not being consistent, even though it's very clear. I'm not crazy
> > for seeing the inconsistency, am I? Without the above being clarified, it's
> > very hard to move forward from this foundation of understanding. Er, it's
> > hard for 2 people to move forward toward common understanding with such
> > uncertainty looming in the shadows.
>
> > Nonetheless, I'll keep going. I understand where the disconnection is, I
> > just need answers to clear them up. :D
>
> > -- Perhaps now would be a good time to note that what I suggested
> > originally, did actually work... That's not to say that I'm out of the
> > woods, and it's only because i'm doing explicit stuff that I'd like to not
> > have to do, like build up the entire entity graph just to add a single Note.
>
> > in case you're all wondering ... the below mapping works as desired:
> > public class TicketMap : ClassMap<Ticket>
> > { public TicketMap() {
> >     Not.LazyLoad()
> >     Table("Tickets")
> >     Id(x=>x.TicketID).GeneratedBy.Sequence("SEQ_TICKET_ID")
>
> >     HasMany<Note>(x=> x.Notes)
> >     .KeyColumn("TicketID")
> >     .Cascade.SaveUpdate()}}
>
> > public class NoteMap : ClassMap<Note>
> > { public NoteMap() {
> >     Not.LazyLoad()
> >     Table("Notes")
> >     Id(x=>x.NoteID).GeneratedBy.Sequence("SEQ_NOTE_ID")
>
> >     HasMany<Note>(x=> x.Notes)
> >     .KeyColumn("TicketID")
> >     .Cascade.SaveUpdate()
>
> >     Map(x => x.TicketID)
> >     .Not.Insert()
> >     .Not.Update()
> >     .Generated.Always()
>
> > }}
>
> > In order to map the FK column (TicketID) AND the instance (Ticket), AND ALSO
> > make it work for both read and write, I was doing it backwards. That is, I
> > was misunderstanding the *magic* NHib was doing to populate TicketID in my
> > domain, but then was frustrated that it couldn't save it to the database
> > (the logs indicated TicketID was resolved, but then oracle was saying
> > couldn't insert null). I was trying to map Ticket as not-insert/update, and
> > have NHib map TicketID. I was also originally just trying to save a single
> > Note by itself with
> > Session.Save(newNote_WithEverythingTheDatabaseTableNeedsButNoTicketInstance­­).
>
> > -- Perhaps this is the question I should ask more directly: I would like to
> > be able to save an individual note without populating Ticket or without
> > building out the entire graph of the parent, BUT ALSO be able to save the
> > entire entity graph like Session.Save(newTicket_WithNewNotesAlso), because
> > there are scenarios where I will have that as well. Is that possible?
>
> > It should now be clear why I need to understand if setting the note.Ticket
> > instance is a requirement, and if so, when?
>
> > BTW, after all hell broke loose and assuming I ever got this resolved, I was
> > going to offer $10 to whomever decided to actually help. Of course I
> > couldn't say that before, but JideO and John Davidson will get it, if that's
> > good enough , for actually trying to help. Sometimes it pays to not be a
> > parrot on repeat =)
>
> > Thanks
>
> > ------
> > Joe Brockhaus
> > [email protected]
> > ------------
>
> > On Mon, Feb 7, 2011 at 7:08 PM, JideO <[email protected]> wrote:
> > > I think a little empathy for Joe's frustration is in order. Joe I
> > > think you should appologise to people you would have offended by
> > > taking out your frustration on them.
>
> > > I have also been on the receiving end of what initially seem to be
> > > unhelpful answers but later on when I understood the issues better, I
> > > find that one of the replies I had been frustrated with already
> > > contained the answer to my question.
>
> > > Even at this, there are still some questions I have on nhibernate and
> > > on other forums where I have given up on getting a direct answer
> > > saying "this is so and so" or "this was not designed to be used like
> > > so try using it like so" or even "you idiot, what were you thinking,
> > > that's not
>
> ...
>
> read more »- Hide quoted text -
>
> - Show quoted text -

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