2010-09-17 11 views
6

संपादित की ओर इशारा करते कुंजी सवाल साफ़ बेहतर वास्तविक मुद्दा प्रतिबिंबित करने के लिए:SQLMetal एकाधिक विदेश एक टेबल जारी करना

मैं अपने एसक्यूएल सर्वर डाटाबेस से डेटाबेस वर्गों उत्पन्न करने के लिए SQLMetal उपयोग कर रहा हूँ। हाल ही में, मुझे एक सारणी जोड़ने की ज़रूरत थी जिसमें एक ही टेबल पर इंगित कई विदेशी कुंजी हों।

  • record.FK_AId
  • record.FK_BId
  • record.FKA
  • record.FKB: नई तालिकाओं के साथ चारों ओर खेलने के लिए LINQPad का उपयोग करना, मैं तो जैसे दोनों विदेशी चाबी के लिए गुण पर पहुंच सकता था

... जो कि मैं इसकी अपेक्षा करता हूं। समस्या है, SQLMetal द्वारा उत्पन्न वर्गों इन गुणों का उत्पादन:

  • record.FK_AId
  • record.FK_BId
  • record.FKA
  • record.FKBTableNameGoesHere

अब मैं सकता है सिर्फ जेनरेट किए गए वर्गों को व्यवस्थित करें ताकि FKBTableNameGoes यहां FK_B होगा, लेकिन जेनरेट की गई फाइलें अलग-अलग टीम के सदस्यों द्वारा अक्सर बदल दी जाती हैं, ताकि यह एक विशाल पाई होगा एन। क्या इसके लिए कोई आसान फिक्स है?

अग्रिम धन्यवाद।

संपादित 2 तो, मैंने सोचा था कि समाधान सिर्फ एक आंशिक वर्ग है कि एक संपत्ति नामित क्या मैं इसे बनना चाहता था था बनाने के लिए, और खराब नामित संपत्ति के लिए गेटर/सेटर बिंदु जाने के लिए किया जाएगा। यह चुनने के लिए काम करता था, लेकिन इसका उपयोग नहीं करते जहां क्लॉज और ऐसे। किसी के पास समाधान है ??

उत्तर

4

तो, मेरा समाधान केवल एक और आंशिक वर्ग जोड़ना था और अजीब नामित FKBTableNameGoesHere संपत्ति की ओर इशारा/सेट के साथ एक संपत्ति जोड़ें। इस तरह हमें जेनरेट किए गए वर्गों को संशोधित करने की आवश्यकता नहीं है। वास्तव में समस्या को हल नहीं करते हैं, लेकिन डेवलपर्स को यह स्पष्ट करना चाहिए कि संपत्ति का क्या अर्थ है। कोई भी उस समाधान के साथ कोई संभावित समस्या देखता है?

संपादित करें - तो जाहिर है, यह केवल डेटा चुनने के लिए काम करता है और इसके आधार पर फ़िल्टरिंग नहीं करता है। जैसा कि मैंने आशा की थी उतनी आसान नहीं है। क्या किसी के पास कोई अन्य सुझाव है?

संपादित करें 2 - जीज़, सोचा कि यह कुछ आम समस्या होगी लेकिन मुझे नहीं लगता। वैसे भी, पता चला कि मैं इसके साथ सही रास्ते पर था।

Multiple foreign keys to the same table

कौन मुझे यह विचार है कि मैं सिर्फ सीधे गेटर/सेटर के लिए एक और संपत्ति के लिए वहाँ शायद एक बहुत है कि पर्दे के पीछे चल रहा से भी अधिक है के बाद से लिंक नहीं कर सके दिया: मैं इस पोस्ट पाया। यह लोग समाधान बिल्कुल जवाब नहीं था, लेकिन यह मुझे कठोर दिशा में भेजा।संघ विशेषताएं जोड़ना क्या अंत में यह किया है:

public partial class ProblemClass 
{ 
    [Association(Name = "FK__SomeLinkHere", Storage = "_OriginalPoorlyNamedStorageVariable", ThisKey = "FK_1_Id", OtherKey = "Id", IsForeignKey = true)] 
    public FKType MyNewBetterName 
    { 
     get 
     { 
      return this._OriginalPoorlyNamedStorageVariable.Entity; 
     } 

     set 
     { 
      this.OriginalPoorlyNamedStorageVariable = value; 
     } 
    } 
} 

इनाम किसी के लिए खुला है जो अभी भी एक क्लीनर समाधान के साथ आ सकते हैं छोड़ने के लिए जा रहे हैं।

+0

इसे वास्तव में एक कदम आगे ले जाया जा सकता है और _OriginalPoorlyNamedStorageVariable का उपयोग करके पूरी तरह से छोड़ा जा सकता है। हालांकि मुझे यकीन नहीं है कि कन्स्ट्रक्टर में आपके स्वयं के स्टोरेज वैरिएबल को शामिल करने से कुछ अन्य जटिलताओं का कारण नहीं होगा, लेकिन शायद मैं वास्तव में जल्द ही पता चल रहा हूं ... – jahu

0

ठीक है, मैं एक नया उत्तर प्रस्तावित करूंगा (थोड़ा देर हो चुकी है, क्षमा करें) जो एसोसिएशन का नाम बदलता है, भले ही काम करेगा।

यह विधि मुख्य इकाई की एसोसिएशन संपत्ति की तलाश करेगी और फिर यह मास्टर टेबल में मान की तलाश करेगी। कल्पना कीजिए कि:

तालिका: OrdersOrders.CustomerID द्वारा तालिका Customers साथ संदर्भित के बराबर होती है Customers.Id। इसलिए हम मुख्य तालिका की मेटा जानकारी, फ़ील्ड CustomerID (जो संदर्भित फ़ील्ड है) और फ़ील्ड Name (जो मान हम चाहते हैं) पास करते हैं।

/// <summary> 
/// Gets the value of "referencedValueFieldName" of an associated table of the "fieldName" in the "mainTable". 
/// This is equivalent of doing the next LINQ query: 
/// var qryForeignValue = 
///  from mt in modelContext.mainTable 
///  join at in modelContext.associatedTable 
///  on mt.fieldName equals at.associatedField 
///  select new { Value = at.referencedValueField } 
/// </summary> 
/// <param name="mainTable">Metadata of the table of the fieldName's field</param> 
/// <param name="fieldName">Name of the field of the foreign key</param> 
/// <param name="referencedValueFieldName">Which field of the foreign table do you the value want</param> 
/// <returns>The value of the referenced table</returns> 
/// <remarks>This method only works with foreign keys of one field.</remarks> 
private Object GetForeignValue(MetaTable mainTable, string fieldName, string referencedValueFieldName) { 
    Object resultValue = null; 
    foreach (MetaDataMember member in mainTable.RowType.DataMembers) { 
    if ((member.IsAssociation) && (member.Association.IsForeignKey)) { 
     if (member.Association.ThisKey[0].Name == fieldName) { 
     Type associationType = fPointOfSaleData.GetType(); 
     PropertyInfo associationInfo = associationType.GetProperty(member.Name); 
     if (associationInfo == null) 
      throw new Exception("Association property not found on member"); 

     Object associationValue = associationType.InvokeMember(associationInfo.Name, BindingFlags.GetProperty, null, fPointOfSaleData, null); 

     if (associationValue != null) { 
      Type foreignType = associationValue.GetType(); 
      PropertyInfo foreignInfo = foreignType.GetProperty(referencedValueFieldName); 
      if (foreignInfo == null) 
      throw new Exception("Foreign property not found on assiciation member"); 

      resultValue = foreignType.InvokeMember(foreignInfo.Name, BindingFlags.GetProperty, null, associationValue, null); 
     } 

     break; 
     } 
    } 
    } 
    return resultValue; 
} 

और कॉल:

 AttributeMappingSource mapping = new System.Data.Linq.Mapping.AttributeMappingSource(); 
     MetaModel model = mapping.GetModel(typeof(WhateverClassesDataContext)); 
     MetaTable table = model.GetTable(typeof(Order)); 
     Object value = GetForeignValue(table, "CustomerId" /* In the main table */, "Name" /* In the master table */); 

समस्या यह है कि केवल केवल एक ही संदर्भित क्षेत्र के साथ विदेशी कुंजी के साथ काम करती है। लेकिन, कई चाबियों में बदलना काफी छोटा है।

यह मास्टर टेबल के किसी फ़ील्ड का मान प्राप्त करने का एक तरीका है, आप संपूर्ण ऑब्जेक्ट को वापस करने के लिए बदल सकते हैं।

पीएस: मुझे लगता है कि मैं अपनी अंग्रेजी के बारे में कुछ गलतियां करता हूं, यह मेरे लिए काफी मुश्किल है।

0

यह प्रश्न बहुत समय पहले आया था, लेकिन मैं बस इस समस्या में भाग गया। मैं एक डीबीएमएल का उपयोग कर रहा हूं और मैंने संबंधों को संपादित करके इस समस्या को हल किया है। यदि आप पेरेंटप्रोपर्टी का विस्तार करते हैं, तो आप नाम संपत्ति को बदलकर संपत्ति का नाम सेट कर सकते हैं।

public partial class ProblemClass 
{ 
    partial void OnCreated() 
    { 
     this._MyNewBetterName = default(EntityRef<FKType>); 
    } 
    protected EntityRef<FKType> _MyNewBetterName; 

    [Association(Name = "FK__SomeLinkHere", Storage = "_MyNewBetterName", ThisKey = "FK_1_Id", OtherKey = "Id", IsForeignKey = true)] 
    public EntityRef<FKType> MyNewBetterName 
    { 
     get 
     { 
      return this._MyNewBetterName.Entity; 
     } 

     set 
     { 
      this.MyNewBetterName = value; 
     } 
    } 
} 
इस के साथ

आप भी जानने की जरूरत नहीं है:

<Association Name="State_StateAction1" Member="DestinationState" ThisKey="DestinationStateId" OtherKey="Id" Type="State" IsForeignKey="true" /> 
0

यहाँ Ocelot20 के संस्करण का एक प्रकार है:

यहाँ (बदला सदस्य विशेषता) dbml से XML है मूल भंडारण नाम, हालांकि मुझे यकीन नहीं है कि क्या सेटटर काम करेगा (मैंने केवल गेटर का उपयोग किया था, लेकिन यह एक आकर्षण की तरह काम करता था)। आप इस संबंध परिभाषा को बेस क्लास में भी पैक कर सकते हैं और आंशिक रूप से इसे प्राप्त कर सकते हैं (क्या आपको इसे कई मॉडलों \ संदर्भों में संबंधों का पुन: उपयोग करने की आवश्यकता होनी चाहिए, जिससे इसे आसान बनाना चाहिए), लेकिन पकड़ है, आपको OnCreated() प्रत्येक के अंदर परिभाषित करना होगा आंशिक रूप से उनको विरासत में नहीं लिया जा सकता है सी # (see this) में।

संबंधित मुद्दे