I would suggest you to look at this problem from an NHibernate point of view. And not from a relational database view. Let me start with what i feel you should be doing.
var customer = session.Load<Customer>(3);
var order = session.Load<Order>(1);
order.Customer = customer;
//assuming this is a one directional mapping. otherwise you might
//have to do some more steps to disassociate the order from the old
//customers collection and add it to the new customers collection
session.SaveOrUpdate(order);
Now, order.Customer.CustomerID
will return 3.
As Serkan suggested, its better and more feasible to work with objects instead of primary keys.
Also, there really shouldnt be any performance impact here. Nhibernate is able to proxy a lot of the associations as long as the classes have virtual public methods. Because of this, as long as you only query for the Id of the customer, it will not generate a separate sql query. The Id is already there with the proxy object.
With regards to the original question, I have a hunch. NHibernate dynamically generates the sql query for the update and the inserts. This case here is of an update. You have explicitly set the CustomerID property to 3. But the Customer property of the order object still points to the customer object with Id 1. So, when NHibernate generates the sql query, it trys to set the value first to 1, as you asked it to. Then it also sees that the Customer is still pointing to the old object, so reset the CustomerId property to 1. I think NHibernate is getting confused with the dual mappings.
There are two things that you can do. First enable the "show_sql" property in the NHibernate configuration.
<nhibernate>
...
<add key="hibernate.show_sql" value="true" />
</nhibernate>
Check what is the sql being generated when you save the order. That will explain things better.
Second, after saving the order, do session.Refresh(order);
You can read about the Refresh() method here. Its towards the end of the section 9.2. It will reload the order object with fresh values from the database. Calling order.CustomerID should show what value you have stored in the database.