NHibernate tidak mengaktifkan pernyataan pembaruan saat memodifikasi entitas yang ada

Saya menggunakan NHibernate & Net Persistence API dengan C# dan MySql db di proyek saya dan saya memiliki lapisan UI (ASP.NET), Lapisan Bisnis, dan Lapisan Akses Data (DAL). Saya memiliki metode Simpan berikut di kelas UserManager DAL:

        private EntityManager GetEm()
        {
            if (_entityManager == null)
            {
                _entityManagerFactory = Persistence.CreateEntityManagerFactory("JPUMain");
                _entityManager = _entityManagerFactory.CreateEntityManager();
            }
            return _entityManager;
        }

        public void **Save**(IGenericEntity entity)
        {
            _entityManager = GetEm();
            _entityManager.GetTransaction().Begin();
            _entityManager.Persist(entity);
            _entityManager.Flush();            
            _entityManager.GetTransaction().Commit();            
            _entityManager.Clear();
        }

Entitas Pengguna Saya:

 [Entity]
 [Table(Name = "user")]
 public class User : IGenericEntity
    {
        [Id]
        [GeneratedValue]
        public virtual int ID { get; set; }

        [Basic]
        [Column(Name = "fname", Nullable = false)]
        public virtual string FirstName { get; set; }

        [Basic]
        [Column(Name = "lname", Nullable = false)]
        public virtual string LastName { get; set; 
    }

Sekarang jika saya mencoba menyelamatkan pengguna dengan menelepon:

UserManager.save(user)

kemudian menyimpan entri ke db dengan benar. Namun katakan lain kali (kapan saja, tidak dalam sesi yang sama) jika saya mencoba mengubah detail pengguna, maka alih-alih menjalankan perintah pembaruan, perintah tersebut akan mengaktifkan penyisipan, dan menyisipkan catatan baru dengan entitas pengguna modifikasi. Saya mengatur kunci utama pengguna dengan benar ke objek yang dimodifikasi.

Juga, ketika saya menjalankan test case untuk hal yang sama menggunakan NUnit, ia mencetak baris berikut:

NHibernate: SELECT LAST_INSERT_ID()
NHibernate: INSERT INTO user (uid, fname, lname) VALUES (?p0, ?p1, ?p2);?p0 = 2[Type: Int32 (0)], ?p1 = 'First Name' [Type: String (9)], ?p2 = 'Last Name' [Type: String (9)]

Saya mencoba menjalankan pernyataan ini langsung dari phpmyadmin di tabel pengguna, dan selalu memberikan nilai 0. Saya menggunakan mesin InnoDB.

Adakah yang bisa memberi tahu saya mengapa entitas pengguna yang ada tidak diperbarui? dan malah membuat rekor baru dengan entitas yang dimodifikasi?


person Arry    schedule 06.01.2013    source sumber


Jawaban (2)


Anda menyimpan entitas di ISession lain selain ISession yang Anda gunakan untuk mengambil entitas.

Hal terbaik yang dapat Anda lakukan adalah memastikan Anda menggunakan ISession yang sama. Saya pikir Anda harus benar-benar memikirkan bagaimana Anda akan mengelolanya. Sesi harus berumur pendek, jadi hal terbaik adalah membuat semacam lapisan layanan yang menangani berbagai kasus penggunaan.

person Frederik Gheysels    schedule 06.01.2013
comment
Bahkan ketika saya membuat entitas baru, dan kemudian memodifikasinya saat itu juga (dalam metode pembuatan entitas yang sama) menggunakan sesi yang sama, ia menyisipkan catatan baru alih-alih memodifikasi yang sudah ada. - person Arry; 07.01.2013
comment
Bisakah Anda memposting lebih banyak kode? Kasus ketika Anda menggunakan sesi yang sama dan mendapatkan penyisipan ganda? (termasuk metode manajer entitas) - person pkmiec; 07.01.2013

Persist tidak pernah meluncurkan pembaruan.

Menggali sumber NH Anda mungkin melihat Persist itu, yang benar-benar diterapkan di DefaultPersistEventListener, memeriksa status entitas:

public class DefaultPersistEventListener : AbstractSaveEventListener, IPersistEventListener
{
    //..
    public virtual void OnPersist(PersistEvent @event, IDictionary createdAlready)
    {
        //... 
        EntityState entityState = GetEntityState(entity, @event.EntityName, source.PersistenceContext.GetEntry(entity), source);

        switch (entityState)
        {
            case EntityState.Persistent:
                EntityIsPersistent(@event, createdAlready);
                break;
            case EntityState.Transient:
                EntityIsTransient(@event, createdAlready);
                break;
            case EntityState.Detached:
                throw new PersistentObjectException("detached entity passed to persist: " + GetLoggableName(@event.EntityName, entity));
            default:
                throw new ObjectDeletedException("deleted instance passed to merge", null, GetLoggableName(@event.EntityName, entity));
        }

}

Hanya metode EntityIsTransient yang mengirimkan sisipan ke DB. Jadi dalam konteks sesi Anda melakukan pembaruan, entitas yang dimaksud bersifat sementara. Anda harus memuat atau melampirkan entitas ini ke konteks sesi sebelum melakukan pembilasan. Metode SaveOrUpdate bisa menjadi jalan pintas yang berguna.

person pkmiec    schedule 06.01.2013
comment
Bisakah Anda memberikan beberapa contoh tentang cara melampirkan entitas ke konteks sesi sebelum melakukan flush? Terima kasih atas jawaban anda! - person Arry; 07.01.2013
comment
Juga Dooh, saya menggunakan NPersistence (implementasi NHibernate), dan saya tidak melihat metode SaveOrUpdate di sini... Bagaimana saya bisa mencapai ini di NPersitence? - person Arry; 07.01.2013