2010-11-01 29 views
15
EmployeeId Name ManagerId 
------------------------------ 
1   A  null 
2   B  null 
3   C  1 
4   D  3 
5   E  2 

बस इस तालिका का उपयोग करके, लिनक्स क्वेरी (linq से sql का उपयोग करके) को मूल डेटा को पुन: प्राप्त करने के लिए कैसे लिखा जा सकता है।linq से sql रिकर्सिव क्वेरी

उदाहरण के लिए

अगर नियोक्ता पहचान चयनित 4 यह ईद के साथ कर्मचारियों की सूची देना चाहिए: 4, 3, 1

धन्यवाद।

+0

4,3,1 ?? आप किस तरह का एल्गोरिदम कह रहे हैं? :) क्या होगा यदि मैं 5 का चयन करता हूं? –

+0

@ सेर्कन: उसे आईडी के साथ कर्मचारी (ओं) की एक सूची देनी चाहिए: 5, 2 – stackoverflowuser

+0

मैं अभी भी आपको समझ नहीं सकता। 2 प्रबंधक है? यदि हां, जैसा कि मैं समझता हूं। आप EmployeeId और इस कर्मचारी के प्रबंधक के रूप में EmployeeId के रूप में चयनित चाहते हैं? –

उत्तर

0
var managedEmployees = ctx.Employess.Where(x => x.ManagerId = 4).AsEnumerable() 

यदि आप एक बार में पूरे पेड़ चाहते हैं, तो समाधान अधिक जटिल है। एसक्यूएल में सीटीई के साथ सबसे अच्छा किया गया, मुझे नहीं पता कि ईएफ linq का उपयोग करके इसे संभाल सकता है- अधिकतर एक पुनरावृत्त समाधान का उपयोग किया जाएगा।

0

आप की तरह

int id = 5; 
    do 
    { 
     employee= employeedata.FirstOrDefault(e => e.EmployeeId == id); 

    } while (employee != null && (id = employee.ManagerId) != 0); 

कुछ कर सकते हैं लेकिन यह करने के बाद से यह एक अनंत लूप में अटक कर सकते हैं एक नहीं बल्कि खतरनाक बात है। जहां तक ​​मुझे पता है कि एक रिकर्सिव क्वेरी सीधे तब तक करने का कोई तरीका नहीं है जब तक आप एक संग्रहीत प्रक्रिया नहीं लिखते।

+0

हाँ हाँ मुझे पता है कि यह एक संग्रहित प्रो के भीतर सीटीई लिखकर किया जा सकता है। मैं देखना चाहता था कि लिनक के माध्यम से एसक्यूएल अभिव्यक्ति के माध्यम से सीधे प्राप्त करने का कोई तरीका है या नहीं। ऐसा लगता है जैसे जवाब "नहीं" की ओर बढ़ रहे हैं। – stackoverflowuser

+0

हम्म :) मैंने एक अभिव्यक्ति नहीं सुना जो रिकर्सिव बना सकता है। मैंने सोचा कि आप प्रोग्राममैटिकल कैसे बनाना चाहते हैं :) –

7

यह .sHierarchy() एक्सटेंशन विधि उपयोगी हो सकती है: link। हालांकि, यह केवल आपके परिणामों को लिंक किए गए ऑब्जेक्ट्स में फेंकने का एक आसान तरीका प्रदान करके काम करता है। ऐसा करने के लिए, यह केवल सभी रिकॉर्ड प्राप्त करेगा और अपनी स्थानीय रिकर्सिव क्वेरी चलाएगा।

यदि आप एक LINQ क्वेरी की तलाश में हैं जो LINQ से SQL के माध्यम से सीधे रिकर्सिव SQL क्वेरी में अनुवाद करेगा, तो आपको यह नहीं मिलेगा। सर्वोत्तम प्रदर्शन के लिए, एक संग्रहित प्रक्रिया में एक सीटीई शायद आप जो खोज रहे हैं। यदि आपके पास वास्तव में एक साधारण पृष्ठ है जिसे पूरे पेड़ को लोड करने की आवश्यकता है, तो AsHierarchy विधि शायद आपकी आवश्यकताओं के अनुरूप होगी। आप linqpad आप स्थापित किया है

public static IEnumerable<Employee> GetTreeForEmployeeNumber(this IEnumerable<Employee> source, int startingId) { 
     var result = source.Where(x => x.EmployeeId == startingId).FirstOrDefault(); 
     if (result != null) { 
      var resultAsE = new [] { result }; 
      if (!result.ManagerId.HasValue) 
       return resultAsE; 
      return resultAsE.Union(source.Except(resultAsE).GetTreeForEmployeeNumber(result.ManagerId.Value)); 
     } 
     return new Employee [] { }; 
    } 

:

2

मुझे यकीन है कि अगर यह है कि वास्तव में आप क्या चाहते हैं, लेकिन यहाँ नहीं हूँ एक पुनरावर्ती विधि अनंत लूप में प्रवेश करने नहीं कुछ LINQ सुनिश्चित करती है कि का उपयोग करता है निम्न स्क्रिप्ट के साथ इसका परीक्षण कर सकते हैं:

void Main() 
{ 
    var lst = new [] { 
     new Extensions.Employee{ EmployeeId = 1, Name = "A", ManagerId = null }, 
     new Extensions.Employee{ EmployeeId = 2, Name = "B", ManagerId = null }, 
     new Extensions.Employee{ EmployeeId = 3, Name = "C", ManagerId = 1 }, 
     new Extensions.Employee{ EmployeeId = 4, Name = "D", ManagerId = 3 }, 
     new Extensions.Employee{ EmployeeId = 5, Name = "E", ManagerId = 2 } 
    }; 

    lst.GetTreeForEmployeeNumber(4).Dump(); 
} 

public static class Extensions { 

    public class Employee { 
     public int EmployeeId { get; set; } 
     public string Name { get; set; } 
     public int? ManagerId { get; set; } 
    } 

    public static IEnumerable<Employee> GetTreeForEmployeeNumber(this IEnumerable<Employee> source, int startingId) { 
     var result = source.Where(x => x.EmployeeId == startingId).FirstOrDefault(); 
     if (result != null) { 
      var resultAsE = new [] { result }; 
      if (!result.ManagerId.HasValue) 
       return resultAsE; 
      return resultAsE.Union(source.Except(resultAsE).GetTreeForEmployeeNumber(result.ManagerId.Value)); 
     } 
     return new Employee [] { }; 
    } 
}