NHibernate: обновить коллекцию ISet - PullRequest
0 голосов
/ 14 февраля 2012

См. Класс и карту ниже. Я хотел бы в некоторых случаях обновить адрес (в настоящее время это все время один адрес).

Я делаю это:

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

адрес исходит из формы, поле id не = 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);
    }
}

Ответы [ 2 ]

1 голос
/ 14 февраля 2012

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

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

Вы получаете эту ошибку, потому что адрес с идентификатором 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 голосов
/ 14 февраля 2012

Если вы обновляете адрес, почему вы очищаете коллекцию и повторно добавляете?

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();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...