2010-11-30 11 views
6

Anahtar sütununda Not Null Kısıtlama yerine, oldukça basit (sanırım) NHibernate kullanım durumuyla ilgili bir sorun yaşıyorum. aşağıdaki gibiNHibernate Yabancı anahtarı, ilk sütunu değil, ilk satırdan ziyade geçersiz kılar.

public class Parent 
{ 
    public virtual int ParentId { get; set; } 
    public virtual string Name { get; set; } 
    public virtual IList<Child> Children { get; set; } 
} 

public class Child 
{ 
    public virtual int ChildId { get; set; } 
    public virtual Parent Parent { get; set; } 
    public virtual string Name { get; set; } 
} 

Ve eşleştirmeleri:

[Test] 
    public void Test_save_family() 
    { 
     var parent = new Parent(); 
     var child = new Child {Parent = parent}; 
     parent.Children = new List<Child>{child}; 

     SessionManager.WithSession(
      session => 
       { 
        session.Save(parent); 
        session.Flush(); 
       }); 

    } 

:

public class ParentMap : ClassMap<Parent> 
{ 
    public ParentMap() 
    { 
     Id(x => x.ParentId).GeneratedBy.Native(); 
     Map(x => x.Name); 
     HasMany(x => x.Children).KeyColumn("ParentId").Cascade.SaveUpdate(); 
    } 
} 

public class ChildMap : ClassMap<Child> 
{ 
    public ChildMap() 
    { 
     Id(x => x.ChildId).GeneratedBy.Native(); 
     Map(x => x.Name); 
     References(x => x.Parent).Column("ParentId").ReadOnly().Not.Nullable(); 
    } 
} 

Son olarak, basit bir test var

Ben klasik bir Ebeveyn ve şöyle bir Çocuk varlık var Sınama bir System.Data.SqlClient.SqlException ile başarısız: NULL değeri 'ParentId' sütununa eklenemiyor. Bu, sütunun null olmadığından doğrudur, ancak null ekliyor?

NHibernate: INSERT INTO [Parent] (Name) VALUES (@p0); select SCOPE_IDENTITY();@p0 = NULL 
NHibernate: INSERT INTO [Child] (Name) VALUES (@p0); select SCOPE_IDENTITY();@p0 = NULL 
NHibernate: UPDATE [Child] SET ParentId = @p0 WHERE ChildId = @p1;@p0 = 2, @p1 = 1 

Bu görünüyor: Ben boş kısıtlamasını kaldırırsanız NHibernate ilk ebeveyn ekler çünkü

, bu çıktıda görüldüğü gibi daha sonra çocuk kaydında parentId sütunu günceller, daha sonra çocuğu ekler, eserlerini kurtarmak hemen hemen her durumda olduğu gibi bu türden yabancı anahtar sütunlar null olmayan olarak ilan edilir ve bu nedenle yabancı anahtar ekinde sağlanmalıdır. Öyleyse, niçin NHibernate yabancı anahtarını çocuk satırının ilk ekine yerleştirmiyor ve bunu nasıl düzeltebilirim?

cevap

7

Eşlemenizle ilgili birkaç sorun ... İki yönlü bir ilişkiniz var ve NHibernate'in hangi yolu güncelleştirmesi gerektiğini bilmesi gerekiyor. OO dünyasında, referanslar sadece bir yoldan gitmektedir ve NHibernate'in Ebeveyn-Çocukların Child-> Parent ile aynı FK olduğunu bilmesinin bir yolu yoktur. Şu anda Çocuk-> Veli ReadOnly() olarak ayarlanmış. Bu NHibernate'in bu özelliği güncellememesini söylüyor. Bu nedenle, çocuğu (boş bir ebeveyn ile) yerleştirmeye ve ardından FK'yi Ana tarafından güncellemeye çalışır. FK'nizde boş bir kısıtınız yoksa bu işe yaramıyor. Bunu eşlemek için normal yol, Ebeveyn tarafında Inverse = true kullanmak ve çocuğun devamlılık konusunda endişelenmesine izin vermektir. (Bu OO modelinde işin Veli-> Çocuk koleksiyonu Child grubu> Veli ilişkileri olarak referansların aynı kümesi içerir sağlamak için bu.) Kaydederken

public class ParentMap : ClassMap<Parent> 
{ 
    public ParentMap() 
    { 
     Id(x => x.ParentId).GeneratedBy.Native(); 
     Map(x => x.Name); 
     HasMany(x => x.Children).KeyColumn("ParentId").Inverse().Cascade.SaveUpdate(); 
    } 
} 

public class ChildMap : ClassMap<Child> 
{ 
    public ChildMap() 
    { 
     Id(x => x.ChildId).GeneratedBy.Native(); 
     Map(x => x.Name); 
     References(x => x.Parent).Column("ParentId").Not.Nullable(); // Removed ReadOnly() 
    } 
} 

SQL ifadeleri veritabanına gönderilen şimdi:

INSERT INTO [Parent] 
      (Name) 
VALUES  ('P1' /* @p0 */) 
select SCOPE_IDENTITY() 

INSERT INTO [Child] 
      (Name, 
      ParentId) 
VALUES  ('C1' /* @p0 */, 
      1 /* @p1 */) 
select SCOPE_IDENTITY() 
+0

James, testin başarılı olması için çalışılan ReadOnly() niteleyicisinin kaldırılması tamam. Ancak, şimdi ben ReadOnly() anlamı hakkında kafam karıştı. Anlayışım, ReadOnly() 'nin, NHibernate'in, ilk ekleme işleminden sonra sütunu hiçbir zaman güncelleştirmeyeceği anlamına gelmesiydi. –

+0

ReadOnly(), değerin hiçbir zaman ekleme veya güncelleştirme üzerine yazılmadığı anlamına gelir. Öncelikle arama tabloları ve hesaplanan sütunlar için kullanılır. –

+0

Hmm, Bunu biliyordum, şimdi bahsettiniz. Ben ReadOnly() bir öznitelik özniteliği olarak bir özellik özniteliği olarak ReadOnly ile karıştırdığını düşünüyorum. Yaşlanmak zorunda. :) Yardım için teşekkürler! –

İlgili konular