EF कोड प्रथम: यादृच्छिक पंक्तियाँ कैसे प्राप्त करें


82

मैं ऐसी क्वेरी कैसे बना सकता / सकती हूँ जहाँ मैं यादृच्छिक पंक्तियों को पुनः प्राप्त करूँ?

अगर मैं इसे एसक्यूएल में लिखता तो मैं न्यूड () पर एक आदेश देता और ऊपर से n की पंक्तियों को काट देता। वैसे भी पहले EF कोड में ऐसा करने के लिए?

मैंने एक क्वेरी बनाने की कोशिश की है जो newid () का उपयोग करती है और DbSet.SqlQuery () का उपयोग करके इसे निष्पादित करती है। जबकि यह काम करता है, इसका समाधान सबसे साफ नहीं है।

इसके अलावा, सभी पंक्तियों को पुनः प्राप्त करने और एक नई मार्गदर्शिका द्वारा उन्हें छांटने की कोशिश की गई। यद्यपि पंक्तियों की संख्या काफी कम है, फिर भी इसका अच्छा समाधान नहीं है।

कोई विचार?



जवाबों:


164

बस कॉल करना:

something.OrderBy(r => Guid.NewGuid()).Take(5)

नमस्ते यह ठीक काम करता है, लेकिन क्या यह तेजी से होगा जब तालिका में अधिक पंक्तियां
होंगी

3
यह प्रश्न देखें , यह दुर्भाग्य से टूटा हुआ है। ऐसा लगता OrderByहै कि रैंकिंग फ़ंक्शन स्थिर होने का अनुमान लगाता है, जो यादृच्छिक जनरेटर के साथ ऐसा नहीं है। Linq संस्थाओं को इसका अनुवाद एक sql क्वेरी में किया जाता है, जिसे एक ही इकाई के लिए अलग रैंकिंग मिल सकती है (जैसे ही आपके प्रश्नों का उपयोग होता है Include)। फिर यह परिणाम सूची में डुप्लिकेट प्राप्त करने के लिए इकाई का कारण बनता है।
फ्रैडरिक

1
यकीन नहीं है कि मैं रैंडम पंक्तियों के एक आयरनक्लाड सेट की आवश्यकता वाले कार्यों के लिए इस पर भरोसा करूंगा - मैं इसके बजाय stackoverflow.com/a/654910/12484 या stackoverflow.com/a/648247/12484 पर जाऊंगा - लेकिन यह सरल तरीका है मेरी जरूरत के लिए ठीक काम किया है जो एक गैर-ग्राहक-सामना करने वाली सुविधा के लिए एकल छद्म यादृच्छिक पंक्ति के लिए कहा जाता है। +1।
जॉन श्नाइडर

@ टूलकिट शायद इतना अजीब नहीं है, अगर एंटिटी में ओरेकल के बराबर Guid.NewGuid()(मतलब, लिनकॉटसक्कल या जो कुछ भी बदल जाता है, NEWID()लेकिन कोई भी ओरेकल के लिए समान नहीं है)।
ड्रूज़

क्या यह दृष्टिकोण कुशल है? मैंने कहीं और पाया कि यह विधि कुछ प्रदर्शन पर विचार करने के लिए-निराश है।
मोहम्मद नौरेलिन

40

दो विकल्पों की तुलना:


छोड़ें (पंक्तियों की यादृच्छिक संख्या)

तरीका

private T getRandomEntity<T>(IGenericRepository<T> repo) where T : EntityWithPk<Guid> {
    var skip = (int)(rand.NextDouble() * repo.Items.Count());
    return repo.Items.OrderBy(o => o.ID).Skip(skip).Take(1).First();
}
  • 2 प्रश्न लेता है

SQL उत्पन्न किया

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

SELECT TOP (1) [Extent1].[ID]            AS [ID],
               [Extent1].[Name]          AS [Name],
               [Extent1].[Age]           AS [Age],
               [Extent1].[FavoriteColor] AS [FavoriteColor]
FROM   (SELECT [Extent1].[ID]                                  AS [ID],
               [Extent1].[Name]                                AS [Name],
               [Extent1].[Age]                                 AS [Age],
               [Extent1].[FavoriteColor]                       AS [FavoriteColor],
               row_number() OVER (ORDER BY [Extent1].[ID] ASC) AS [row_number]
        FROM   [dbo].[People] AS [Extent1]) AS [Extent1]
WHERE  [Extent1].[row_number] > 15
ORDER  BY [Extent1].[ID] ASC;

GUID

तरीका

private T getRandomEntityInPlace<T>(IGenericRepository<T> repo) {
    return repo.Items.OrderBy(o => Guid.NewGuid()).First();
}

SQL उत्पन्न किया

SELECT TOP (1) [Project1].[ID]            AS [ID],
               [Project1].[Name]          AS [Name],
               [Project1].[Age]           AS [Age],
               [Project1].[FavoriteColor] AS [FavoriteColor]
FROM   (SELECT NEWID()                   AS [C1],
               [Extent1].[ID]            AS [ID],
               [Extent1].[Name]          AS [Name],
               [Extent1].[Age]           AS [Age],
               [Extent1].[FavoriteColor] AS [FavoriteColor]
        FROM   [dbo].[People] AS [Extent1]) AS [Project1]
ORDER  BY [Project1].[C1] ASC

1
तुलना के लिए धन्यवाद, यह वास्तव में मदद करता है
हाओबो जूल

यह सही उत्तर है, चिह्नित उत्तर की अनुशंसा नहीं की जाती है क्योंकि यह कुछ प्रदर्शन समस्याओं का कारण हो सकता है।
जैकब

1
प्रश्न बहुवचन में "पंक्तियाँ" बताता है, आप उस पर अपना समाधान कैसे लागू करेंगे? मेरे लिए ऐसा लगता है कि मुझे एक ही एसक्यूएल को कई बार निष्पादित करना OrderBy(o => o.ID).Skip(skip).Take(5)होगा , क्योंकि यह वास्तव में यादृच्छिक नहीं होगा, जो प्रदर्शन में अड़चन बन सकता है।
माइक मैट

@ मायकेमैट बस " .First()" को हटा दें । मैं कुछ अन्य उत्तरों के बीच तुलना प्रस्तुत कर रहा था जिन्हें मैंने देखा है जो अब प्रकट नहीं होते हैं, इसलिए आपकी बात दोगुनी है। लेकिन NewGuidसमाधान में आपके द्वारा वर्णित समस्या नहीं होगी।
at१
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.