2009-03-16 17 views
6

के बारे में एसक्यूएलएक्सप्शन कोई इस अपवाद के साथ मेरी सहायता कर सकता है? मुझे समझ नहीं आता कि इसका क्या मतलब है या कैसे इसे ठीक करने के ... यह निम्न संदेश के साथ एक SqlException है:यूनियन, इंटरसेक्ट और EXCEPT

सभी प्रश्नों एक संघ का उपयोग कर संयुक्त, काटना या ऑपरेटर को छोड़कर में भाव की संख्या बराबर होनी चाहिए उनकी लक्ष्य सूचियां।

मैं समझ गया, जब इस तरह लग रही छद्म कोड में एक क्वेरी चलाने:

// Some filtering of data 
var query = data.Subjects 
      .Where(has value) 
      .Where(has other value among some set of values); 

// More filtering, where I need to have two different options 
var a = query 
      .Where(some foreign key is null); 
var b = query 
      .Where(some foreign key is not null) 
      .Where(and that foreign key has a property which is what I want); 
query = a.Union(b); 

// Final filter and then get result as a list 
var list = query 
      .Where(last requirement) 
      .ToList(); 

अगर मैं a.Union(b) भागों निकालते हैं तो वह बिना किसी अपवाद के चलाता है। तो मुझे पता है कि त्रुटि है। लेकिन मुझे यह क्यों मिलता है? और मैं इसे कैसे ठीक कर सकता हूं? क्या मैं यहाँ कुछ पागल कर रहा हूँ? क्या मैंने गलत समझा है कि Union चीज़ का उपयोग कैसे करें?

असल में मेरे पास कुछ ऐसी संस्थाएं हैं जिनके पास किसी अन्य इकाई के लिए विदेशी कुंजी है। और मुझे उन सभी संस्थाओं को प्राप्त करने की आवश्यकता है जिनके पास या तो विदेशी कुंजी null पर सेट है या जहां वह विदेशी इकाई कुछ आवश्यकताओं को पूरा करती है।

+0

अपवाद क्या है? –

+0

यह एक एसक्यूएलएक्सप्शन है। मैंने प्रश्न अपडेट किया =) – Svish

+0

क्या आप सुनिश्चित हैं कि कोई भी प्रश्न कुछ भी नहीं चुन रहा है (चयन करें)? मैंने इसमें भाग नहीं लिया है, लेकिन अभी मुझे याद नहीं है कि मैंने जो यूनियन किया है, वह linq2sql या पहले से ही पुनर्प्राप्त डेटा के खिलाफ था :( – eglasius

उत्तर

4

चूंकि यह उत्पन्न एसक्यूएल के साथ एक समस्या की तरह लग रहा है, तो आप का उपयोग या तो के लिए एक एसक्यूएल प्रोफाइलर, या उपयोग का प्रयास करना चाहिए हो जाते जोड़कर खेलने this code for DebuggerWritter class विजुअल स्टूडियो में अपनी आउटपुट विंडो में एसक्यूएल लिखने के लिए।

एसक्यूएल त्रुटि आमतौर पर यूनियन के लिए पुनर्प्राप्त फ़ील्ड के कारण 2 प्रश्नों के लिए समान नहीं है। उदाहरण के लिए, यदि पहली क्वेरी में 3 फ़ील्ड हो सकते हैं, लेकिन दूसरी क्वेरी में 4 फ़ील्ड हैं, तो यह त्रुटि होगी। इसलिए, जेनरेट किए गए एसक्यूएल को निश्चित रूप से इस मामले में मदद मिलेगी।

0

क्या आप शायद इसे एक प्रश्न में लिख सकते हैं?

.Where(row => row.ForeignKey == null || row.ForeignKey.SomeCondition); 

वहाँ भी विलय भाव (OrElse) के तरीके हैं, लेकिन है कि तुच्छ नहीं है।

यह सुनिश्चित नहीं है कि त्रुटि कहां से आती है!

संपादित करें: यह परीक्षण नहीं किया है, लेकिन इस तार्किक एक संघ के बराबर होना चाहिए:

public static IQueryable<T> WhereAnyOf<T>(
    this IQueryable<T> source, 
    params Expression<Func<T, bool>>[] predicates) 
{ 
    if (source == null) throw new ArgumentNullException("source"); 
    if (predicates == null) throw new ArgumentNullException("predicates"); 
    if (predicates.Length == 0) return source.Where(row => false); 
    if (predicates.Length == 1) return source.Where(predicates[0]); 

    var param = Expression.Parameter(typeof(T), "row"); 
    Expression body = Expression.Invoke(predicates[0], param); 
    for (int i = 1; i < predicates.Length; i++) 
    { 
     body = Expression.OrElse(body, 
      Expression.Invoke(predicates[i], param)); 
    } 
    return source.Where(Expression.Lambda<Func<T, bool>>(body, param)); 
} 
+0

समस्या यह है कि यह केवल कुछ कंडिशन नहीं है, लेकिन कुछ कंडिशन और व्हाटबेटवीन विधि का भी उपयोग है, जिसने आपने मुझे थोड़ी देर पहले मदद की थी, और इस तरह की चीजें। (http://stackoverflow.com/questions/553443/c-linq2sql-creating-a-predicate-to-find-elements-within-a-number-of-ranges) – Svish

+0

शायद आप WhereAnyOf (ऊपर) का उपयोग कर सकते हैं WhereBetween का मुख्य भाग (या कहां के बीच का संस्करण जो स्रोत को कॉल करने के बजाए भविष्यवाणी करता है। जहां (predicate)) –

+0

जो आशाजनक और रोचक लग रहा है ... कल पहली चीज़ को आजमाएगा! (काम खत्म हो गया है, और पकड़ने के लिए बस है!) – Svish

0

क्वेरी = a.Union (ख);

कैप्चर किए गए चर को म्यूट करने का कोई अच्छा विचार नहीं है ... त्रुटि का कारण शायद।

अद्यतन: ठीक नहीं

यहां एक और विचार है। संकेत त्रुटि संदेश में है।

var a = query 
     .Where(some foreign key is null) 
     .Select(x => x); 

या किसी अन्य 'झूठे' कहाँ तक वे बराबर :)

+0

म्यूट कैप्चर चर? – Svish

+0

आप सही हैं कि पुन: उपयोग भ्रम का परिचय देता है, लेकिन ध्यान दें कि उनमें से कोई भी कब्जा नहीं किया गया है ... –

+1

उसका मतलब है - var query2 = a.Union (b) है और क्वेरी 2 डाउनस्ट्रीम के साथ काम करते हैं। हालांकि, मुझे बहुत संदेह है कि इस अवसर पर ** यह समस्या ** है, क्योंकि यह वास्तव में कब्जा नहीं किया गया है। –

0

मैं data.GetCommand(query) पर कॉल करूंगा और परिणामी DbCommand (विशेष रूप से जेनरेट की गई SQL स्ट्रिंग) का विश्लेषण करूंगा। इससे आपको गलत होने के बारे में एक संकेत मिलना चाहिए।

कहीं भी कोई प्रक्षेपण नहीं चल रहा है, इसलिए मैं उम्मीद करता हूं कि दोनों लक्ष्य सूचियां समान होंगी।

आप एक छोटे से एक है कि अभी भी काम नहीं करता है करने के लिए आपकी क्वेरी को कम करने की कोशिश कर सकते। query.Union(query) से शुरू करें (यह कम से कम काम करना चाहिए)। अपने Where को एक-एक करके कॉल करने के लिए यह देखने के लिए कि यह काम करना बंद कर देता है।

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

+0

पहले से ही एसक्यूएल को देखा, हालांकि मुझे इसे डिबगिंग के दौरान मिला। इसे कॉपी किया और इसे एक नई क्वेरी में एसक्यूएल मैनेजर में चिपकाया। और मुझे वही त्रुटि मिलती है। समस्या यह है कि क्वेरी काफी बड़ी है, और मैं एसक्यूएल पढ़ने पर बहुत स्थिर नहीं हूं ... – Svish

+0

कुछ सुझावों को शामिल करने के लिए मेरे उत्तर को संपादित किया .. –

0

क्या आप एक चर में 'चयन' पक्ष के मूल्य में गुजरने के किसी भी मौके से हैं, या आप एक ही क्षेत्र को एक से अधिक बार लौट रहे हैं? एसपी 1 ने एक बग पेश किया जहां यह ऐसी चीजों को 'ऑप्टिमाइज़' करने का प्रयास करता है और इससे संघीय प्रश्नों को तोड़ने का कारण बन सकता है (विभिन्न हिस्सों में अलग-अलग पास किए गए क्वेरी भागों को अनुकूलित करने के कारण)।

आप छद्म कोड के बजाय अपने वास्तविक क्वेरी पोस्ट करते हैं तो यह आसान ऐसा तो नहीं है की पहचान करने में आता है।

(और यदि कोई मामला है तो पहले व्यक्तिगत भागों को पूरा करना है और फिर क्लाइंट-साइड (एल 2 ओ) संघ करना है)।

9

एसक्यूएल त्रुटि आप सूचीबद्ध आप एक ही मुद्दा रहा था अनुभव हो सकता है से आंकना। असल में जब लिंक से एसक्यूएल क्वेरीज जो दो अलग-अलग प्रश्नों पर कंसैट या यूनियन एक्सटेंशन विधि का उपयोग करते हैं, ऐसा लगता है कि लिंक से एसक्यूएल में एक बग है जो इस तथ्य के बावजूद अलग-अलग प्रक्षेपण को अनुकूलित करता है कि प्रक्षेपण को पूरा करने के लिए प्रोजेक्ट को वही रहना चाहिए एसक्यूएल संघ

संदर्भ:

LINQ to SQL produces incorrect TSQL when using UNION or CONCAT

Linq to SQL Union Same Fieldname generating Error

यह आपकी समस्या हो यदि ऐसा होता है के रूप में अच्छी तरह से मैं एक समाधान है कि मेरे लिए काम कर रहा है जिन्हें आप नीचे देख पाया है।

var queryA = 
    from a in context.TableA 
    select new 
    { 
     id, 
     name, 
     onlyInTableA, 
    } 

var queryB = 
    from b in context.TableB 
    let onlyInTableA = default(string) 
    select new 
    { 
     id, 
     name, 
     onlyInTableA, 
    } 

var results = queryA.Union(queryB).ToList(); 
+0

नोट, कि आपको प्रत्येक गणना मूल्य के लिए एक नया लेट स्टेटमेंट परिभाषित करना है, भले ही वास्तविक इस तकनीक को काम करने के लिए शाब्दिक मूल्य समान हैं। अब तक यह समस्या का एकमात्र उचित समाधान है। – jpierson

+2

यहां कुछ भयानक खबरें हैं, ऐसा प्रतीत होता है कि न केवल .NET Framework 4.0 ने इस समस्या को सही नहीं किया है बल्कि यह ऊपर दिए गए वर्कअराउंड को भी मिटा दिया है। – jpierson

+3

मैं सहमत हूं, .NET 4 भी बयान बयानों को अनुकूलित कर रहा है। हालांकि, v4 में ऑप्टिमाइज़र को रोकने के लिए एक और अधिक भयानक हैक यह है कि लेट स्टेटमेंट पर एक बेकार ऑपरेशन करना है जो इसके परिणाम को परिवर्तित नहीं करता है, जैसे एक खाली स्ट्रिंग को जोड़ना या शून्य जोड़ना। इस मामले में, निम्न की तरह कुछ काम कर सकता है: केवल InTableA = डिफ़ॉल्ट (स्ट्रिंग) + डिफ़ॉल्ट (स्ट्रिंग) –

0

jpierson समस्या को सही ढंग से संक्षेप है।
मैं भी समस्या है, इस समय का चयन करें बयान में कुछ शाब्दिक की वजह से था:
Dim results = (From t in TestDataContext.Table1 _
Where t.ID = WantedID _
Select t.name, SpecialField = 0, AnotherSpecialField = 0, t.Address).Union _
From t in TestDataContext.Table1 _
Where t.SecondID = WantedSecondID _
Select t.name, SpecialField = 1, AnotherSpecialField = 0, t.Address)

की "SpecialField = 0" पहले उप क्वेरी और "0 AnotherSpecialField =" अनुकूलित किया गया है, एक में जिसके परिणामस्वरूप संघ में दो का उपयोग किया जा रहा है, जो स्पष्ट रूप से असफल हो जाएगा।
मैं पहली बार क्वेरी को बदलने के लिए इतना है कि SpecialField & AnotherSpecialField विभिन्न मूल्यों था, बहुत दूसरा उप क्वेरी में की तरह था।

0

खैर मुझे इसके साथ कोई समस्या थी। एसक्यूएल 08 का उपयोग करके मेरे पास दो टेबल फ़ंक्शन थे जो दोनों मामलों में एक int और स्ट्रिंग लौटाते थे। मैंने एक जटिल वस्तु बनाई और यूनियन का प्रयास करने के लिए linq का उपयोग किया। तुलना करने के लिए एक IEqualityComparer था। सभी संकलित ठीक है, लेकिन एक असमर्थित अधिभार के साथ दुर्घटनाग्रस्त हो गया। ठीक है, मुझे एहसास हुआ कि चर्चा की गई समस्या निष्पादित निष्पादन की कमी लग रही थी। तो मुझे संग्रह मिलते हैं, और ToList() रखें, फिर यूनियन करें और यह सब अच्छा है। सुनिश्चित नहीं है कि यह सहायक है, लेकिन यह मेरे लिए काम करता है

+2

ठीक है, मुझे पता है। लेकिन आप जो कर रहे हैं वह स्थानीय रूप से यूनियन करना है। यह आपकी परिस्थितियों के आधार पर एक अच्छा विचार हो सकता है या नहीं भी हो सकता है। – Svish

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