views:

63

answers:

3

I'm having trouble saving a many-to-many relationship with nhibernate. I searched and looked at almost every same question in SO and google but nothing works. The single classes are update correctly but nothing is inserted in the join-table.

I have 2 classes: Event and Category.

The mapping is this (I updated the two mapping and added some code):

Event:

<bag name="Categories" access="field.camelcase-underscore" table="EventCategories" cascade="all-delete-orphan" lazy="true">
  <key column="Event"/>
  <many-to-many class="Category" column="Category"/>
</bag> 

Category:

<bag name="Events" table="EventCategories" access="field.camelcase-underscore"  inverse="true" cascade="all-delete-orphan"  lazy="true" >
  <key column="Category"/>
  <many-to-many class="Event" column="Event"/>
</bag>

The code who generate the Event+Categories is

public void AddEvent(EventInputModel model)
    {
        var rawCategories = model.Categories.Split(',');
        IEnumerable<Category> categories = _repository.GetCategories(rawCategories);

        foreach (var category in rawCategories)
        {
            var c = categories.Where(p => p.Name.ToLower().Equals(category));
            if (c.Any())
            {
                model.Event.AddCategory(c.First<Category>());
            }
            else
            {
                model.Event.AddCategory(new Category() { Name = category });
            }
        }

        _repository.Save(model.Event);

    }

 public void Save(Event p)
    {
        using (var t = Session.BeginTransaction())
        {
            Session.SaveOrUpdate(p);
            t.Commit();
        }
    }

I tried to swap every parameter in both mappings but nothing works...

Do you know what I'm doing wrong or have a right mapping for this case?

Thank you very much!

+1  A: 

The following code should save correctly:

using (var tx = session.BeginTransaction())
{
    var category = new Category { Events = new List<Event> { new Event() } };
    session.Save(category);
    tx.Commit();
}

In this case I'm saving a new Category with a new Event, but using existing ones should also work.

It's important to note that the exact opposite of the code I wrote (an Event with a collection containing a new Category) would not save the relationship because of the Inverse.

Diego Mijelshon
@Diego I updated the mapping swapping the inverse. Your example does not work anyway :(
Davide Vosti
I tested my code here and it works as expected. What's your FlushMode? How is the Event loaded? What's the code for AddCategory? Have you verified (using a debugger) that the event contains the expected categories when the repository method is called?
Diego Mijelshon
A: 

You should make all changes to the entities incide a single transaction. You should begin it just before getting categories.

Sly
A: 

So. I don't know what's exactly but I got this working. After trying different configurations I got the right one and I'm posting the entire code here.

The mapping in the Event class is:

<bag name="Categories" access="field.camelcase-underscore" table="EventCategories" cascade="all-delete-orphan"  lazy="true">
  <key column="Event"/>
  <many-to-many class="Category" column="Category"/>
</bag>

For Category is:

<bag name="Events" table="EventCategories" access="field.camelcase-underscore" inverse="true" cascade="all-delete-orphan" lazy="true" >
  <key column="Category"/>
  <many-to-many class="Event" column="Event"/>
</bag>

The code who save to db is simply:

 Session.SaveOrUpdate(p);
 Session.Flush();

No transaction is needed. It works.

Davide Vosti