2015-08-11 15 views
10

Bazı girdiler kullanabileceğim NHibernate ile ilgili bir sorunla uğraşıyorum.Nesnenin bir alt kümesinin tamamı yerine nasıl devam edilir?

Giriş:

ben ilişkisel kavramlar gerçekten uygulanmamıştır eski bir veritabanı var.

Veritabanında, sipariş satırları için veri içeren bir OrderLine tablom var. Tablo ayrıca Order özel bilgilerle tüm sütunları içerir Bunun üzerine

. Bu, örneğin bir müşterinin sipariş numarası olabilir.

E.x. 10 satırlık siparişim varsa, OrderLines tablomda 10 satır var ve her satırın tümü Order spesifik verilere sahip. sipariş numarası veya müşteri bilgisi.

Ben o zaman çok daha mantıklı OrderLines bir dizi/çantası var NHibernate benim Order harita böylece böylece bir görünüm Orders için oluşturulan benim kodunda yukarıdaki yapıya sahip istemiyordu.

Haritalama:

<class name="Order" table="[view_Orders]"> 
    <bag name="OrderLines"> 
</class> 

<class name="OrderLine" table="OrderLines" /> 

sorunu (basitleştirilmiş):

bakış karmaşıklığı imkansız görünüme kaydetmek için yapar.

NHibernate.Exceptions.GenericADOException: XXX ---> System.Data.SqlClient.SqlException: insert olamazdı NHibernates çalışırken bu istisnayı atar Görünüm veya işlev 'view_Orders' modifikasyon birden etkilediğinden güncellenebilir değil taban tabloları.

Benim NHibernate eşleme OrderLine nesnelerin bir "set ya da torba" sahip bir Order nesne olarak inşa edilir. İdeal olarak, NHibernate'in sadece tüm nesne yerine OrderLine nesnesini kullanmaya devam etmesini istiyorum. Bunu gerçekleştirmenin bir yolu

var mı? Nesneyi farklı kilit modlarını kullanarak kilitlemeyi denedim ama bana yardımcı olmadı. Ben sorununuzu anlıyorum durumda

+0

Yapmaya çalıştığınız gibi çalışmanız gerektiği gibi görünüyor. Kural dışı durum, NHibernate'in güncellenemeyen bir görünümle eşleştirilen Sipariş varlıklarınıza karşı bir GÜNCELLEŞTİRME gerçekleştirmeye çalıştığını gösterir. NHibernate, yalnızca varlığın kirli olduğunu düşünürse, OrderLines koleksiyonlarının dışında yapar. Diğer haritalanmış özelliklerini kontrol etmelisiniz. Ve belki neyin değiştiğini görmek için NHProf gibi bir profiler kullanmayı deneyin. –

+0

Tam olarak. Siparişimi güncellenemediğinden, güncellenemeyen bir görünümle eşleştirilmemesini istiyorum. Bunun yerine sadece çocuk nesnesini güncellemek istiyorum.OrderLines'in çantası. NHProfiler'i kullanıyorum ve yukarıdaki istisnalar temel olarak NHibernate'den geçirilen bir SQL İstisnasıdır. – JuniorCoder

cevap

1

, çözüm şaşırtıcı basittir.Biz sadece o Order sınıfta görünümüne eşleştirilmiş olan her mülk veya referansa update="false" uygulamak ardından dynamic-update="true"

<class name="Order" table="[view_Orders]" dynamic-update="true"> 
    ... 
</class> 

Ve kök nesnesi işaretlemek olacaktır:

... 
<property name="Code"  update="false"/> 
... 
<many-to-one name="Country" update="false /> 

Ama toplama olacak standart, hatta kademeli haritalamaya ihtiyaç duyar:

<class name="Order" table="[view_Orders]" dynamic-update="true"> 
    <bag name="OrderLines" 
     lazy="true" 
     inverse="true" 
     batch-size="25" 
     cascade="all-delete-orphan" > 
     ... 
    </bag> 
    ... // other stuff is update="false" 
</class> 
Kök nesnesi Order

var session = ... // get ISession 
// load root 
var root = session.Get<Order>(123); 

// if needed change existing line (pretend there is one) 
root.OrderLines[0].Amount = 100; 

// add new 
var newOrder = ... // new order 
root.OrderLines.Add(newOrder); 

session.Save(root); 
session.Flush(); 

üzerinde hiçbir güncellemeyi yürütme değilken böyle

Ve şimdi kod, OrderLines yönetimini yapacağını Ve o kadar. mutable="false" ayar sınıf ve toplama da var, ancak - Sadece ilginç not: Kök nesne üzerinde Cascade

... update = "false" olarak güncellenmiyorsa ederken, ne gerek NOT yapıyor Burada işe yaramaz ... yukarıda belirtilen çözüm olarak (bu üzgün, çünkü bu daha fazla olurdu, ama beklendiği gibi çalışmıyor ...). Bkz: 19.2.2. Strategy: read only

Başvurunuz okumak ama kalıcı sınıfın örneklerini değiştirmek asla gerekiyorsa

, salt okunur bir önbellek kullanılabilir. Bu en basit ve en iyi performans gösteren stratejidir. Bir kümede kullanım için bile mükemmel derecede güvenlidir.

<class name="Eg.Immutable" mutable="false">

+0

Hi Radim, Yardımlarınız için çok teşekkür ederim. Zaten mutable = "false" ayarını sıfırlamadan denedim. Dinamik güncelleştirme kullanmayı denedim, ancak hala aynı hataları alıyorum. Yukarıda tarif ettiğim hata, örnekleminizin doğru olup olmadığını hedeflediğime inandığım güncellemeler değil, veri ekleriyle ilgilidir. – JuniorCoder

+0

Evet, dediğim gibi 'değişebilir =' yanlış ''burada çözüm değildir. Ancak tüm görünümle ilgili özellikleri işaretleyerek "update =" false "' çalışacaktır. Sadece "" devam edecek ... Çünkü ... eğer manzarayı haritalandırdığınızı söylerseniz - GÜNCELLEME HAKKINDA SADECE konuşmamız gerekiyor. Yani, açıkladığınız gibi * (eğer doğru şekilde okursam) * - güncelleme sırasında sadece koleksiyona devam etmemiz gerekir. Bu durumda, bu koleksiyonun bile öğeleri INSERTED olabilir. Ancak yepyeni kaydın ana görünümüne eklenmesi, senaryonuza göre anlamlı değildir. Kontrol ettiğim ve çalıştığım şey .. ya da? –

+0

Sorunuzun bir parçası * "... İdeal olarak, NHibernate'i yalnızca tüm nesne yerine OrderLine nesnelerini kullanmaya devam etmesini isterim." * *, Eğer mevcut kayıt varsa (görünümünde, ana nesne olarak eşlenmiş), sadece OrderLines ekleyeceğiz ... ve bu çözüm, yukarıdaki yanıtla desteklenecektir. Sipariş zaten var (NHibernate tarafından güncellenmez) OrderLines'deki tüm öğeler tamamen yönetilebilir ... –

3

bu article söylediği gibi Güncellemeyi önlemek için mutable="false" kullanabilir ve siler edebilirsiniz:

Immutable sınıfları, değişken =, "false" tarafından güncellenen ya silinemez uygulama. Bu, NHibernate'in bazı küçük performans optimizasyonları yapmasına izin verir.

İşte
<sql-insert check="none">SELECT 1</sql-insert> 

bir test örneğidir:

aşağıdaki ifadeyi kullanabilirsiniz insert önlemek için

(kullanımını check="none" unutmak yerine komutu eklemek proyection Yüklü kullanır)

<class name="Order" table="[view_Orders]" mutable="false"> 
    <id name="OrderId" type="System.Guid"> 
    <generator class="guid.comb"/> <!-- Change as you need --> 
    </id> 

    <!-- Other properties --> 
    <!-- <property name="GrandTotal"/> --> 

    <set name="OrderLines" lazy="true" inverse="true" cascade="all-delete-orphan"> 
    <key column="OrderId"/> 
    <one-to-many class="OrderLine"/> 
    </set> 

    <sql-insert check="none">SELECT 1</sql-insert> 
</class> 

<class name="OrderLine" table="OrderLine"> 
    <id name="OrderLineId" type="System.Guid"> 
    <generator class="guid.comb"/> <!-- Change as you need --> 
    </id> 

    <!-- Other properties --> 
    <!-- <property name="OrderId"/> 
    <property name="GrandTotal"/>/> --> 

</class> 
İlgili konular