2011-11-05 6 views
5

में महत्वपूर्ण स्तंभ को निर्दिष्ट मान लें मैं निम्नलिखित दो वर्गों है:बचें डबल जुड़ा हुआ परिदृश्य

public class User : Entity 
{ 
    public virtual IList<Item> Items { get; set; } 
} 

public class Item : Entity 
{ 
    public virtual User Owner { get; set; } 
} 

मैं दो मानचित्रण कक्षाओं बनाया:

public class UserMap : ClassMap<User> 
{ 
    public UserMap() 
    { 
     Id(x => x.Id); 
     HasMany(x => x.Items); 
    } 
} 

public class ItemMap : ClassMap<Item> 
{ 
    public ItemMap() 
    { 
     Id(x => x.Id); 
     References(x => x.Owner); 
    } 
} 

यह एक मेज Item एक स्तंभ है कि में परिणाम होगा UserId और एक कॉलम OwnerId। जब मैं मैपिंग पर KeyColumn("OwnerId") का उपयोग करता हूं, तो यह केवल OwnerId कॉलम के साथ काम करता है, लेकिन मैं इससे बचना चाहता हूं। क्या ItemMap में मैपिंग द्वारा बनाए गए कॉलम का उपयोग करने के लिए एनएचबीर्नेट को बताने का कोई तरीका है?

मैं कॉलम को स्पष्ट रूप से निर्दिष्ट करने से बचना क्यों चाहता हूं:
कॉलम का नाम OwnerId स्वचालित रूप से संपत्ति के नाम और कुछ नियमों के आधार पर जेनरेट किया जा रहा है। अगर मैं नियम या संपत्ति का नाम बदलता हूं, तो मुझे KeyColumn को भी बदलना याद रखना होगा। तो, मूल रूप से, यह सहेजने के लिए refactoring नहीं है।

+0

क्या आप संपत्ति का नाम उपयोगकर्ता को बदल सकते हैं? सार्वजनिक वर्चुअल उपयोगकर्ता उपयोगकर्ता {प्राप्त करें; सेट; }। आपको –

+0

@ColeW के भी अपने संदर्भ मैपिंग को बदलना होगा: ठीक है, उपयोगकर्ता को संपत्ति को बदलना स्पष्ट रूप से ठीक होगा, लेकिन संपत्ति के नाम की तुलना में अब उतना अच्छा नहीं होगा जितना अब है। –

+0

मैं सहमत हूं लेकिन मुझे नहीं लगता कि आप जो कुछ भी पूछ रहे हैं उसे करने का एक साफ तरीका है। –

उत्तर

2

अपडेट किया गया: तय बग

यदि आप तो

public static void KeyColumnFromReference<TChild>(
    this OneToManyPart<TChild> collectionmap, ClassMap<TChild> map, Expression<Func<TChild, object>> referenceprop) 
{ 
    string propertyname = GetPropertyName(referenceprop); 
    var column = ((IMappingProvider)map).GetClassMapping() 
     .References.First(m => m.Name == propertyname) 
     .Columns.First().Name; 

    collectionmap.KeyColumn(column); 
} 

public static void KeyColumnFromReference<T, TChild>(
    this OneToManyPart<TChild> collectionmap, ClassMap<TChild> map) 
{ 
    var column = ((IMappingProvider)map).GetClassMapping() 
     .References.First(m => m.Type == typeof(TChild)) 
     .Columns.First().Name; 

    collectionmap.KeyColumn(column); 
} 

public UserMap() 
{ 
    HasMany(x => x.Items) 
     .KeyColumnFromReference<User, Item>(new ItemMap()); 

    // or 

    HasMany(x => x.Items) 
     .KeyColumnFromReference(new ItemMap(), u => u.Owner); 
} 

नक्शे में नियम लागू होते हैं, तो आप नियम लागू होते हैं के रूप में सम्मेलनों तो आप IHasManyConvention को लागू करने और EntityType पर वही नियम लागू करने की जरूरत है और PROPERTYNAME (आप ChildType से प्रतिबिंब के माध्यम से प्राप्त करने के लिए जो)

अद्यतन:

class ForeignKeyConvention : IHasManyConvention 
{ 
    public void Apply(IOneToManyCollectionInstance instance) 
    { 
     // to force the compiler to take the Name property and not the Name method 
     string propertyName = ((ICollectionInspector)instance).Name; 

     // should be equal to the convention for the reference key column 
     instance.Key.Column(propertyName + instance.EntityType.Name + "id"); 
    } 
} 
+0

धन्यवाद, यह अच्छा लग रहा है। हालांकि, मुझे आश्चर्य है कि क्या आप सुनिश्चित हैं कि यह कोड काम कर रहा है। यह मुझे अंतहीन रिकर्सन की तरह दिखता है: 'UserMap' के ctor में, आप' UserMap' का एक नया उदाहरण बनाते हैं ... क्या यह ''' को पारित करना बेहतर नहीं होगा? –

+0

यह एक बग thx, तय है। असल में यह एक त्वरित शॉट था;) – Firo

+0

कोड के लिए धन्यवाद - मैंने अभी इसका परीक्षण किया है। दुर्भाग्यवश, एक समस्या बाकी है: यह विदेशी कुंजी को खाते में स्वरूपित करने के लिए सम्मेलन नहीं लेता है ... क्या आप कृपया अपना कोड अपडेट कर सकते हैं? नमूना: मेरा सम्मेलन संपत्ति के नाम पर "आईडी" जोड़ना है। आपका कोड "_id" जोड़ता है। –