2009-03-17 18 views
26

के साथ विरासत मानचित्रण निम्नलिखित परिदृश्य को देखते हुए, मैं Fluent NHibernate का उपयोग कर डेटाबेस स्कीमा में प्रकार पदानुक्रम को मानचित्र बनाना चाहता हूं।Fluent NHibernate

मैं NHibernate 2,0


प्रकार पदानुक्रम

public abstract class Item 
{ 
    public virtual int ItemId { get; set; } 
    public virtual string ItemType { get; set; } 
    public virtual string FieldA { get; set; } 
} 

public abstract class SubItem : Item 
{ 
    public virtual string FieldB { get; set; } 
} 

public class ConcreteItemX : SubItem 
{ 
    public virtual string FieldC { get; set; } 
} 

public class ConcreteItemY : Item 
{ 
    public virtual string FieldD { get; set; } 
} 

See image

Item और SubItem कक्षाओं का उपयोग कर रहा सार हैं।


डाटाबेस स्कीमा

 
+----------+ +---------------+ +---------------+ 
| Item  | | ConcreteItemX | | ConcreteItemY | 
+==========+ +===============+ +===============+ 
| ItemId | | ItemId  | | ItemId  | 
| ItemType | | FieldC  | | FieldD  | 
| FieldA | +---------------+ +---------------+ 
| FieldB | 
+----------+ 

See image

ItemType क्षेत्र ठोस प्रकार निर्धारित करता है।

ConcreteItemX तालिका में प्रत्येक रिकॉर्ड Item तालिका में एक समान रिकॉर्ड है; इसी प्रकार ConcreteItemY तालिका के लिए।

FieldB आइटम प्रकार ConcreteItemY है, तो हमेशा शून्य होता है।


मानचित्रण (अब तक)

public class ItemMap : ClassMap<Item> 
{ 
    public ItemMap() 
    { 
     WithTable("Item"); 
     Id(x => x.ItemId, "ItemId"); 
     Map(x => x.FieldA, "FieldA"); 

     JoinedSubClass<ConcreteItemX>("ItemId", MapConcreteItemX); 
     JoinedSubClass<ConcreteItemY>("ItemId", MapConcreteItemY); 
    } 

    private static void MapConcreteItemX(JoinedSubClassPart<ConcreteItemX> part) 
    { 
     part.WithTableName("ConcreteItemX"); 
     part.Map(x => x.FieldC, "FieldC"); 
    } 

    private static void MapConcreteItemY(JoinedSubClassPart<ConcreteItemY> part) 
    { 
     part.WithTableName("ConcreteItemX"); 
     part.Map(x => x.FieldD, "FieldD"); 
    } 
} 

FieldB मैप नहीं है।


प्रश्न

मैं कैसे धाराप्रवाह NHibernate का उपयोग कर SubItem वर्ग के FieldB संपत्ति मैप करते हैं?

क्या कोई तरीका है कि मैं ItemType फ़ील्ड का उपयोग कर DiscriminateSubClassesOnColumn का लाभ उठा सकता हूं?


परिशिष्ट

मैं एक hbm.xml फ़ाइल का उपयोग कर वांछित परिणाम प्राप्त करने में सक्षम हूँ:

<class name="Item" table="Item"> 

    <id name="ItemId" type="Int32" column="ItemId"> 
    <generator class="native"/> 
    </id> 

    <discriminator column="ItemType" type="string"/> 

    <property name="FieldA" column="FieldA"/> 

    <subclass name="ConcreteItemX" discriminator-value="ConcreteItemX"> 
    <!-- Note the FieldB mapping here --> 
    <property name="FieldB" column="FieldB"/> 
    <join table="ConcreteItemX"> 
     <key column="ItemId"/> 
     <property name="FieldC" column="FieldC"/> 
    </join> 
    </subclass> 

    <subclass name="ConcreteItemY" discriminator-value="ConcreteItemY"> 
    <join table="ConcreteItemY"> 
     <key column="ItemId"/> 
     <property name="FieldD" column="FieldD"/> 
    </join> 
    </subclass> 

</class> 

मैं ऊपर मानचित्रण धाराप्रवाह NHibernate का उपयोग कर कैसे पूरा करते हैं?

फ़्लुएंट एनएचबेर्नेट का उपयोग करके तालिका-प्रति-उप-वर्ग के साथ टेबल-प्रति-श्रेणी-पदानुक्रम को मिश्रित करना संभव है?

+0

किसी भी कारण से यह समुदाय विकी चिह्नित है? किसी भी मामले में, क्या आप मानचित्रण रणनीति का उपयोग कर सकते हैं जिसका आप उपयोग कर रहे हैं? JoinSubClassPart तालिका-प्रति-सबक्लास पैटर्न का तात्पर्य है लेकिन कह रहा है कि आइटम तालिका में ठोस आइटम बनाए रखा जाता है, तालिका-प्रति-श्रेणी-पदानुक्रम पैटर्न का तात्पर्य है। –

+0

मुझे यकीन नहीं है कि समुदाय विकी सेटिंग कैसे बदलें। फील्डबी को अनदेखा करते हुए, मैं टेबल-प्रति-सबक्लास का उपयोग कर सकता हूं। फील्डबी की उपस्थिति मुझे कुछ भ्रम का कारण बनती है। यह दो रणनीतियों का मिश्रण प्रतीत होता है। ConcreteItemX प्रकार SubItem से FieldB विरासत में मिलता है। आइटम तालिका में फ़ील्डबी जारी है। –

उत्तर

1

अच्छा, मुझे यकीन नहीं है कि यह सही है, लेकिन यह काम कर सकता है ... अगर कोई इसे और अधिक साफ कर सकता है, तो मुझे इसे देखना अच्छा लगेगा (गंभीरता से, मैं चाहता हूं; यह एक दिलचस्प समस्या है) ।

सटीक वर्ग परिभाषाओं आप दे दी है की सहायता से देखें मैपिंग हैं:

public class ItemMap : ClassMap<Item> 
{ 
    public ItemMap() 
    { 
     Id(x => x.ItemId); 
     Map(x => x.ItemType); 
     Map(x => x.FieldA); 

     AddPart(new ConcreteItemYMap()); 
    } 
} 

public class SubItemMap : ClassMap<SubItem> 
{ 
    public SubItemMap() 
    { 
     WithTable("Item"); 

     // Get the base map and "inherit" the mapping parts 
     ItemMap baseMap = new ItemMap(); 
     foreach (IMappingPart part in baseMap.Parts) 
     { 
      // Skip any sub class parts... yes this is ugly 
      // Side note to anyone reading this that might know: 
      // Can you use GetType().IsSubClassOf($GenericClass$) 
      // without actually specifying the generic argument such 
      // that it will return true for all subclasses, regardless 
      // of the generic type? 
      if (part.GetType().BaseType.Name == "JoinedSubClassPart`1") 
       continue; 
      AddPart(part); 
     } 
     Map(x => x.FieldB); 
     AddPart(new ConcreteItemXMap()); 
    } 
} 

public class ConcreteItemXMap : JoinedSubClassPart<ConcreteItemX> 
{ 
    public ConcreteItemXMap() 
     : base("ItemId") 
    { 
     WithTableName("ConcreteItemX"); 
     Map(x => x.FieldC); 
    } 
} 

public class ConcreteItemYMap : JoinedSubClassPart<ConcreteItemY> 
{ 
    public ConcreteItemYMap() 
     : base("ItemId") 
    { 
     WithTableName("ConcreteItemY"); 
     Map(x => x.FieldD); 
    } 
} 

उन मैपिंग तो (कुछ बाहरी डेटा स्पष्टता के लिए निकाला गया) की तरह दो hbm.xml फ़ाइलों का उत्पादन:

<class name="Item" table="`Item`"> 
    <id name="ItemId" column="ItemId" type="Int32"> 
     <generator class="identity" /> 
    </id> 
    <property name="FieldA" type="String"> 
     <column name="FieldA" /> 
    </property> 
    <property name="ItemType" type="String"> 
     <column name="ItemType" /> 
    </property> 
    <joined-subclass name="ConcreteItemY" table="ConcreteItemY"> 
     <key column="ItemId" /> 
     <property name="FieldD"> 
     <column name="FieldD" /> 
     </property> 
    </joined-subclass> 
    </class> 

    <class name="SubItem" table="Item"> 
    <id name="ItemId" column="ItemId" type="Int32"> 
     <generator class="identity" /> 
    </id> 
    <property name="FieldB" type="String"> 
     <column name="FieldB" /> 
    </property> 
    <property name="ItemType" type="String"> 
     <column name="ItemType" /> 
    </property> 
    <property name="FieldA" type="String"> 
     <column name="FieldA" /> 
    </property> 
    <joined-subclass name="ConcreteItemX" table="ConcreteItemX"> 
     <key column="ItemId" /> 
     <property name="FieldC"> 
     <column name="FieldC" /> 
     </property> 
    </joined-subclass> 
    </class> 

यह बदसूरत है, लेकिन ऐसा लगता है कि यह एक प्रयोग योग्य मैपिंग फ़ाइल उत्पन्न कर सकता है और यह फ्लुएंट है! :/ आप जो कुछ भी चाहते हैं उसे प्राप्त करने के लिए आप कुछ और विचारों को ट्विक करने में सक्षम हो सकते हैं।

1

कोड की पंक्ति:

public static class DataObjectBaseExtension 
{ 
    public static void DefaultMap<T>(this ClassMap<T> DDL) where T : IUserAuditable 
    { 
     DDL.Map(p => p.AddedUser).Column("AddedUser"); 
     DDL.Map(p => p.UpdatedUser).Column("UpdatedUser"); 
    } 
} 

तब आप अपने सुपर क्लास मानचित्र निर्माता को यह जोड़ सकते हैं:

part.GetType().BaseType.IsGenericType && part.GetType().BaseType.GetGenericTypeDefinition() == typeof(JoinedSubClassPart<>) 
1

यह कैसे मैं अपने विरासत समस्या हल हो: if (part.GetType().BaseType.Name == "JoinedSubClassPart1") इस प्रकार लिखा जा सकता है :

internal class PatientMap : ClassMap<Patient> 
{ 
    public PatientMap() 
    { 
     Id(p => p.GUID).Column("GUID"); 
     Map(p => p.LocalIdentifier).Not.Nullable(); 
     Map(p => p.DateOfBirth).Not.Nullable(); 
     References(p => p.Sex).Column("RVSexGUID"); 
     References(p => p.Ethnicity).Column("RVEthnicityGUID"); 

     this.DefaultMap(); 
    } 


} 
+0

बढ़िया, धन्यवाद! – vondip

26

मुझे पता है कि यह वास्तव में पुराना है, लेकिन मैं टी प्रारंभिक रूप से वांछित सटीक मैपिंग उत्पन्न करने के लिए अब धाराप्रवाह सेट अप करने के लिए बहुत आसान है। चूंकि मैं जवाब के लिए खोज करते समय इस पोस्ट में आया, मैंने सोचा कि मैं इसे पोस्ट करूंगा।

आप बस अपनी उपवर्गों के लिए किसी भी संदर्भ के बिना आधार वर्ग के लिए अपने ClassMap बनाएँ:

public class ItemMap : ClassMap<Item> 
{ 
    public ItemMap() 
    { 
     this.Table("Item"); 
     this.DiscriminateSubClassesOnColumn("ItemType"); 
     this.Id(x => x.ItemId, "ItemId"); 
     this.Map(x => x.FieldA, "FieldA"); 
    } 
} 

तो इस तरह से अपनी सार उपवर्ग नक्शा:

public class SubItemMap: SubclassMap<SubItemMap> 
{ 
    public SubItemMap() 
    { 
     this.Map(x => x.FieldB); 
    } 
} 

फिर तो जैसे अपने ठोस उपवर्गों नक्शा:

public class ConcreteItemXMap : SubclassMap<ConcreteItemX> 
{ 
    public ConcretItemXMap() 
    { 
     this.Join("ConcreteItemX", x => 
     { 
      x.KeyColumn("ItemID"); 
      x.Map("FieldC") 
     }); 
    } 
} 

उम्मीद है कि यह किसी और को इस प्रकार की तलाश करने में मदद करता है धाराप्रवाह के साथ मैपिंग का।

+0

अच्छा! वास्तव में मुझे क्या चाहिए। – jweyrich