2008-09-17 11 views
6

मैं निम्नलिखित (सुंदर मानक) तालिका संरचना है:कई LINQ क्वेरी में कितने लोड करें?

Post <-> PostTag <-> Tag 

मान लीजिए मैं निम्नलिखित रिकॉर्ड:

PostID Title 
1,  'Foo' 
2,  'Bar' 
3,  'Baz' 

TagID Name 
1, 'Foo' 
2, 'Bar' 

PostID TagID 
1  1 
1  2 
2  2 

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

मैं सभी पोस्ट और उसके टैग को एक प्रश्न में लोड करना चाहता हूं लेकिन ऑपरेटरों का सही संयोजन नहीं ढूंढ पा रहा हूं। मैं टैग्स के साथ पदों को केवल या बार-बार पोस्ट लोड करने में सक्षम हूं जब एक से अधिक टैग

ऊपर दिए गए डेटाबेस को देखते हुए, मैं पोस्ट ऑब्जेक्ट्स की संग्रह संपत्ति में तीन पोस्ट और उनके टैग (यदि कोई हो) प्राप्त करना चाहता हूं। क्या यह सभी के लिए संभव है?

धन्यवाद

उत्तर

0

मैं एक और पोस्ट में इस का उत्तर दिया है: About eager loading। आपके मामले में यह शायद होगा की तरह कुछ:

DataLoadOptions options = new DataLoadOptions();  
options.LoadWith<Post>(p => p.PostTag); 
options.LoadWith<PostTag>(pt => pt.Tag); 

हालांकि सावधान रहना - DataLoadOptions सेट किया जाना चाहिए से पहले किसी भी क्वेरी डेटाबेस को भेजा जाता है - यदि नहीं, तो एक अपवाद फेंक दिया जाता है (पता नहीं क्यों यह इस तरह का है Linq2Sql - शायद बाद के संस्करण में तय किया जाएगा)।

0

मुझे खेद नहीं है, उत्सुक लोडिंग प्रति पोस्ट प्रति टैग एक अतिरिक्त क्वेरी निष्पादित करेगी।

इस कोड के साथ परीक्षण किया गया:

var options = new DataLoadOptions(); 
options.LoadWith<Post>(p => p.PostTags); 
options.LoadWith<PostTag>(pt => pt.Tag); 
using (var db = new BlogDataContext()) 
{ 
    db.LoadOptions = options; 
    return (from p in db.Posts 
      where p.Status != PostStatus.Closed 
      orderby p.PublishDateGmt descending 
      select p); 
} 

उदाहरण डेटाबेस यह 4 प्रश्नों जो उत्पादन में स्वीकार्य नहीं है पर अमल होता है। क्या कोई दूसरा समाधान सुझा सकता है?

धन्यवाद

1

यह थोड़ा अजीब है, क्योंकि

DataLoadOptions o = new DataLoadOptions (); 
o.LoadWith<Listing> (l => l.ListingStaffs); 
o.LoadWith<ListingStaff> (ls => ls.MerchantStaff); 
ctx.LoadOptions = o; 

IQueryable<Listing> listings = (from a in ctx.Listings 
      where a.IsActive == false 
          select a); 
List<Listing> list = listings.ToList (); 

परिणाम एक क्वेरी जैसे:

SELECT [t0].*, [t1].*, [t2].*, (
SELECT COUNT(*) 
FROM [dbo].[LStaff] AS [t3] 
INNER JOIN [dbo].[MStaff] AS [t4] ON [t4].[MStaffId] = [t3].[MStaffId] 
WHERE [t3].[ListingId] = [t0].[ListingId] 
) AS [value] 
FROM [dbo].[Listing] AS [t0] 
LEFT OUTER JOIN ([dbo].[LStaff] AS [t1] 
INNER JOIN [dbo].[MStaff] AS [t2] ON [t2].[MStaffId] = [t1].[MStaffId]) ON 
[t1].[LId] = [t0].[LId] WHERE NOT ([t0].[IsActive] = 1) 
ORDER BY [t0].[LId], [t1].[LStaffId], [t2].[MStaffId] 

(मैं नाम छोटा और * जोड़ा चयन पर है)।

तो ऐसा लगता है कि यह ठीक है।

1

मुझे खेद है। आपके द्वारा प्रदान किया जाने वाला समाधान काम करता है, लेकिन मुझे पता चला कि टेक (एन) के साथ पेजिंग करते समय यह टूट जाता है।

public IList<Post> GetPosts(int page, int records) 
{ 
    var options = new DataLoadOptions(); 
    options.LoadWith<Post>(p => p.PostTags); 
    options.LoadWith<PostTag>(pt => pt.Tag); 
    using (var db = new BlogDataContext()) 
    { 
     db.LoadOptions = options; 
     return (from p in db.Posts 
       where p.Status != PostStatus.Closed 
       orderby p.PublishDateGmt descending 
       select p) 
       .Skip(page * records) 
       //.Take(records) 
       .ToList(); 
    } 
} 
लें साथ

() विधि टिप्पणी की कि यह क्या आप पोस्ट करने के लिए एक क्वेरी के समान उत्पन्न करता है लेकिन अगर मैं टेक() जोड़ने के लिए इसे फिर से उत्पन्न करता है 1 + N एक्स: पूरा विधि मैं उपयोग कर रहा हूँ पीछा कर रहा है एम प्रश्न

तो, मुझे लगता है कि अब मेरा प्रश्न है: क्या अंक() विधि को पगनेट रिकॉर्ड करने के लिए कोई प्रतिस्थापन है?

धन्यवाद

2

आहा! इसने काम कर दिया।

को भी यही समस्या यहां हो रही है अगर मैं क्या किया है:

public IList<Post> GetPosts(int page, int record) 
{ 
    var options = new DataLoadOptions(); 
    options.LoadWith<Post>(p => p.PostTags); 
    options.LoadWith<PostTag>(pt => pt.Tag); 
    using (var db = new DatabaseDataContext(m_connectionString)) 
    { 
     var publishDateGmt = (from p in db.Posts 
           where p.Status != PostStatus.Hidden 
           orderby p.PublishDateGmt descending 
           select p.PublishDateGmt) 
           .Skip(page * record) 
           .Take(record) 
           .ToList() 
           .Last(); 
     db.LoadOptions = options; 
     return (from p in db.Posts 
       where p.Status != PostStatus.Closed 
        && p.PublishDateGmt >= publishDateGmt 
       orderby p.PublishDateGmt descending 
       select p) 
       .Skip(page * record) 
       .ToList(); 
    } 
} 

यह प्रत्येक पद के लिए केवल दो प्रश्नों और भार सभी टैग निष्पादित करता है।

विचार हमें अंतिम पोस्ट पर क्वेरी को सीमित करने के लिए कुछ मूल्य प्राप्त करना है (इस मामले में PublishDateGmt कॉलम पर्याप्त होगा) और फिर दूसरी क्वेरी को टेक() के बजाय उस मान से सीमित करें।

आपकी सहायता सिरोक्रो के लिए धन्यवाद।

0

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

var q = from p in db.Posts 
     where db.Posts.Take(10).Contains(p) 
     select p; 

ऊपर दिए गए प्रश्न के साथ डेटालोडऑप्शन का उपयोग करके आप अपने संबंधित टैग समेत पहले दस पदों को एक ही प्रश्न में देंगे। परिणामी एसक्यूएल निम्नलिखित का संक्षिप्त संस्करण होगा:

SELECT p.PostID, p.Title, pt.PostID, pt.TagID, t.TagID, t.Name FROM Posts p 
JOIN PostsTags pt ON p.PostID = pt.PostID 
JOIN Tags t ON pt.TagID = t.TagID 
WHERE p.PostID IN (SELECT TOP 10 PostID FROM Posts) 
संबंधित मुद्दे