请参阅下面的类和映射。我想在某些情况下更新地址(此时,它始终是一个地址)。
我这样做:
var customer = session.Get<Customer>(customerId);
customer.Address.Clear();
customer.Address.Add(address);
地址来自表单,id字段不是= 0(当0时,创建时没问题)
但是当我这样做时:
session.Save(customer);
session.Commit();
我在提交时收到异常(14是CustomerAddress的id):
具有相同标识符值的另一个对象已与会话关联:14,实体:CustomerAddress
更新此地址的方法是什么?
谢谢,
类和映射
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);
}
}
答案 0 :(得分:1)
如果您要保存的地址已分配了ID,则只需执行以下操作:
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);
您收到该错误,因为ID为14的地址已经与您的NHibernate会话相关联。因此,当您创建新的分离瞬态实体并尝试使用该id保存它时,NHibernate会抛出错误。一般来说,这是一件好事,因为很少想要做你正在做的事情。
更好的模式是为用户可更改的地址字段设置ViewModel,然后执行以下操作:
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);
答案 1 :(得分:0)
如果您更新地址,为什么要清除收藏并重新添加?
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();
}