2012-02-14 7 views
0

См. Ниже приведенный ниже класс и карту. Я бы хотел, в некоторых случаях, обновить адрес (в это время все время один адрес).NHibernate: обновить коллекцию ISet

Я делаю это:

var customer = session.Get<Customer>(customerId); 
customer.Address.Clear(); 
customer.Address.Add(address); 

адрес исходит из формы, поле идентификатор не = 0 (при 0, при создании, нет проблем)

, но когда я делаю это:

session.Save(customer); 
session.Commit(); 

получаю исключение на фиксации (14 идентификатор CustomerAddress):

другой объект с тем же значением идентификатора уже был связан с сеансом: 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

Если адрес, который вы сохраняете уже имеет идентификатор, присвоенный этому вы можете просто сделать следующее:

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 получают эту ошибку, потому что и адрес с идентификатором 14 уже связан с вашим сеансом NHibernate. Поэтому, когда вы создаете новый отсоединенный переходный объект и пытаетесь сохранить его с помощью этого идентификатора, 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); 
+0

Я попробовал второе решение. Странно, что нет обновления, кроме вставки. Переменная 'address' имеет id = 14, и у меня есть вставка (а не обновление, а затем 2 адреса) –

+0

@ Kris-l Спасибо за указание на ошибку в моем коде Session.Save() должен быть Session.SaveOrUpdate(). Сожалею. – acarasso

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

Я нахожу этот метод громоздким, когда редактирую адрес, как правило, «ВСЕ», поля, кроме «Id' ** могут быть обновлены **. Я полагаю, это то, что мы должны играть с ... – Rippo

+0

@ Rippo Почему? Вы всегда должны назначать значения либо новому экземпляру, либо существующему. Шаблоны для отслеживания изменений хорошо определены и применимы к любой ORM, а не только к NH. –

+0

Я согласен с тобой 100% Я просто нахожу это громоздким, что все – Rippo

Смежные вопросы