2010-05-18 11 views
12

के कारण एफ # प्रकारों को ऑर्डर करने में समस्या का निर्धारण करने में समस्या मेरे पास कुछ प्रकार हैं जो एक सामान्य प्रकार का विस्तार करते हैं, और ये मेरे मॉडल हैं।परिपत्र संदर्भ

मेरे पास सीआरयूडी संचालन के लिए प्रत्येक मॉडल प्रकार के लिए डीएओ प्रकार हैं।

अब मुझे एक फ़ंक्शन की आवश्यकता है जो मुझे किसी भी मॉडल प्रकार को आईडी खोजने की अनुमति देगी, इसलिए मैंने कुछ विविध कार्यों के लिए एक नया प्रकार बनाया।

समस्या यह है कि मुझे नहीं पता कि इन प्रकारों को कैसे ऑर्डर करना है। वर्तमान में मेरे पास दाओ से पहले मॉडल हैं, लेकिन मुझे DAOMiscCityDAO और CityDAO से पहले DAOMisc से पहले DAOMisc की आवश्यकता है, जो संभव नहीं है।

सरल दृष्टिकोण प्रत्येक डीएओ में इस समारोह डाल करने के लिए, बस प्रकार है कि यह पहले आ सकता है की चर्चा करते हुए होगा, इसलिए, State आता है से पहले CityState रूप City के साथ एक विदेशी कुंजी संबंध नहीं है, इसलिए विविध समारोह होगा बहुत छोटा। लेकिन, यह सिर्फ मुझे गलत मानता है, इसलिए मुझे यकीन नहीं है कि इस पर सबसे अच्छा तरीका कैसे है।

यहां मेरा विविध प्रकार है, जहां BaseType मेरे सभी मॉडलों के लिए एक आम प्रकार है।

type DAOMisc = 
    member internal self.FindIdByType item = 
     match(item:BaseType) with 
     | :? StateType as i -> 
      let a = (StateDAO()).Retrieve i 
      a.Head.Id 
     | :? CityType as i -> 
      let a = (CityDAO()).Retrieve i 
      a.Head.Id 
     | _ -> -1 

यहाँ एक दाव प्रकार है। CommonDAO वास्तव में सीआरयूडी संचालन के लिए कोड है, लेकिन यह यहां महत्वपूर्ण नहीं है।

type CityDAO() = 
    inherit CommonDAO<CityType>("city", ["name"; "state_id"], 
     (fun(reader) -> 
      [ 
       while reader.Read() do 
        let s = new CityType() 
        s.Id <- reader.GetInt32 0 
        s.Name <- reader.GetString 1 
        s.StateName <- reader.GetString 3 
      ]), list.Empty 
    ) 

यह मेरा मॉडल प्रकार है:

type CityType() = 
    inherit BaseType() 
    let mutable name = "" 
    let mutable stateName = "" 
    member this.Name with get() = name and set restnameval=name <- restnameval 
    member this.StateName with get() = stateName and set stateidval=stateName <- stateidval 
    override this.ToSqlValuesList = [this.Name;] 
    override this.ToFKValuesList = [StateType(Name=this.StateName);] 

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

यह सम्मिलित करने के लिए एक बहुत ही सामान्य तरीके से सबसे अच्छा तरीका प्रतीत होता है, जो वर्तमान समस्या है जिसे मैं हल करने की कोशिश कर रहा हूं।

अद्यतन:

मैं अनुसंधान और अगर मैं किसी भी तरह अन्य सभी DAOs परिभाषित किया गया है के बाद CommonDAO में FindIdByType विधि इंजेक्षन कर सकते हैं, लगभग जैसे कि यह एक बंद है को देखने के लिए की जरूरत है। यदि यह जावा था तो मैं उस कार्यक्षमता को प्राप्त करने के लिए एओपी का उपयोग करूंगा जो मैं खोज रहा हूं, निश्चित नहीं है कि यह F # में कैसे करें।

अंतिम अद्यतन:

मेरे दृष्टिकोण के बारे में सोच के बाद मैंने महसूस यह घातक रूप से त्रुटिपूर्ण था, तो मैं एक अलग दृष्टिकोण के साथ आया था।

इस प्रकार मैं एक सम्मिलित करूंगा, और मैंने इस विचार को प्रत्येक इकाई वर्ग में रखने का फैसला किया, जो शायद एक बेहतर विचार है।

member self.Insert(user:CityType) = 
    let fk1 = [(StateDAO().Retrieve ((user.ToFKValuesList.Head :?> StateType), list.Empty)).Head.Id] 
    self.Insert (user, fk1) 

मैं अभी तक fklist उपयोग करने के लिए शुरू कर दिया है नहीं, लेकिन यह int list है और मुझे पता है जो स्तंभ नाम से हर एक के साथ चला जाता है, तो मैं बस, चयन के लिए inner join करने की जरूरत है, उदाहरण के लिए।

इस आधार प्रकार डालने कि सामान्यीकृत है:

member self.Insert(user:'a, fklist) = 
    self.ExecNonQuery (self.BuildUserInsertQuery user) 

यह अच्छा होगा अगर एफ # सह/विपरीत विचरण कर सकता है, इसलिए मुझे लगता है कि सीमा के आसपास काम करने के लिए किया था।

+0

भी देखें http उपयोग कर रहा है: निम्नलिखित चिकन/अंडा प्रकार परिभाषा पर विचार करें .com/प्रश्न/1378575/एफ-फॉरवर्ड-टाइप-घोषणाएं – Brian

+0

@ ब्रायन - जब तक मैंने इस अन्य प्रश्न के बारे में सोचा नहीं, मैंने केवल कई प्रकार के उपयोग और विचार करने पर विचार नहीं किया। ऐसा लगता है कि मेरे हिस्से पर एक दोषपूर्ण डिजाइन के लिए एक हैक है, लेकिन मुझे लगता है कि यह सबसे अच्छा तरीका है। –

उत्तर

7

यह उदाहरण कार्यात्मक प्रोग्रामिंग में आदी से बहुत दूर है। लेकिन पारस्परिक रूप से पुनरावर्ती प्रकारों को आदेश देने की समस्या के लिए, एक मानक समाधान है: प्रकार के पैरामीटर का उपयोग करें और दो-स्तर के प्रकार बनाएं। मैं ओकैमल, एक संबंधित भाषा में एक साधारण उदाहरण दूंगा। मुझे नहीं पता कि आप जिस प्रकार के डरावनी प्रकार के कार्यों का उपयोग कर रहे हैं, उसमें सरल उदाहरण का अनुवाद कैसे करें।

यहाँ काम नहीं करता है:

type misc = State of string 
      | City of city 

type city = { zipcode : int; location : misc } 

यहाँ कैसे आप इसे दो स्तर प्रकार के साथ ठीक है:

type 'm city' = { zipcode : int; location : 'm } 

type misc = State of string 
      | City of misc city' 
type city = misc city' 

यह उदाहरण OCaml है, लेकिन हो सकता है आप एफ # का सामान्यीकरण कर सकते हैं। उम्मीद है की यह मदद करेगा।

+1

मुझे जो दिखा रहा है उस पर मुझे प्रतिबिंबित करने की आवश्यकता है, ऐसा लगता है कि यह मेरे द्वारा किए जा रहे कार्यों की तुलना में बेहतर दृष्टिकोण हो सकता है। –

+0

आपने जो लिखा है उसके बारे में सोचने के बाद मुझे एहसास हुआ कि आप सही थे कि मेरा दृष्टिकोण गलत था। –

+0

मुझे इस अच्छे समाधान के बारे में कुछ पलों के बारे में भी सोचना पड़ा था :) –

10

एफ # में, पारस्परिक रूप से रिकर्सिव प्रकार परिभाषित करना संभव है, यानी, आप दो प्रकारों को परिभाषित कर सकते हैं जिन्हें एक-दूसरे को एक साथ संदर्भित करने की आवश्यकता है और वे एक-दूसरे को देखेंगे। इस लेखन के लिए वाक्य रचना है:

type CityDAO() = 
    inherit CommonDAO<CityType>(...) 
    // we can use DAOMisc here 

and DAOMisc = 
    member internal self.FindIdByType item = 
    // we can use CityDAO here 

इस वाक्य की सीमा यह है कि प्रकार के दोनों एक एकल फाइल में घोषित किए जाने की जरूरत है, तो आप 1 फ़ाइल प्रति ठेठ सी # संगठन 1 प्रकार का उपयोग नहीं कर सकते हैं।

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

आप शायद अधिक अच्छी तरह से अगर आप पहले दो प्रकार के लिए इंटरफेस को परिभाषित कोड लिख सकते हैं - इन या (एक दूसरे के सार्वजनिक इंटरफ़ेस में प्रयोग किया जाता है, इस पर निर्भर करता है) परस्पर पुनरावर्ती होने की जरूरत नहीं हो सकता है:

type ICityDAO = 
    abstract Foo : // ... 

type IDAOMisc = 
    abstract Foo : // ... 

यह निम्न लाभ हैं:

  • एक एकल फाइल में सभी परस्पर पुनरावर्ती इंटरफेस को परिभाषित करना कोड कम पठनीय नहीं है
  • आप बाद में, इंटरफेस का उल्लेख कर सकते इसलिए कोई अन्य प्रकार, एक पक्ष प्रभाव के रूप में पारस्परिक रूप से पुनरावर्ती
  • होने की जरूरत है आप और अधिक एक्स्टेंसिबल कोड (इंटरफेस के लिए धन्यवाद)
+0

मैं शायद एक इंटरफ़ेस के साथ जाने जा रहा हूं, लेकिन मैं समाधान से खुश नहीं हूं, क्योंकि यह प्रतीत होता है। मुझे लगता है कि मेरे डिजाइन के साथ कुछ मौलिक रूप से गलत है। मैंने इसके बारे में अपने प्रश्न पर एक संपादन जोड़ा। –

2

कैसे DAOMisc.FindIdByType को नष्ट करने, और प्रत्येक डीएओ के भीतर एक FindId इसकी जगह के बारे में होगा कक्षा? FindId केवल यह जान लेंगे कि अपना प्रकार कैसे ढूंढें। यह बेस क्लास और डायनामिक टाइप टेस्ट, और डीओओमिस्क और अन्य सभी डीएओ कक्षाओं के बीच परिपत्र निर्भरता की आवश्यकता को खत्म कर देगा।डीएओ प्रकार एक दूसरे पर निर्भर कर सकते हैं, इसलिए सिटीडाओ स्टेटडाओ.फिंडआईड को कॉल कर सकता है। (यदि आवश्यक हो तो डीएओ प्रकार पारस्परिक रूप से एक-दूसरे पर निर्भर हो सकते हैं।)

क्या आप यह कह रहे थे कि आप इस बारे में क्या कह रहे थे, "सरल दृष्टिकोण यह कार्य प्रत्येक डीएओ में रखना होगा ... लेकिन, यह सिर्फ मुझे गलत के रूप में हमला करता है ... "? मुझे यकीन नहीं है क्योंकि आपने कहा था कि फ़ंक्शन केवल उन प्रकारों को संदर्भित करेगा जो इससे पहले आते हैं। यह विचार कि मैं यहां प्रस्तुत कर रहा हूं वह यह है कि प्रत्येक FindId फ़ंक्शन केवल अपने ही प्रकार को जानता है।

+0

मैं जितना भी कर सकता हूं उतना कम करने की कोशिश कर रहा हूं, और मेरे कार्यों को जेनेरिक के रूप में सामान्य रूप से रख सकता हूं, यही कारण है कि प्रत्येक दाओ वर्ग में फ़ंक्शन दोहराना चिंता का विषय होगा। –

+1

आपका विचार था कि मैं –

3

एफ # सीधे पारस्परिक रूप से पुनरावर्ती प्रकारों का समर्थन करता है। // stackoverflow:

type Chicken = 
    | Eggs of Egg list 
and Egg = 
    | Chickens of Chicken list 

मुद्दा यह है कि पारस्परिक रूप से पुनरावर्ती प्रकार एक साथ घोषित किया गया है 'और' ऑपरेटर (के रूप में दो अलग-अलग प्रकार के के खिलाफ)

+0

के साथ गया था, मुझे विश्वास है कि मैंने आपके दृष्टिकोण की कोशिश की थी और जब मैंने अपना प्रश्न लिखा था तो मैं इसे काम नहीं कर सका। एफ # 3.0 ने यह संभव बना दिया है, मैंने इस बिंदु पर कोशिश नहीं की है। –