6

Değiştiremediğimiz eski bir veritabanımız var. Ve bir çöp olan ve çok yavaş olan eski DataAccess katmanının yerine NHibernate'e geçmeye çalışıyoruz.Birleşik anahtar bileşeninin bir parçasıyla eşlenen NHibernate gezginleri - eski veritabanı kullanımı

bu gibi tablolar:

GPI tablosu vardır (PU_ID, PAR_ID, veri, Veri2) sütun
BLOK tablosu vardır (GA_ID, veri, PAR_ID) sütun
ŞİRKET tablosu vardır (PU_ID, veri)

GPI

<class name="GroupPartnerInterest" table="[GPI]"> 
    <composite-id > 
     <key-property name="GroupId" column="PAR_ID" /> 
     <key-property name="CompanyId" column="PU_ID" /> 
    </composite-id> 
    <property name="data" column="Data"/> 
    <property name="data2" column="Data2"/> 
    <many-to-one name="Company" fetch="select" cascade="none"> 
     <column name="PU_ID"/> 
    </many-to-one> 
    <set name="Blocks" cascade="none" inverse="true" fetch="select"> 
     <key property-ref="GroupId"> 
      <column name="PAR_ID"/> 
     </key> 
     <one-to-many class="Block"/> 
    </set> 
</class> 
: sütunlar

yukarıda tablolar için bu eşleştirmeleri yaratmıştı

BLOK

<class name="Block" table="[BLOCK]" > 
    <id name="BlockId" column="GA_ID" > 
     <generator class="assigned"/> 
    </id> 
    <property name="data" column="Data"/> 
    <property name="GroupId" column="PAR_ID"/> 
    <set name="GroupPartnerInterests" cascade="all-delete-orphan" fetch="select"> 
     <key property-ref="GroupId"> 
      <column name="PAR_ID"/> 
     </key> 
     <one-to-many class="GroupPartnerInterest"/> 
    </set> 
</class> 

ŞİRKET

<class name="Company" table="[COMPANY]"> 
    <id name="CompanyId" column="PU_ID"> 
     <generator class="assigned"/> 
    </id> 
    <property name="data" column="Data"/> 
    <set name="GroupPartnerInterests" cascade="none" inverse="true" fetch="select"> 
     <key> 
      <column name="PU_ID"/> 
     </key> 
     <one-to-many class="GroupPartnerInterest"/> 
    </set> 
</class> 

sınıflar çok basit ve sadedir. Tüm uygulama Eşittir ve GetHashCode yöntemleri. İşte

çalışmak navigasyon listesi:

  • GroupPartnerInterest.Company - büyük
  • Company.GroupPartnerInterests işleri - büyük
  • GroupPartnerInterest.Company işleri - büyük çalışır

Ve Bu iki başarısız:

  • Block.GroupPartnerInterests: Bir birim testi

:

[TestMethod] 
public void TestGroupPartnerInterests() 
{ 
    using (ISession session = SessionFactory.OpenSession()) 
    { 
     IList<Block> blocks = session.CreateCriteria(typeof(Block)) 
      .SetMaxResults(5).List<Block>(); 

     foreach (var block in blocks) 
     { 
      TestContext.WriteLine("Block #{0}", block.BlockId); 

      if (block.GroupPartnerInterests != null) 
      { 
       foreach (GroupPartnerInterest gpi in block.GroupPartnerInterests) 
       { 
        TestContext.WriteLine("Company '{0}':", gpi.Company.CompanyId); 
       } 
      } 
     } 
    } 
} 

Ben GPI haritalama test çalışmalarında Blokları navigasyon eşlemesi açıklama ve bazı verileri çıkışını gerçekleştirmektedir:

Block #1
Company 'LALA':
Company 'LALA SA':
Block #2
Company 'BG PO':
Company 'LIMPOPO':
Block #3
Company 'HAHA':
Company 'Other partner(s)':
Block #4

Ama Bu sınama aşağıdaki hatayla başarısız olur:

'999' PAR_ID var - veriler tutarlı: Bu PAR_ID ile iki blok ve GPI'da birkaç kayıt var.

Neden bir noktada oturumu kapatır?

  • GroupPartnerInterest.Blocks:

Birim test yukarıda da belirtildiği gibi, sadece farklı özellikleri kullanılan hemen hemen aynıdır. bir hata aşağıdaki gibidir:

NHibernate.FKUnmatchingColumnsException: NHibernate.FKUnmatchingColumnsException: Foreign key (FKA3966498349694F:[BLOCK] [PAR_ID])) must have same number of columns as the referenced primary key ([GPI] [PAR_ID, PU_ID]).

mi:

NHibernate.MappingException: NHibernate.MappingException: property not found: GroupId on entity Model.EntityClasses.GroupPartnerInterest.

ben "mülkiyet ref = GroupId" GPI eşlemenizde Blokları gezginin elemandan, aşağıdaki özel durum alacak kaldırırsanız GroupPartnerInterest.Blocks navigator çalışacak şekilde GPI için bloklar eşleştirmek için herhangi bir yolu var mı?

sayesinde Alex

cevap

2

sorun şudur: Bir kompozit kimliğe sahip bir varlık varsa

  • , kendisine yapılan tüm başvurular kompozit id tutmalıdır, yani orada iki yabancı anahtar olmalı.
  • GroupPartnerInterest blokları bir kümedir, bu nedenle yabancı anahtar GroupPartnerInterest işaret ederek, Blocks işaretindedir. Mevcut olmayan iki yabancı anahtar gerektirir.
  • property-ref, birincil anahtarı başka bir özellikle değiştirmektir. Dolayısıyla, GroupPartnerInterest olan ilişkinin bir tarafındaki tablonun bir özelliğidir, ancak GroupId yoktur. (Iki yabancı anahtarlar GPI.PAR_ID için Block.PAR_ID nokta yapmak, eksik olduğu)
  • Sen muhtemelen GroupPartnerInterest.Blocks için property-ref kullanabilirsiniz, ama bu konuda iki kez düşünmek istiyorum.

Size burada bir çözüm sunamıyorum. Kompozit anahtar kullanmıyorum ve bu daha karmaşık. Ancak daha fazla fikir var:

  • Bileşik anahtarı engellemeye çalışırdım. Mümkün değilse, bileşik anahtarı temsil eden bir sınıf yazın. Bu işlem onu ​​daha kolay hale getirir.
  • Birincil anahtara dayalı olmayan ilişkilerden kaçınmaya çalışırdım. Aksini yapmak için sebepler olabilir, NH onları destekliyor, sadece sorunlara neden olduklarını düşünüyorum.

Neden seans kapalıdır ? Bilmiyorum, yığın izine bakarım. Gerçekten de kullanım bloğu içinden atılan istisna? Yoksa TestCleanup yönteminden mi atıldı?

+0

Derinlemesine cevap için teşekkürler! Ekibimizi DB şemasını biraz değiştirmeye ikna etmeye çalışacağım: GPI tablosuna otomatik oluşturulmuş (artırım) bir birincil anahtar ekleyin. Bu özellik-ref = GroupID sorunu giderecek ve benim sorun gezinme özelliklerini düzeltmem gerekir – LucID

+0

Çok benzer bir sorunum var. Bu senaryoyu hem xml hem de akıcı eşleştirmelerle eşleştirmeyi denedim, ancak sevinç yok. Maalesef şemayı şu anda değiştiremiyorum. Göz atmanı sağlayabilir miyim? http://stackoverflow.com/questions/25191275/fluent-nhibernate-map-hasmany-to-entity-table-with-no-primary-key –

İlgili konular