Reputation: 2485
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!
Upvotes: 0
Views: 1706
Reputation: 2485
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.
Upvotes: 0
Reputation: 15247
You should make all changes to the entities incide a single transaction. You should begin it just before getting categories.
Upvotes: 0
Reputation: 52753
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
.
Upvotes: 1