2012-02-14 65 views
0

請參見下面的類和映射。我想在某些情況下更新地址(此時,它始終是一個地址)。NHibernate:更新ISet集合

我這樣做:

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

回答

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會拋出一個錯誤。通常這是一件好事,因爲想要做你正在做的事情是非常罕見的。

一個更好的模式將有一個視圖模型對於用戶是可以改變的地址字段,然後進行以下操作:

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); 
+0

我試過第二種解決方案。奇怪的是沒有更新,但插入。 'address'變量的id = 14,我有一個插入(而不是更新,然後是2個地址) – 2012-02-14 12:46:03

+0

@ Kris-l感謝您指出我的代碼中的錯誤Session.Save()應該是Session.SaveOrUpdate ()。抱歉。 – acarasso 2012-02-17 02:56:04

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(); 
} 
+0

當我編輯一個通常爲'ALL'的地址時,我發現這個方法很麻煩,除了'Id' **之外的字段可能會被更新。我想它是我們必須玩的...... – Rippo 2012-02-14 17:18:36

+0

@Rippo爲什麼?您始終必須將值分配給新實例或現有值。變更追蹤的模式是明確的,適用於任何ORM,而不僅僅是NH。 – 2012-02-14 18:34:58

+0

我同意你100%我只是覺得它很麻煩這是所有 – Rippo 2012-02-14 18:41:09