एंटिटी फ्रेमवर्क linq क्वेरी शामिल करें () कई बच्चे संस्थाएं


176

यह वास्तव में एक प्रारंभिक प्रश्न हो सकता है लेकिन कई बच्चों वाली संस्थाओं को शामिल करने का एक अच्छा तरीका क्या हो सकता है जब यह प्रश्न लिखे कि यह तीन स्तर (या अधिक) है?

यानी मैं 4 टेबल है: Company, Employee, Employee_CarऔरEmployee_Country

कंपनी का कर्मचारी के साथ 1: m संबंध है।

कर्मचारी का Employee_Car और Employee_Country दोनों के साथ 1: m संबंध है।

यदि मैं एक क्वेरी लिखना चाहता हूं जो सभी 4 तालिकाओं से डेटा लौटाता है, तो मैं वर्तमान में लिख रहा हूं:

Company company = context.Companies
                         .Include("Employee.Employee_Car")
                         .Include("Employee.Employee_Country")
                         .FirstOrDefault(c => c.Id == companyID);

वहाँ एक और अधिक सुंदर तरीका है! यह लंबी घुमावदार है और भयावह एसक्यूएल उत्पन्न करती है

मैं वीएस 2010 के साथ ईएफ 4 का उपयोग कर रहा हूं

जवाबों:


201

एक्सटेंशन विधियों का उपयोग करें । अपने ऑब्जेक्ट संदर्भ के नाम के साथ NameOfContext बदलें ।

public static class Extensions{
   public static IQueryable<Company> CompleteCompanies(this NameOfContext context){
         return context.Companies
             .Include("Employee.Employee_Car")
             .Include("Employee.Employee_Country") ;
     }

     public static Company CompanyById(this NameOfContext context, int companyID){
         return context.Companies
             .Include("Employee.Employee_Car")
             .Include("Employee.Employee_Country")
             .FirstOrDefault(c => c.Id == companyID) ;
      }

}

फिर आपका कोड बन जाता है

     Company company = 
          context.CompleteCompanies().FirstOrDefault(c => c.Id == companyID);

     //or if you want even more
     Company company = 
          context.CompanyById(companyID);

लेकिन मैं इसे इस तरह इस्तेमाल करना चाहूंगा: //inside public static class Extensions public static IQueryable<Company> CompleteCompanies(this DbSet<Company> table){ return table .Include("Employee.Employee_Car") .Include("Employee.Employee_Country") ; } //code will be... Company company = context.Companies.CompleteCompanies().FirstOrDefault(c => c.Id == companyID); //same for next advanced method
हामिद

बुल्सये निक्स। एक्सटेंशन कॉल के लिए पहला पोर्ट होना चाहिए ... अच्छी तरह से ... पूर्वनिर्धारित कार्यक्षमता का विस्तार।
ComeIn

12
वर्षों बाद, मैं स्ट्रिंग-आधारित शामिल करने की सिफारिश नहीं करूंगा, क्योंकि वे रनटाइम सुरक्षित नहीं हैं। अगर नेविगेशन प्रॉपर्टी का नाम कभी बदल जाता है या गलत वर्तनी हो जाता है, तो यह टूट जाएगा। इसके बजाय टाइप किए गए शामिल का उपयोग करके दृढ़ता से सुझाव दें।
जेफ पुतज

2
nameof (वर्ग) की शुरुआत के बाद से इस दृष्टिकोण का सुरक्षित रूप से उपयोग करना संभव है। यदि इकाई का नाम बदलता है, तो उसे संकलन के दौरान उठाया जाएगा। "।": उदाहरण context.Companies.Include (nameof (कर्मचारी)) मामले में एक की जरूरत है नाम और नीचे जाने के लिए + nameof (Employee_Car) nameof (कर्मचारी) के साथ concatent + करने के लिए है
कार्ल

विस्तार विधि तकनीक संकलित प्रश्नों के लिए काम नहीं करती है (कम से कम EFCore पर नहीं) यहाँ पुष्टि की गई है: github.com/aspnet/EntityFrameworkCore/issues/7016
डंज़

156

EF 4.1 से EF 6

एक जोरदार टाइप किया गया है.Include जो उचित गहराई तक चयन अभिव्यक्ति प्रदान करके निर्दिष्ट लोडिंग की आवश्यक गहराई को निर्दिष्ट करने की अनुमति देता है:

using System.Data.Entity; // NB!

var company = context.Companies
                     .Include(co => co.Employees.Select(emp => emp.Employee_Car))
                     .Include(co => co.Employees.Select(emp => emp.Employee_Country))
                     .FirstOrDefault(co => co.companyID == companyID);

दोनों उदाहरणों में उत्पन्न Sql अभी भी सहज नहीं है, लेकिन पर्याप्त प्रदर्शन करता है। मैंने यहाँ GitHub पर एक छोटा सा उदाहरण दिया है

ईएफ कोर

EF Core में एक नई एक्सटेंशन विधि है .ThenInclude(), हालाँकि सिंटैक्स थोड़ा अलग है :

var company = context.Companies
                     .Include(co => co.Employees)
                           .ThenInclude(emp => emp.Employee_Car)
                      ...

डॉक्स के अनुसार, मैं .ThenIncludeआपकी पवित्रता को बनाए रखने के लिए अतिरिक्त 'इंडेंट' रखूंगा।

अप्रचलित जानकारी (ऐसा न करें):

कई पोते लोडिंग को एक चरण में किया जा सकता है, लेकिन इसके लिए अगले नोड के नीचे आने से पहले ग्राफ को वापस करने के लिए एक अजीब उलट आवश्यकता होती है (NB: यह साथ काम नहीं करता है AsNoTracking()- आपको एक रनटाइम त्रुटि मिलेगी):

var company = context.Companies
         .Include(co => 
             co.Employees
                .Select(emp => emp.Employee_Car
                    .Select(ec => ec.Employee)
                    .Select(emp2 => emp2.Employee_Country)))
         .FirstOrDefault(co => co.companyID == companyID);

इसलिए मैं पहले विकल्प (एक लीफ प्रति लीफ डेप्थ मॉडल) को शामिल करूंगा।


4
मैं सोच रहा था कि इसे कैसे टाइप किया जाए। सेलेक्ट वाले बच्चों को जवाब देना था!

1
"Co.Employees.Select (...)" के मेरे समीकरण में "सिलेक्ट" पर एक सिंटैक्स त्रुटि दिखाई देती है, यह कहते हुए कि "कर्मचारियों" में 'Select' [या एक्सटेंशन विधि] के लिए परिभाषा नहीं है। मैंने System.Data.Entity को शामिल किया है। मैं केवल सम्मिलित तालिका से एक कॉलम प्राप्त करना चाहता हूं।
क्रिस वॉल्श

1
मेरे पास एक पेरेंट टेबल थी जो एक ही चाइल्ड टेबल को दो बार संदर्भित कर रही थी। पुरानी स्ट्रिंग में सिंटैक्स शामिल है सही रिश्ते को प्रीलोड करना मुश्किल था। यह तरीका बहुत अधिक विशिष्ट है। कृपया नामस्थान को ध्यान में रखें System.Data.Entity को दृढ़ता से टाइप करने के लिए शामिल करें।
कार्ल

1
.Net

27

आपको ब्याज का यह लेख मिल सकता है जो codeplex.com पर उपलब्ध है ।

यह आलेख उन प्रश्नों को व्यक्त करने का एक नया तरीका प्रस्तुत करता है जो घोषणात्मक ग्राफ़ आकृतियों के रूप में कई तालिकाओं को फैलाते हैं।

इसके अलावा, लेख में EF प्रश्नों के साथ इस नए दृष्टिकोण की संपूर्ण प्रदर्शन तुलना है। इस विश्लेषण से पता चलता है कि GBQ EF प्रश्नों से बेहतर प्रदर्शन करता है।


इसे वास्तविक दुनिया के अनुप्रयोग में कैसे लागू किया जा सकता है?
विक्टर.उदयक

4

एक संदर्भ संपत्ति या लोड () कॉल करने के बजाय, आप चाइल्ड ऑब्जेक्ट्स को सीधे लोड करने के लिए LINQ से एंटिटीज क्वेरी का निर्माण कैसे करते हैं

कोई अन्य तरीका नहीं है - आलसी लोडिंग को लागू करने के अलावा।

या मैनुअल लोडिंग…।

myobj = context.MyObjects.First();
myobj.ChildA.Load();
myobj.ChildB.Load();
...
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.