2016-02-23 5 views
6

मैं एक Linq निम्नलिखित जैसे SQL करने के लिए है:LINQ एसक्यूएल गणना करने के लिए शामिल करें मिलती

var members=db.Members.Include(x=> x.Contact).Count(); 

अब कुछ बुरा डेटा की वजह से मेरी सदस्यों में सभी संपर्कों इसी संपर्क रिकॉर्ड नहीं है। तो गिनती के दौरान मैं संपर्क तालिका के साथ आंतरिक में शामिल होने के बाद गणना कैसे शामिल कर सकता हूं।

समस्या है जब मैं सदस्यों की सूची प्राप्त, सदस्यों की सूची है 100 रिकॉर्ड्स गणना 150 रिकॉर्ड (50 रिकॉर्ड खराब डेटा जा रहा है) है, जबकि।

var membersQ=db.Members.Include(x=> x.Contact).Select(i=> new MemberViewModel(){ 
Name = i.Contact.Name, 
ContactId= i.Contact.Id, 
CreatedDate= i.CreatedDate 
}).AsQueryable(); 
var members=memberQ.ToList();// =100,paging is done... 
// the memebers list uses paging but the count doesn't 
var total=membersQ.Count(); // =150 

मैं गिनती के दौरान परिणामी क्वेरी जाँच की, जाहिरा तौर पर यह संपर्क की मेज के साथ JOIN ऐसा नहीं करता है, जबकि Count()

अद्यतन डेटाबेस संरचना

Member Table 
Id ContactId, CompanyId, CreatedDate ... 

Contact Table 
Id Name ... 

विदेशी ContactId के लिए में महत्वपूर्ण सदस्य तालिका डेटाबेस स्तर पर सेट नहीं है बल्कि केवल मॉडल पर है।

[ForeignKey("ContactId")] 
Public Contact Contact { get; set; } 

बुरा डेटा इस

मैं संपर्क रिकॉर्ड के रूप में पहले से 1,2,3,4,5,6,7,8,9,10 था और उन सभी संपर्कों की तरह चला जाता है सदस्य तालिका में थे भी।

अब मैंने संपर्क तालिका से रिकॉर्ड हटा दिए हैं 6-10 कहें। लेकिन सदस्य तालिका से हटाना नहीं हुआ।

तो यह गिनती के साथ एक मुद्दा पैदा कर रहा है। हां, सदस्य से खराब डेटा को हटाने से समस्या हल हो जाती है लेकिन सवाल यह है कि join while using Count() का उपयोग कैसे करें।

नोट: मैं डेटाबेस प्रारंभकर्ता अशक्त का उपयोग

अद्यतन 2 मैं LINQPad का इस्तेमाल किया और दोनों डिफ़ॉल्ट Linq To SQL और EntityFramework (DbContext) कनेक्शन की कोशिश की और मैं क्या पाया भ्रामक है।

क्वेरी के लिए:

(from a in Members 
join b in Contacts on a.ContactId equals b.ContactId 
select a).Count() 

डिफ़ॉल्ट LINQ का उपयोग कर

SELECT COUNT(*) AS [value] 
FROM [Member] AS [t0] 
INNER JOIN [Contact] AS [t1] ON [t0].[ContactID] = [t1].[ContactID] 

SQL के Entityframework DbContext

SELECT 
    [GroupBy1].[A1] AS [C1] 
    FROM (SELECT 
     COUNT(1) AS [A1] 
     FROM [dbo].[Member] AS [Extent1] 
    ) AS [GroupBy1] 

का उपयोग करते हुए मेरी कोड में मैं DbContext विधि का उपयोग करें। तो .. पता नहीं क्या पर क्या करना है। Btw: linq-to-sql के साथ एक टैग होने के लिए खेद है यह वास्तव में entityframework

+0

प्रयास करें। प्रयत्न। memberQ.Contacts.Count() (यह 100 होना चाहिए) –

+0

तो मुझे 'toList' के लिए उपयोग किए गए' की तुलना में 'संपर्क' का चयन करने वाली अलग-अलग क्वेरी का उपयोग करना होगा? – Ruchan

उत्तर

4

क्या इस बारे में:

var x = from m in Members 
     join c in Contacts on m.ContactId equals c.ID 
     select new 
     { 
      Name = c.Name, 
      ContactId= c.ID, 
      CreatedDate= c.CreatedDate 
     }; 

Console.Write(x.Count()); 

संपादित

जब मैं इस प्रश्न के साथ LINQPad का उपयोग करें और उत्पन्न एसक्यूएल को देखो मैं:

SELECT COUNT(*) AS [value] 
FROM [Members] AS [t0] 
INNER JOIN [Contact] AS [t1] ON [t0].[ContactId] = ([t1].[ID]) 

संपादित 2

आप भी इस कोशिश कर सकते:

var x = from c in Contacts 
     from m in Members where m.ContactId == c.ID 
     select new 
     { 
      Name = c.Name, 
      ContactId= c.ID, 
      CreatedDate= c.CreatedDate 
     }; 

Console.Write(x.Count()); 
+0

दरअसल यह भी काम नहीं करता है, परिणामी क्वेरी 'संपर्क' – Ruchan

+0

@ रुचान के साथ जुड़ती नहीं है जब मैं लिंककैड का उपयोग करता हूं और क्वेरी चलाता हूं मुझे एक आंतरिक मिलती है: चुनें COUNT (*) AS [value] से [सदस्य] ] एएस [टी 0] इनर जॉइन [संपर्क] एएस [टी 1] चालू [टी 0]। [संपर्क आईडी] = ([टी 1]। [आईडी]) –

+0

अपडेटेड पोस्ट – Ruchan

2

सुनिश्चित नहीं है अगर यह सही है लेकिन, रिकॉर्ड गलत डेटा, डुप्लिकेट युक्त कर रहे हैं? यदि हां, तो क्यों न केवल उन 100 अच्छे रिकॉर्ड प्राप्त करने के लिए अलग() का उपयोग करें?यदि सब आप चाहते हैं सूची में से सिर्फ गिनती है, तो क्यों उपयोग नहीं:

var members = memberQ.ToList(); 
int total = members.Count; 
+0

उदाहरण के लिए मैंने सीधे ToList का उपयोग किया, लेकिन मुझे रिकॉर्ड में पेजिंग करने की आवश्यकता है। गिनती पेजिंग होने की आवश्यकता नहीं है। – Ruchan

2

जवाब इस करने के लिए है आप सदस्यों और संपर्क के बीच कोई संबंध नहीं है। सदस्यों की तालिका में 150 पंक्तियां हैं और संपर्क तालिका में 100 पंक्तियां हैं। तो जब आप लाने की कोशिश करते हैं तो आप वास्तव में कुछ पंक्ति समाप्त होने तक डेटा पंक्ति को पंक्ति से जोड़ते हैं। जब आप गिनती करते हैं तो आप पहली तालिका को गिनते हैं।

समाधान आपको सदस्यों या किसी भी प्रकार के पहचानकर्ता से संपर्कों में एफके जोड़ने की आवश्यकता है, आप संपर्क से सदस्यों पर डेटा को "बाध्य" कर सकते हैं।

अधिक विवरण & भी अधिक टिप्पणियां

तालिका में में Members आप एक Contact के लिए एक संदर्भ है। जो आप अपने Include(x=> x.Contact) बयान के साथ पॉप्युलेट

तो आप इस

new MemberViewModel(){ 
    Name = i.Contact.Name, 
    ContactId= i.Contact.Id, 
    CreatedDate= i.CreatedDate 
} 

बनाने के लिए आप कुछ स्पष्टीकरण के लिए एक संपर्क की सामग्री के लिए पूछ रहे हैं (जैसा कि आप शायद जानते हैं।)

अब प्रयास करते हुए। जब आप डेटाबेस को क्वेरी करते हैं तो आप MembersQ में करते हैं तो आप डेटा को नहीं ला रहे/महसूस नहीं कर रहे हैं। (आप बस एक प्रश्न तैयारी कर रहे हैं)

एक प्रश्न आप ToArray() कॉल करना होगा, ToList() आदि का एहसास करने के लिए और आप एक समय (कर्सर) पर एक पंक्ति का एहसास जब आप डेटा पर एक foreach है।

अपने परिणाम के लिए अब

, जब आप ToList() आप प्रकार सूची की सूची को साकार कर रहे हैं फोन

जब आप memberQ.Count() प्रदर्शन कर रहे हैं आप से पूछना (अब केवल भरने के लिए कर तत्वों का इस्तेमाल किया जाता है (यह अपने 100) है) डेटाबेस से क्वेरी की गणना, के रूप में डेटाबेस MemberViewModel के बारे में कुछ नहीं जानता के लिए यह एक संभव Where(x=>{filter}) मिलान सदस्यों की गिनती वापस आ जाएगी (यह आपका 150 है)

एक साधारण ठीक ToList() बजाय AsQueryable() लिखने के लिए है। मैं LINQ-to-SQL पर भयानक जंगली आपको AsQueryable().ToList()

एक संभावित समाधान पहले फ़िल्टर करना है।

var membersQ=db.Members.Include(x=> x.Contact).Where(a=> a.Contact != null).Select(i=> new MemberViewModel(){ 
    Name = i.Contact.Name, 
    ContactId= i.Contact.Id, 
    CreatedDate= i.CreatedDate 
}).AsQueryable(); 

अब membersQ.Count() वर membersQ.ToList().Count()

बराबर होना चाहिए और पेजिंग उपयोग memberQ.Skip(x).Take(y) इस एसक्यूएल पर और वेबसर्वर पर नहीं प्रदर्शन किया जाएगा करने के लिए। जब तक आप ToList() तब तक सब कुछ सर्वर पर है क्योंकि अचानक सर्वर मेमोरी में डेटा का एक सेट है।

कि न काम, तो आप न एक foreigh कुंजी मौजूद है, तो आप सिर्फ फिल्टर ContactID के बजाय संपर्क में फिल्टर करने के लिए बदल सकता है। आप तो अपने एसक्यूएल संशोधित नल सदस्य में ContactID बनाने के लिए और करने के लिए से सदस्यों ContactID और संपर्क की आईडी एक विदेशी कुंजी जोड़ने के लिए पहुँच है, तो: के एक FK (विदेशी कुंजी)

जोड़े विदेशी कुंजी जोड़ें।

फिर अपने डीबीएमएल से दो टेबल हटाएं और उन्हें डीबी एक्सप्लोरर से फिर से खींचें। अब आप बिना भी शामिल है के रूप में है "लेज़ी लोड" हो जाएगा (जिसका अर्थ है कोई भी शामिल है) की तुलना में बस कोड का उपयोग करने में सक्षम होना चाहिए उत्सुक भरी हुई है (यानी आप क्या लोड करने के लिए कहना है)

+0

हाँ, 'ToList' समस्या का समाधान करता है, लेकिन एक और समस्या पैदा करता है। ** बहुत अधिक डेटा ** 'ToList' डेटाबेस से सभी रिकॉर्ड्स सूचीबद्ध करेगा, जब उपयोग किए जाने वाले पेजिंग की आवश्यकता नहीं होती है। हाँ मैंने पेजिंग का उदाहरण नहीं दिया है, लेकिन मैंने पोस्ट में उद्धृत किया है कि पेजिंग होगी। गिनती पेजिंग के बिना डेटाबेस में रिकॉर्ड्स की कुल गणना है। – Ruchan

+0

नीचे एक उदाहरण जोड़ा गया है, देखें कि क्या –

+0

में मदद नहीं मिली है मैंने 'ए। संपर्क! = Null' का उपयोग किया है और यह अभी भी काम नहीं करता है। परिणामी क्वेरी 'गणना') ' – Ruchan

0
var members = db.Contracts.Where(w=> w.Member != null).Select(i=> new MemberViewModel(){ 
Name = i.Contact.Name, 
ContactId= i.Contact.Id, 
CreatedDate= i.CreatedDate 
}).AsQueryable()); 

यह कुछ हद तक है कि आप के बाद क्या कर रहे हैं?

1

सिर्फ मनोरंजन के लिए इस

var members=db.Members.Include(x=> x.Contact) 
         .Where(x => x.Contact != null) 
         .Count(); 
संबंधित मुद्दे