NHibernate - Praktik Terbaik hanya untuk memilih

Ada tindakan pada aplikasi MVC saya yang memiliki id dan mengembalikan nama seseorang.

Apa praktik terbaik untuk itu? Saya mengikuti tip NHProf, tetapi kodenya terdengar agak aneh atau semacamnya bagi saya.

using (var session = Helper.SessionFactory.OpenStatelessSession())
{
    using (var tran = session.BeginTransaction(IsolationLevel.ReadCommitted))
    {
        return session.Query<Person>().Where(x => x.Id == id).Select(x => x.Name).SingleOrDefault();
        tran.Rollback();
    }
}

person Zote    schedule 10.05.2012    source sumber
comment
Saya tidak mengerti mengapa ini menyarankan transaksi...   -  person Felice Pollano    schedule 10.05.2012
comment
Saya tidak akan menggunakan OpenStatelessSessionsesi stateless untuk skenario massal dan mengabaikan cache L1. Daripada melakukan kueri linq, saya cukup memanggil .Load<Person>(1) atau .Get<Person>(1) yang menyatakan maksud lebih dari sekadar kueri linq.   -  person Andreas    schedule 10.05.2012


Jawaban (3)


Menurut saya, halaman peringatan NNHProf menjelaskannya dengan cukup baik -

http://nhprof.com/Learn/Alerts/DoNotUseImplicitTransactions

Pada dasarnya dikatakan jika Anda tidak mengelola transaksi sendiri, database akan membuat "transaksi implisit" dan melakukan komitmen otomatis untuk setiap pernyataan, termasuk kueri. Kesalahpahaman adalah bahwa transaksi hanya berguna untuk operasi penyisipan/pembaruan.

Dalam contoh Anda di atas, ini tidak menjadi masalah karena transaksi Anda hanya mengeksekusi satu pernyataan saja. Namun jika metode Anda menjalankan beberapa pernyataan, akan lebih baik jika menggabungkannya dalam sebuah transaksi.

person richeym    schedule 10.05.2012
comment
Oke, tapi untuk cara sederhana apakah saya harus mengikuti NProf dan membuat transaksi atau tidak? - person Zote; 10.05.2012
comment
Jawabannya hanya sebagian yang benar, Anda harus selalu mengubah query database Anda dalam suatu transaksi dan memang itu akan menjadi masalah bahkan jika Anda menjalankan satu pernyataan. Transaksi implisit itu mahal! dan NH tidak akan menggunakan cache L2 tanpa transaksi. - person Andreas; 10.05.2012

Berikut ini adalah cara saya mendekati pilihan ini:

    using (var session = Helper.SessionFactory.OpenStatelessSession())
    using (var tran = session.BeginTransaction(IsolationLevel.ReadCommitted))
    {
        try
        {
            string personName = session.Query<Person>()
            .Where(x => x.Id == id)
            .Single(x => x.Name);

            tran.Commit();
            return personName;
        }
        catch(Exception ex)
        {
            // handle exception
            tran.Rollback();
        }
    }

Jawaban SO ini memberikan saran bagus untuk menangani komitmen transaksi:

NHibernate - Apakah ITransaction.Commit benar-benar diperlukan?

Sehubungan dengan LINQ Anda, ini adalah artikel menarik tentang bagaimana tidak mendekati kueri menggunakan sintaks gaya metode ekstensi:

http://compiledexperience.com/blog/posts/how-not-to-use-linq

person Peadar Doyle    schedule 10.05.2012
comment
-1 untuk menangkap semuanya, melakukan pekerjaan yang berlebihan (menggunakan dan mencoba menangkap). - person Andreas; 10.05.2012
comment
@Andreas sejauh yang saya tahu menggunakan tidak memiliki cara untuk memproses pengecualian yang dilemparkan dan pilihannya adalah menggunakan percobaan yang berlebihan atau membuang secara manual. Juga bagaimana Anda menerapkan penanganan kesalahan dalam kasus ini karena ada sejumlah lapisan yang dapat menimbulkan kesalahan (NHibernate, ADO.NET, LINQ). - person Peadar Doyle; 11.05.2012
comment
stackoverflow.com/questions/6418992/ dan untuk pengecualian stackoverflow.com/ pertanyaan/426346/ stackoverflow. com/questions/114658/ blogs.msdn.com/b/ericlippert/archive/2008/09/10/ dan jangan beri tahu saya bahwa Anda dapat menangani stackoverflow dengan benar, kehabisan memori kecuali dengan tran.Rollback(); Anda. - person Andreas; 11.05.2012
comment
Terima kasih atas tautannya, saya tidak menyadari bahwa transaksi secara implisit dibatalkan. Saya juga harus meletakkan //handle pengecualian setelah Rollback() karena saya bermaksud sebagai tempat untuk penanganan kesalahan. Saya menghargai apa yang Anda katakan sehubungan dengan penanganan semua pengecualian dan mungkin itu bukan hal terbaik untuk dilakukan di sini. - person Peadar Doyle; 11.05.2012

jangan membuat banyak sesi dalam satu permintaan HTTP, idealnya yang perlu Anda lakukan adalah membuka sesi dan transaksi terkait pada cakupan permintaan dan menggunakan sesi ini di seluruh tindakan Anda.

Berikut ini postingan blog yang menjelaskan cara mencapainya: http://hackingon.net/post/NHibernate-Session-Per-Request-with-ASPNET-MVC.aspx

Saya akan menyarankan penggunaan wadah IOC dan membuat kelas yang membuat sesi untuk Anda dan memasukkan kelas ini ke cakupan permintaan.

Ada banyak sumber daya di web untuk mengatasi masalah ini.. Google saja..

person Baz1nga    schedule 10.05.2012
comment
Meskipun satu sesi per permintaan adalah saran yang bagus, ini bukanlah aturan yang tegas, dan memiliki satu transaksi per permintaan adalah saran yang buruk, jelas dan sederhana. - person Spivonious; 22.07.2016