tags:

views:

1384

answers:

3

I have two tables:

SupportTicket

SupportTicketID
SupportTicketDate

SupportTicketNote

SupportTicketNoteID
SupportTicketNoteDate
SupportTicketID

With a foreign key constraint so I don't have any unassociated Notes...in sql that constraint is working properly.

On my SupportTicket class I have an IList SupportTicketNotes property and have it mapped as a bag (probably really should be a set but that's not important at the moment). The load works just fine. The problem is if I new up a SupportTicket, new up a SupportTicketNote, add the note to the ticket and save the ticket. NHibernate is inserting the SupportTicket, then inserting the SupportTicketNote with a SupportTicketID of zero which blows up of course because of the FK constraint. If I delete the constraint it will insert with the SupportTicketID of zero and then go back and do an update on the SupportTicketNote with the proper ID value...but that seems....wrong. Is there anything I might be doing in the mapping that is causing that?

UPDATED to include Many to One mapping on child object

Here's my current mapping for SupportTicket:

<bag name="_supportTicketNotes" table="SupportTicketNotes" access="field" cascade="save-update" inverse="true" >
  <key column="SupportTicketID" foreign-key="FK_SupportTicketNotes_supporttickets" ></key>
  <one-to-many class="NhibernateSample.DomainModel.SupportTicketNote, NhibernateSample.DomainModel" />
</bag>

Here is my mapping for SupportTicketNote (note my SupportTicketNote class has both the SupportTicketID and SupportTicket object properties):

 <many-to-one name="SupportTicket"   class="NhibernateSample.DomainModel.SupportTicket, NhibernateSample.DomainModel"   column="SupportTicketId" cascade="all"/>
A: 

You'll need to write your function in such a way that the persistance of the New SupportTicket happens prior to you adding the SupportTicketNote

e.g.

SupportTicket st = new SupportTicket();
SupportTicketNote stn = new SupportTicketNote();

///Code to set properties on both objects

st.Save();
st.SupportTicketNotes.Add(stn);
st.Save();
Eoin Campbell
Yeah...that's what I'm doing.
Webjedi
Downvoted because one of the principal benefits of NHibernate is that you don't have to worry about operation order. If your domain model is mapped correctly NHibernate takes care of this for you.
Jamie Ide
+1  A: 

I haven't seen your full mapping, but the first thing that pops into my head is this section from the documentation:

Very Important Note: If the <key> column of a <one-to-many> association is declared NOT NULL, NHibernate may cause constraint violations when it creates or updates the association. To prevent this problem, you must use a bidirectional association with the many valued end (the set or bag) marked as inverse="true". See the discussion of bidirectional associations later in this chapter.

Stuart Childs
I updated the question with the child object mapping...still having the same challenge...Nhibernate is inserting a 0 in the constrained column and then running an update to set the the zero to the proper parent id....ugh.
Webjedi
See Jamie's answer for the necessary property of bidirectional. Making sure the parent property SupportTicket mapped on SupportTicketNote is one half of the bidirectional association.
Stuart Childs
I think the problem is the one-to-one. For bidirectional mapping to work it has to be many-to-one (AFAIK).
Stuart Childs
+1  A: 

How have you mapped the parent SupportTicket property on SupportTicketNote? Are you setting the SupportTicket property when you add a SupportTicketNote to the collection? I almost always follow this pattern:

public class SupportTicket
{
    private IEnumerable<SupportTicketNote> _notes = new List<SupportTicketNote>();

    public IEnumerable<SupportTicketNote> Notes
    {
        get { return _notes; }
    }

    public void AddNote(SupportTicketNote note)
    {
        note.SupportTicket = this;
        _notes.Add(note)
    }

    public void RemoveNote(SupportTicketNote note)
    {
        note.SupportTicket = null;
        _notes.Remove(note)
    }
}

Edited to add: Your mapping for SupportTicketNote looks wrong. It should be many-to-one to SupportTicket and you shouldn't be mapping SupportTicketId at all. I've been using Fluent NHibernate for a while but I think the XML mapping should look like:

<many-to-one name="SupportTicket"
   class="NhibernateSample.DomainModel.SupportTicket, NhibernateSample.DomainModel"
   column="SupportTicketId" cascade="all"/>
Jamie Ide
Thanks for hanging in there with me. Ok so now we're closer...now I'm recieving an error regarding trying to insert null into the SupportTicketID column (the FK constrained column) on the SupportTicketNote table.
Webjedi
Are you setting the SupportTicket property when you add a SupportTicketNote to the collection. It would help if you posted the code for this.
Jamie Ide
That was it...I just figured it out and saw you posted it...I figured that NHibernate would know that the unsaved support ticket would automatically have to be the parent if I had added the note as a child...guess I have to learn to be a little more explicit when doing those types of relationships....next up using NHibernate to store images in the database...wish me luck!
Webjedi