5

यह कुछ हद तक अमूर्त प्रश्न होगा।तालिका, उसके लेआउट और उसके रिकॉर्ड मॉडलिंग करते समय मैं कोड डुप्लिकेशन से कैसे बचूं, जिनमें से सभी समान संरचना को साझा करते हैं?

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

+-----------+ 
| Foo | 
+-----------+ 
| +Id: Guid | 
+-----------+ 

ध्यान दें कि यह चित्र इनमें से किसी भी वर्णन कर सकता है: एक मेज स्कीमा, एक ठोस तालिका, या एक ठोस तालिका रिकॉर्ड, प्रकार Guid के साथ एक क्षेत्र Id रही है।

  • स्कीमा में जो कुछ भी जाना जाता है वह फ़ील्ड का नाम और प्रकार है।
  • कंक्रीट (खुली) तालिका में, फ़ील्ड का "कॉलम इंडेक्स" अतिरिक्त रूप से जाना जाता है।
  • रिकॉर्ड के साथ, इन सभी चीजों को जाना जाता है, साथ ही फ़ील्ड का ठोस मूल्य होता है।

इसे कोड में अनुवादित करने के लिए, मुझे बहुत सारे प्रकार (तीन जोड़े में) मिलेंगे। उदाहरण संक्षेप में रखने के लिए मैं इंटरफेस का उपयोग करूंगा; मैं क्या दिखाना चाहते हैं प्रकार की समानता है:

// these interfaces only need to be implemented once: 

interface ISchemaField<T> { string Name { get; }  } 


interface ITableField<T> { string Name { get; }   
           int Index { get; }  } 

interface IRecordField<T> { string Name { get; }   
           int Index { get; }  
           T  Value { get; set; } } 

// these three interfaces are an example for one entity; there would be 
// three additional types for each additional entity. 

interface IFooSchema 
{ 
    ISchemaField<Guid> Id { get; } 
    IFooTable Open(IDbConnection dbConnection, string tableName); 
} 

interface IFooTable 
{ 
    ITableField<Guid> Id { get; } 
    ICollection<IFooRecord> ExecuteSomeQuery(); 
} 

interface IFooRecord 
{ 
    IRecordField<Guid> Id { get; } 
} 

अब मैं एक ठोस डाटा मॉडल में हर इकाई के लिए तीन बहुत समान कार्यान्वयन लिखने के लिए होने से बचने के लिए चाहते हैं। कोड डुप्लिकेशन को कम करने के कुछ संभावित तरीके क्या हैं?

  • मैं कोड & अधिक पठनीय के कम लाइनों के साथ कोड पीढ़ी (जैसे टी -4) है, जो एक ठीक समाधान होगा के बारे में सोचा है, लेकिन मैं एक "मैन्युअल" कोडित समाधान पसंद करेंगे (यदि वहाँ एक है) कोड।

  • मैंने एक वर्ग प्रति इकाई बनाने के बारे में सोचा है जो स्कीमा, टेबल और रिकॉर्ड इंटरफ़ेस को एक ही समय में लागू करता है ... लेकिन यह गन्दा लगता है और चिंता के पृथक्करण का उल्लंघन करता है।

+0

आप इकाई की रूपरेखा का उपयोग कर रहे हैं? – TheBoyan

+0

@ बोजन, नहीं। मैं एक एपीआई (ईएसआरआई आर्कऑब्जेक्ट्स) के शीर्ष पर एक कस्टम डीएएल ढांचा तैयार कर रहा हूं जो इकाई फ्रेमवर्क, न ही एनएचबीरनेट द्वारा समर्थित नहीं है, न ही कोई अन्य OR/M मुझे पता है। – stakx

+0

आपकी स्कीमा पर बस एक संक्षिप्त रूप से मुझे आश्चर्य होता है कि तीन स्कीमा इंटरफेस के बीच कोई विरासत क्यों नहीं है? आप उन्हें विरासत के बजाय बस मेटाडेटा डुप्लिकेट करना प्रतीत होता है। –

उत्तर

1

आईएमएचओ, मुझे लगता है कि आप टेबल संरचना के अमूर्तता के साथ बहुत दूर जा रहे हैं। ओवरफ्यूज इंटरफेस कोड को पढ़ने में कठोर बना सकता है। मुझे यह बहुत परेशान लगता है, उदाहरण के लिए, कि आप किसी ऑब्जेक्ट के कार्यान्वयन को देखने के लिए F12 दबा नहीं सकते क्योंकि यह एक इंटरफ़ेस प्रकार है।

एक सिद्ध मॉडल जिसे मैंने वर्षों से काम किया है और यह बनाए रखना बेहद आसान है, सभी वर्गों को तालिका के नामों के समान रखना है, फिर फ़ील्ड नाम जो कॉलम नामों से मेल खाते हैं।आप आसानी से खोज का उपयोग करके और संपादक में प्रतिस्थापित करने के तरीकों को आसानी से उत्पन्न कर सकते हैं, और कोड परिवर्तनों के लिए भी यही होता है। इस तरह आपको स्मृति में कॉलम नाम और कॉलम अनुक्रमणिका रखने की आवश्यकता नहीं है। आप उन्हें अपने डेटा एक्सेस स्तरीय में हार्डकोड करते हैं (हार्डकोडिंग हमेशा खराब नहीं होता है!)। उदाहरण के लिए:

this.Price = reader["Price"] as decimal?; 

प्रदर्शन इस दृष्टिकोण के साथ बहुत अच्छा है और कोड सुपर पोषणीय है!

जो भी दृष्टिकोण आप अनुसरण करते हैं, मुख्य बात यह है कि आप टेबल कॉलम से क्लास गुणों में मैपिंग कैसे रखते हैं। मैं उन्हें हार्डकोडिंग की सलाह देता हूं और एक सीधा नामकरण सम्मेलन (कॉलम नाम = संपत्ति का नाम) का उपयोग करता हूं। जब आप कॉलम जोड़ते या बदलते हैं तो इस दृष्टिकोण के लिए आपको पुन: संकलित करने की आवश्यकता होती है, लेकिन मुझे लगता है कि ये परिवर्तन अक्सर भिन्नता में कॉलम नाम रखने या उन्हें अलग फ़ाइल से पढ़ने के लिए पर्याप्त नहीं होते हैं। ऐसा करने से पुनर्मूल्यांकन से बचा जाता है, लेकिन कोड को कम करने में आसान बनाता है। मुझे नहीं लगता कि यह इसके लायक है।

+0

मैंने अपने उदाहरण में इंटरफेस का उपयोग किया क्योंकि मुझे लगा कि एक ठोस कार्यान्वयन केवल वास्तविक मुद्दे से विचलित होगा।इंटरफेस यह दिखाने के लिए पर्याप्त हैं कि कोड डुप्लिकेशन कब होगा। लेकिन मैं 'इंटरफ़ेस' के बजाय 'कक्षा' का उपयोग कर सकता था। (मैंने इसे और अधिक स्पष्ट करने के लिए अपना प्रश्न अपडेट कर दिया है।) – stakx

+0

मैं आप जो कह रहा हूं उससे सहमत नहीं हूं, esp। हार्डकोडिंग कॉलम इंडेक्स बिट (त्रुटियों के संभावित स्रोत की तरह लगता है), लेकिन मैं आपका जवाब स्वीकार कर रहा हूं क्योंकि आपका कथन, _ "आप टेबल संरचना के अबास्ट्रक्शन के साथ बहुत दूर जा रहे हैं" _ अब मेरे लिए बहुत उचित लगता है। मैंने जो कुछ किया है, उसके बारे में मैंने एक अलग उत्तर पोस्ट किया है (नीचे देखें)। – stakx

+1

कुडोस यह सब स्वयं को डिजाइन करने के लिए, और माइक्रोसॉफ्ट या किसी भी द्वारा अनुशंसित पैटर्न का पालन नहीं करने के लिए। मैंने अपने हार्डकोडेड पैटर्न को औचित्य देने का प्रयास करने के लिए अपना उत्तर अपडेट किया। – Diego

1

AutoMapper पर एक नज़र डालें। यह डीटीओ के पीओसीओ इत्यादि को परिवर्तित करने के लिए एक उपयोगी छोटी मुक्ति है और आपके आवेदन की परतों के बीच डेटा स्थानांतरित करने के लिए बड़ी संख्या में डुप्लीकेट कोड और प्रयास को हटा देगा।

+0

अंतर्निहित डेटाबेस एपीआई (ईएसआरआई आर्कऑब्जेक्ट्स) में आपके सामान्य आरडीबीएमएस में कई वैचारिक मतभेद हैं। (एक बात के लिए, यह COM- आधारित है। दूसरे के लिए, डीबी कर्सर द्वारा लौटाई गई पंक्तियां अगली पंक्ति लौटने के बाद ही "समाप्त हो सकती हैं"। आखिरकार, कर्सर को स्पष्ट रूप से मुक्त किया जाना चाहिए। सूची चालू और चालू होती है।) - मुझे पूरा यकीन है कि ऑटोमैपर, न ही अधिक परिष्कृत या/एम ढांचे, उसमें सही तरीके से निपटने में कठिनाई होगी। लेकिन मुझे गलत सिद्ध होना अच्छा लगेगा। – stakx

1

एक अंतरफलक वंशानुगत पदानुक्रम बनाएं इन इंटरफेस को लागू तो एक ही विरासत योजना का अनुसरण कर सकते

interface ISchemaField<T> 
{ 
    string Name { get; } 
} 

interface ITableField<T> : ISchemaField<T> 
{ 
    int Index { get; } 
} 

interface IRecordField<T> : ITableField<T> 
{ 
    T Value { get; set; } 
} 

क्लासेस।

+0

असली काम शुरू होता है जब आपको इन्हें * कार्यान्वित करना होता है। और इससे भी बदतर '... फ़ील्ड ' फ्रेमवर्क प्रकार (जिसे लागू किया जाना चाहिए * केवल एक बार *) इकाई प्रकार के ट्रिपल (जिन्हें प्रति इकाई * लागू करने की आवश्यकता है *) हैं, जिनमें से 'IFoo ... ' केवल एक है उदाहरण। – stakx

0

मैं एक जवाब स्वीकार कर लिया है, लेकिन सोचा कि मैं हिस्सा था मैं अंत में करने के लिए तय कर लिया है क्या:

  • मैं एक प्रकार में मेज स्कीमा और तालिका मर्ज करके कुछ दोहराव को हटाने कर रहा हूँ । यह एक राज्य प्रकार का बन जाता है: एक तालिका "खोला नहीं जा सकता" या "खोला" जा सकता है। यदि यह खोला नहीं गया है, तो केवल फ़ील्ड के नाम और प्रकार उपलब्ध हैं। यदि तालिका खोला गया है, तो फील्ड इंडेक्स भी उपलब्ध हैं।

  • फ़ील्ड नाम तालिका प्रकार में स्थिर फ़ील्ड या बस स्ट्रिंग स्थिरांक हैं।

  • मैं फिर कुछ डुप्लिकेशंस के साथ समाप्त होता हूं, अर्थात् दो प्रकार की समानता, एक रिकॉर्ड के लिए एक, दूसरा टेबल/स्कीमा के लिए, लेकिन यह स्वीकार्य है।

संक्षेप में, मैं एक और अधिक व्यावहारिक समाधान की तुलना में मैं इसे पसंद किया है | चयन किया हो, यह शुद्ध नहीं है, लेकिन संभवतः चीजें पूरी की जाएगी।


class FooRecord 
{ 
    FooRecord(FooTable table) { … } 
    readonly FooTable table; 

    public Guid Id { get { … } set { … } } 
} 

class TableField<T> 
{ 
    public TableField(string name) { … } 
    public string Name { get; } 
    public int Index { get; internal set; } 
} 

class FooTable 
{ 
    public void Open(IDbConnection dbConnection, string tableName) { … } 
    //^opens the table and determines the fields' indices, e.g. Id.Index. 

    public TableField<Guid> Id 
    { 
     get 
     { 
      return idField; 
     } 
    } 
    TableField<Guid> idField = new TableField<Guid>("ID"); 
}