简体   繁体   中英

Nhibernate mapping / design issue

This issue is either due my poor project design, my lack of knowledge of how to use nhibernate, or both (just a note, I blame nhibernate for my poor project design). Here it is:

In my domain model, I have the following (I've cut out a lot of excess to keep things simple):

An Event object:

public class EventBO 
{

    public int ID { get; set; }

    public String Name
    {
        get;
        set;
    }

    private List<InviteeBO> _invitees = null;

    public List<InviteeBO> Invitees
    {
        get { return _invitees; }
        set { _invitees = value; }
    }
}

And an Invitee Object:

public class InviteeBO 
{

    public int ID { get; set; }

    public String Name
    {
        get;
        set;
    }

    private List<InviteeBO> _invitees = null;

    public List<InviteeBO> Invitees
    {
        get { return _invitees; }
        set { _invitees = value; }
    }

    private EventBO theEvent;

    public EventBO TheEvent
    {
        get { return theEvent; }
        set { theEvent = value; }
    }

    private InviteeBO invitedByUser = null;

    public InviteeBO InvitedByUser
    {
        get { return invitedByUser; }
        set { invitedByUser = value; }
    }
}

When an event is created, the person who creates it is automatically added to the Event.Invitees list. That same person can then add an unlimited amount of invitees, which are then added to the Invitees list within the Invitee object that was just added to the Event. The reason for this is because I need to keep track not only of who was added to the event, but also of who added whom.

My issue is this: When I save an event, the EventID is added to the respective column in the db for each Invitee present in the Event's Invitees list (in the Invitees db table). In addition, if an Invitee within that Event.Invitees list invites friends (and therefore adds invitees to it's own respective Invitee.Invitees list), saving an event will properly write the InviteeID of the Invitee who did the inviting to all Invitees he invited (also in the Invitee db table). THE PROBLEM: The EventID is not added to the child Invitees of all Invitees in the Event.Invitees list.

God... I'm doing a terrible job of explaining this, and I apologize. I can provide unlimited details here, but I don't want to overload this post. Please tell me if you need anything else to help me solve this problem.

Regardless, here are the relevant portions of the Event and Invitee mapping files:

Event.hbm.xml:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="DAL"
                   namespace="DAL.DAO.Entities">
  <class name="EventDO" table="Events">
    <id name="ID">
      <column name="ID"/>
      <generator class="native" />
    </id>
    <property name="Name">
      <column name="Name"/>
    </property>
    <property name="Description">
      <column name="Description"/>
    </property>    
    <bag name="Invitees" table="Invitees" inverse="false" cascade="all" lazy="false" >
      <key column="EventID"/>
      <one-to-many class="InviteeDO" />
    </bag>

  </class>
</hibernate-mapping>

Invitee.hbm.xml:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="DAL" namespace="DAL.DAO.Entities" >
  <class name="InviteeDO" table="Invitees">
    <id name="ID">
      <generator class="identity"/>
    </id>
      <property name="FullName"/>
      <many-to-one name="TheEvent"  cascade="none" column="EventID" lazy="false" />
      <bag name="Contacts" table="Contacts" inverse="false" cascade="all" lazy="false" >
        <key column="ContactOfUserID"/>
        <one-to-many class="ContactDO" />
      </bag>
      <bag name="Invitees" table="Invitees" inverse="false" cascade="save-update" lazy="false" >
        <key column="InvitedByID" />
        <one-to-many class="InviteeDO"/>
      </bag>
      <property name="IsOrganizer"/>
      <property name="IsCreator"/>


  </class>
</hibernate-mapping>

UPDATE @Roberto Hernandez - First, thank you for responding. I really, really appreciate it.

Second, took your lead and ran a test using only my DAL and DOs, and it worked. So clearly there's something wrong with the functions that convert my DOs to BOs.

There's also something else I did wrong, that you pointed out. I had added the child invitee to the parent invitee, and the parent invitee to the event.Invitees. I then presumed that saving the event would then perform all the necessary persistence, including for the child invitees. Clearly I was wrong, and I needed to also add the parentInvitee to the child, and the child to the Event.Invitees. Thanks!

I don't think there is anything particularly wrong with the code you have outlined above, I mean there are some possible improvements, but I think you are mainly assuming NHibernate will do more that is currently doing for you. I built an app using your code and mappings and everything works as expected as long as I set the properties explicitly that you have mentioned above. The following is the snippet.

// This is my SessionFactory (Not Relevant!)
using (var session = NhSessionFactory.GetSession(generatedatabase: false))
{
using (var tran = session.BeginTransaction())
{
    var theEvent = new EventBO();
    theEvent.Name = "EventName";

    var parentInvitee = new InviteeBO();
    parentInvitee.Name = "Parent";
    theEvent.Invitees.Add(parentInvitee);

    for (int index = 0; index <= 5; index++)
    {
        var childInvitee = new InviteeBO();
        childInvitee.Name = string.Format("Child {0}", index);
        childInvitee.InvitedByUser = parentInvitee;  // Adding invited by user.

        parentInvitee.Invitees.Add(childInvitee);
        theEvent.Invitees.Add(childInvitee);   // Adding child invitees to Event.
    }

    session.SaveOrUpdate(theEvent);
    tran.Commit();
}
}

While the code above works, I would recommend refactoring all this into your BO objects. For example adding an AddInvitee method to the Event class that handles the setting of the properties in the child object.

WARNING: You seem to have a mapping layer you are not showing us that handles mapping from BO to DO I answered the best way I could without knowing what you have in that layer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM