NHibernate:更新ISet集合

时间:2012-02-14 07:51:32

标签: nhibernate orm fluent-nhibernate

请参阅下面的类和映射。我想在某些情况下更新地址(此时,它始终是一个地址)。

我这样做:

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);
    }
}

2 个答案:

答案 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();
}