views:

853

answers:

1

First, I have the following table:

CREATE TABLE CustomerHub (
   CustomerId INT NOT NULL,
   HubId INT NOT NULL
)

Which I have mapped to the this entity:

public class CustomerHub
{
   public int CustomerId {get;set;}
   public int HubId {get;set}

   //GetHashCode, Equals, Etc...
}

Using this mapping:

public class CustomerHubMap : ClassMap<CustomerHub>
{
   UseCompositeId()
      .WithKeyProperty(x => x.CustomerId)
      .WithKeyProperty(x => x.HubId);
}

The problem I have is that when I create a new entity of type CustomerHub and attempt to save it, nothing is persisted to the database. I am able to retrieve everything fine, just not save them. For example:

//this will work
var x = session.CreateCriteria(typeof(CustomerHub)); 

//this will not
using (var trans = session.BeginTransaction()) 
{
   var custHub = new CustomerHub {CustomerId = 293, HubId = 1193};
   var y = session.SaveOrUpdate(custHub); 
   trans.Commit();
}

The odd part is that no exceptions are thrown, it simply just doesn't do anything. I fired up NH Profiler (excellent tool!) and it looks like it isn't issuing any type of insert command to the database.

Thoughts?

Note: I realize that this table looks much like a join table (because it technically is) and would best be served as a ManyToMany relationship on another entity such as Customer... but due to some extremely screwy data design (ie no Hub table) it is FAR simpler to map the join table to an entity and work with it that way.

+1  A: 

Edit (put at top)

quote from NHibernate docs:

Due to its inherent nature, entities that use this generator cannot be saved via the ISession's SaveOrUpdate() method. Instead you have to explicitly specify to NHibernate if the object should be saved or updated by calling either the Save() or Update() method of the ISession.

http://www.nhforge.org/doc/nh/en/index.html#mapping-declaration-id-assigned (5.1.4.7)

Composite ID have generator = assigned.

This goes back to composite id = sucking :)


You aren't issuing a flush or commit. You are probably used to working with something like identity that issues an INSERT on save, but composite are assigned by your code, not the database, so you need a flush/commit for the insert to take place.


var custHub = new CustomerHub {CustomerId = 293, HubId = 1193};
var y = session.SaveOrUpdate(custHub);
session.Flush();

or

using(var tx = session.BeginTransaction())
{
    var custHub = new CustomerHub {CustomerId = 293, HubId = 1193};
    var y = session.SaveOrUpdate(custHub);
    tx.Commit();
}


Also, one note: using composite keys will make you hate your life. A lot of things don't work the same with composite keys and it isn't immediately obvious. Basically NHibernate can do less of the work so you have to pick up the slack.

eyston
Thanks for the quick answer. For the sake of brevity I left it out, but I have all my calls in a wrapped in code very similar to your second example. I also tried the flush with no luck.
jckeyes
added update. I wasn't sure on the SaveOrUpdate thing, so was waiting to see if this worked or not :p
eyston
I recently was reading the section on how SaveOrUpdate works and it wasn't clear how it would handle composite id... which is probably why they just don't even try.
eyston
Although I swear I have used it before... but I think it was already in the session state... I hate composite id.
eyston