Reputation: 19903
See the class and mapping below. I'd like in some case update the address (at this time, it's all the time one address).
I do this :
var customer = session.Get<Customer>(customerId);
customer.Address.Clear();
customer.Address.Add(address);
address is coming from a form, the id field is not = 0 (when 0, at creation, no problem)
but when I do this :
session.Save(customer);
session.Commit();
I receive an exception on the commit (14 is the id of CustomerAddress) :
a different object with the same identifier value was already associated with the session: 14, of entity: CustomerAddress
What is the way to update this address ?
Thanks,
Class and Mapping
public class Customer
{
public virtual int Id { get; set; }
public virtual string LastName { get; set; }
public virtual Iesi.Collections.Generic.ISet<CustomerAddress> Address { get; set; }
public Customer()
{
Address = new Iesi.Collections.Generic.HashedSet<CustomerAddress>();
}
}
public class CustomerAddress
{
public virtual int Id { get; set; }
public virtual string Street { get; set; }
public virtual Customer Customer { get; set; }
}
public class CustomerMap : ClassMap<Customer>
{
public CustomerMap()
{
Id(x => x.Id).GeneratedBy.Native();
Map(x => x.LastName)
.Length(50)
.Not.Nullable();
HasMany(x => x.Address)
.AsSet()
.Inverse()
.Cascade.AllDeleteOrphan()
.Not.LazyLoad();
}
}
public class CustomerAddressMap : ClassMap<CustomerAddress>
{
public CustomerAddressMap()
{
Id(x => x.Id).GeneratedBy.Native();
Map(x => x.Street).Length(50);
References(x => x.Customer);
}
}
Upvotes: 0
Views: 557
Reputation: 146
If the address you are saving already has an id assigned to it you can simply do the following:
var customer = session.Get<Customer>(customerId);
Session.Merge(address); // This will copy your transient entity into
// ..an entity with the same id that is in the
// ..first level cache.
session.SaveOrUpdate(customer);
You are getting that error because and address with an ID of 14 is already associated with your NHibernate session. So when you create the new detached transient entity and try to save it with that id NHibernate throws an error. Generally this is a good thing as it is very rare to want to do what you are doing.
A far better pattern would be to have a ViewModel for the fields of an address that are changeable by a user, and then do the following:
var address = Session.Get<Address>(addressVM.Id);
Mapper.Map(addressVM, address); // This is some type of mapper to copy properties
// ..from one object to another. I like automapper
// ..for this
Session.SaveOrUpdate(address);
Upvotes: 1
Reputation: 52725
If you are updating an address, why are you clearing the collection and re-adding?
using (var tx = session.BeginTransaction())
{
var customer = session.Get<Customer>(customerId);
var address = customer.Address.Single(/*optional condition here*/);
//or, if you are not updating the Customer, this might be better
var address = session.Get<Address>(addressId);
address.Street = updatedStreetInfo;
tx.Commit();
}
Upvotes: 0