2009-09-23 23 views
6

में लीकी अबास्ट्रक्शन मुझे कुछ डीबीएमएल जेनरेटेड क्लास के साथ समस्या हो रही है जो कुशल SQL को हल नहीं करते हैं। कल्पना करें कि मेरे पास एक खाता तालिका और एक लेनदेन तालिका है जहां प्रत्येक लेनदेन किसी विशेष खाते से जुड़ा होता है। मैं इसे सब डीबीएमएल में लोड करता हूं और बाहर एक खाता वर्ग और एक लेनदेन वर्ग पॉप करता है। खाता वर्ग में लेनदेन के संग्रह के लिए एक EntitySet संदर्भ है जो उस खाते के सभी लेन-देन का प्रतिनिधित्व करता है। काफी उचित।LINQ से SQL EntitySet

अब मान लीजिए कि मैं केवल वर्तमान लेखांकन अवधि के लिए लेनदेन चाहता हूं। तो मैं इस तरह एक पद्धति जोड़ें:

public IEnumerable<Transaction> CurrentTransactions 
{ 
    get 
    { 
     DateTime dtStart = CurrentPeriod; 
     DateTime dtEnd = NextPeriod; 
     return 
      from t in Transactions 
      orderby t.date 
      where t.date >= CurrentPeriod && t.date <= NextPeriod 
      select t; 
    } 
} 

अच्छा लग रहा है और यह काम करता है, लेकिन SQL अच्छा नहीं है:

SELECT [t0].[id], [t0].[account_id], [t0].[date], [t0].[description], [t0].[amount], [t0].[sign] 
FROM [dbo].[transactions] AS [t0] 
WHERE [t0].[account_id] = @p0 

Ie: यह LINQ के साथ नीचे लेन-देन के पूरे सेट खींच रहा है और हम इसे संसाधित है ऑब्जेक्ट्स के लिए। मैंने कॉन्स्टेंट्स के साथ तारीखों को प्रतिस्थापित करने के लिए, जहां ऑर्डर क्लॉज, ऑर्डरबी क्लॉज को निकालने का प्रयास किया है, यह अभी भी क्लाइंट पक्ष है।

तुलना के लिए, मैं डेटा संदर्भ बंद सीधे लेनदेन संग्रह कॉल करने की कोशिश:

DateTime dtStart = account.CurrentPeriod; 
DateTime dtEnd = account.NextPeriod; 
IEnumerable<Transaction> trans= 
       from t in MyDataContext.Transactions 
       orderby t.date 
       where t.date >= dtStart && t.date <= dtEnd && t.account_id==iAccountID 
       select t; 

और यह खूबसूरती से काम करता है:

SELECT [t0].[id], [t0].[account_id], [t0].[date], [t0].[description], [t0].[amount], [t0].[sign] 
FROM [dbo].[transactions] AS [t0] 
WHERE ([t0].[date] >= @p0) AND ([t0].[date] <= @p1) AND ([t0].[account_id] = @p2) 
ORDER BY [t0].[date] 
सब के बाद

तो, मैं दो प्रश्न हैं:

  1. क्या लेनदेन इकाई का उपरोक्त व्यवहार सही है और/या इसे ठीक करने का कोई तरीका है?
  2. मैं अपने खाता वर्ग पर उपरोक्त "फिक्स" को कैसे कार्यान्वित कर सकता हूं। डीबीएमएल द्वारा उत्पन्न इकाई वर्गों को डेटाकॉन्टेक्स्ट तक पहुंच नहीं है।

उत्तर

6

तुम बस ऐसा नहीं कर सकते, दुर्भाग्य से सक्षम होने के लिए की आवश्यकता होगी। LINQ से SQL इकाई वर्गों के लिए जेनरेट किए गए संग्रह गुण IQueryable नहीं हैं; इसलिए, उन पर किए गए किसी भी प्रश्न LINQ से ऑब्जेक्ट्स का उपयोग करेंगे। यह डिजाइन द्वारा है। जैसा कि आप सही तरीके से स्वयं को ध्यान में रखते हैं, कुशल क्वेरी प्राप्त करने के लिए आपको अपने DataContext से Transactions से पूछताछ करना है, लेकिन आपके पास अपनी संपत्ति गेटोर में कोई नहीं है।

इस बिंदु पर अपने विकल्पों को या तो कर रहे हैं:

  • यह एक तरीका है जिसके तर्क के रूप में एक DataContext लेता करते हैं; या
  • उपयोग प्रतिबिंब hackery संदर्भ पुनर्प्राप्त करने के लिए - इकाई ही यह दुकान नहीं है, लेकिन उस पर EntitySet है, करना यद्यपि परोक्ष रूप से - स्वाभाविक रूप से इस संस्करण विशिष्ट, टूटना की संभावना है, आदि

अब तक जैसा कि मुझे पता है, इकाई फ्रेमवर्क में यह सीमा नहीं है, क्योंकि इसकी संग्रह गुण ObjectQuery<T> है - जो IQueryable है।

+0

कम से कम 200 9 से अब तक इकाई फ्रेमवर्क के संग्रह गुण, ऑब्जेक्टिव 'प्रकार के प्रकार नहीं हैं, लेकिन' EntityCollection 'टाइप करें (हालांकि, उनके पास उन्हें 'ऑब्जेक्टक्चर ') में बदलने की विधि है। –

0

आईएनयूमेरेबल के बजाय आईक्वायरबल का उपयोग करने से स्विच करें और आपके एसक्यूएल को केवल वही मांग को खींचने के लिए अनुकूलित किया जाएगा जो आपको चाहिए।

+1

यह नहीं होगा। उनकी समस्या यह है कि 'लेनदेन' 'IQueryable' नहीं है, और वह इसके बारे में कुछ भी नहीं कर सकता है (यह एक 'EntitySet' है, और एक रहना चाहिए)। –

+0

हाँ यह बिल्कुल समस्या है। –

+0

अरग। कभी आसान समाधान नहीं। :) –

3

पहले उदाहरण में लेनदेन का प्रकार क्या है?

याद रखें कि आप एक्सटेंशन विधियों का उपयोग कर रहे हैं। Linq एक्सटेंशन के तरीके है कि उपयोग किया जाता है इंटरफेस पर निर्भर लेनदेन लागू कर रहे हैं: टी >

  • IQueryable < LINQ करने वाली एसक्यूएल या LINQ करने वाली संस्थाओं या ... होगा
  • IEnumerable < टी > आपको linq-to-items देगा।

संपादित करें:

public sealed class EntitySet<TEntity> : IList, 
    ICollection, IList<TEntity>, ICollection<TEntity>, IEnumerable<TEntity>, 
    IEnumerable, IListSource 
where TEntity : class 

आपके सवालों के जवाब के लिए::

  1. लेनदेन IQueryable < टी > तो लागू नहीं होता

    यह EntitySet प्रकार की अंगुली की छाप है यह सही व्यवहार

  2. है
  3. आपका खाता वर्ग संदर्भ के लिए लेन-देन तालिका वस्तु
+0

लेनदेन डीबीएमएल जेनरेट एंटिटीसेट संपत्ति है। \t \t [एसोसिएशन (नाम = "Account_Transaction", भंडारण = "_ लेन-देन", ThisKey = "आईडी", OtherKey = "ACCOUNT_ID")] \t \t सार्वजनिक EntitySet लेनदेन –

+0

2 के संबंध में)। मैं इसे समझता हूं, समस्या यह है कि मुझे ऐसा संदर्भ कैसे मिलता है कि खाता ऑब्जेक्ट आमतौर पर डेटा संदर्भ/इकाई ढांचे द्वारा बनाए जाते हैं? खाता ऑब्जेक्ट को लेनदेन तालिका के संदर्भ में कहां पास करने के लिए मैं कहां लगाऊंगा? या, एक और तरीका डालें, किसी विशेष डेटा संदर्भ से जुड़ी एक इकाई ऑब्जेक्ट को देखते हुए, मैं उस इकाई से डेटा संदर्भ में वापस कैसे प्राप्त करूं? –

+0

आप खाता ऑब्जेक्ट की कार्यक्षमता को विस्तारित कर रहे हैं? पैरामीटरयुक्त विधि कॉल जोड़ें? IENumerable GetCurrentTransactions (DataContext ctx) –