LINQ

2008-12-03 14 views
9

एक controversial blog post आज में, Hackification क्या संस्थाओं ढांचे के लिए नए LINQ में एक बग हो गया लगता है पर pontificates:LINQ

var alice = data.Customers.First(c => c.Name == "Alice"); 
:

मान लीजिए मैं ग्राहक की खोज करने

ठीक है, जो अच्छी तरह से काम करता है। अब चलो देखें कि क्या मैं उसके आदेश से एक पा सकते हैं करते हैं:

var order = (from o in alice.Orders 
      where o.Item == "Item_Name" 
      select o).FirstOrDefault(); 

LINQ करने वाली एसक्यूएल बच्चे पंक्ति मिल जाएगा। LINQ-to-Entities चुपचाप कुछ भी वापस नहीं आएगा। मेरी खोज को दोहरा

foreach(var order in data.Orders) { 
Console.WriteLine("Order: " + order.Item); } 

और अब:

अब मैं के माध्यम से डेटाबेस में सभी आदेश पुनरावृति लगता है जाने

var order = (from o in alice.Orders 
      where o.Item == "Item_Name" 
      select o).FirstOrDefault(); 

वाह! LINQ-to-Entities अचानक मुझे बता रहा है कि बच्चे की वस्तु मौजूद है, मुझे पहले बताए हुए कि यह नहीं था!

मेरे आरंभिक प्रतिक्रिया है कि यह एक बग होना ही था था, लेकिन आगे विचार (और backed up by the ADO.NET Team) के बाद, मुझे एहसास हुआ है कि इस व्यवहार इकाई की रूपरेखा द्वारा नहीं आलसी लोड हो रहा है आदेश सबक्वेरी जब ऐलिस से खींचा जाता है कारण होता था DataContext।

var order = (from o in alice.Orders 
     where o.Item == "Item_Name" 
     select o).FirstOrDefault(); 

और किसी भी तरह से DataContext पर न गया, जबकि उसके foreach पाश:

foreach(var order in data.Orders) 

DataContext ऐक्सेस करना है

इसका कारण यह है आदेश में एक LINQ-टू-वस्तु क्वेरी है ।

LINQ-to-SQL वास्तव में ऑर्डर के लिए आलसी लोड गुणों का निर्माण करता है, ताकि जब एक्सेस किया जाए, तो एक और क्वेरी करेगा, LINQ से Entities आपको संबंधित डेटा को मैन्युअल रूप से पुनर्प्राप्त करने के लिए छोड़ देता है।

अब, मैं ओआरएम का बड़ा प्रशंसक नहीं हूं, और यह सटीक कारण है। मैंने पाया है कि आप अपने उंगलियों पर तैयार सभी डेटा प्राप्त करने के लिए, वे बार-बार आपकी पीठ के पीछे पूछताछ निष्पादित करते हैं, उदाहरण के लिए, उपरोक्त linq-to-sql क्वेरी ऑर्डर प्राप्त करने के लिए ग्राहकों की प्रति पंक्ति अतिरिक्त क्वेरी चला सकती है ।

हालांकि, ऐसा करने वाला ईएफ मुख्य रूप से कम से कम आश्चर्य के सिद्धांत का उल्लंघन करता प्रतीत होता है। हालांकि यह चीजों को करने का तकनीकी रूप से सही तरीका है (आपको ऑर्डर पुनर्प्राप्त करने के लिए दूसरी क्वेरी चलनी चाहिए, या दृश्य से सब कुछ पुनर्प्राप्त करना चाहिए), ऐसा व्यवहार नहीं करता है जैसे आप ओआरएम से अपेक्षा करेंगे।

तो, क्या यह अच्छी ढांचा डिजाइन है? या माइक्रोसॉफ्ट हमारे लिए यह सोचने पर है?

उत्तर

1

मुझे ओआरएम के बारे में बहुत कुछ पता नहीं है, लेकिन लिंककॉक्ल और लिंक्टोइन्टिटीज के उपयोगकर्ता के रूप में मुझे उम्मीद है कि जब आप ऐलिस के ऑर्डर पूछने का प्रयास करेंगे तो यह आपके लिए अतिरिक्त क्वेरी करता है जब आप linq क्वेरी बनाते हैं (जैसा कि विरोध किया गया है कुछ भी पूछताछ या हर पंक्ति के लिए सब कुछ पूछताछ करने के लिए)।

यह उम्मीद करना

from o in alice.Orders where o.Item == "Item_Name" select o 

कि कारणों लोग ORM का उपयोग पहली जगह में (डेटा का उपयोग आसान बनाने के लिए) में से एक है को देखते हुए काम करने के लिए प्राकृतिक लगता है।

जितना अधिक मैंने लिंकटोइन्टिटीज के बारे में पढ़ा उतना ही मुझे लगता है कि LinqToSql अधिकांश डेवलपर्स को पर्याप्त रूप से पूरा करने की आवश्यकता है। मुझे आमतौर पर टेबल की एक-से-एक मैपिंग की आवश्यकता होती है।

2

यदि LINQ-to-Sql और LINQ-to-Entities दो अलग-अलग कंपनियों से आए हैं, तो यह एक स्वीकार्य अंतर होगा - कोई कानून नहीं है कि सभी LINQ-to-Whatevers को उसी तरह लागू किया जाना चाहिए।

हालांकि, वे दोनों माइक्रोसॉफ्ट से आते हैं - और हम कैसे दो अलग अलग चीजें हैं जो, उनके चेहरे पर, ठीक उसी देखने के उपयोग करने के लिए पता करने के लिए अपने आंतरिक विकास टीमों और प्रक्रियाओं के अंतरंग ज्ञान की जरूरत नहीं होनी चाहिए।

ओआरएम के पास उनकी जगह है, और वास्तव में लोगों को काम करने की कोशिश करने वाले लोगों के लिए एक अंतर भरते हैं, लेकिन ओआरएम उपयोगों को पता होना चाहिए कि उनके ओआरएम को चीजें कैसे मिलती हैं - इसे एक अभेद्य काले बॉक्स की तरह व्यवहार करने से आपको परेशानी होगी ।

5

तो, क्या यह अच्छी ढांचा डिजाइन है? या माइक्रोसॉफ्ट हमारे लिए यह सोचने पर है?

अच्छी तरह से विश्लेषण करते हैं - माइक्रोसॉफ्ट की सभी सोचें हमें वास्तव में हमें आलसी प्रोग्रामर बनाने की ज़रूरत नहीं है। लेकिन आम तौर पर, यह हमें अधिक उत्पादक बनाता है (अधिकांश भाग के लिए)। तो वे से सोच रहे हैं या क्या वे हमारे लिए सोच रहे हैं?

1

भले ही आपको माइक्रोसॉफ्ट की आंतरिक विकास टीमों और प्रक्रियाओं के बारे में पता नहीं होना चाहिए, इस तथ्य का तथ्य यह है कि ये दो तकनीकें दो पूरी तरह से अलग जानवर हैं।

LINQ से SQL के लिए डिज़ाइन निर्णय सादगी के लिए, आलसी लोड लोड संग्रह के लिए था। ADO.NET इकाई फ्रेमवर्क टीम उपयोगकर्ता को जानने के बिना क्वेरी निष्पादित करना चाहता है ताकि वे एपीआई को पहली रिलीज के लिए स्पष्ट रूप से लोड करने के लिए डिज़ाइन कर सकें।

LINQ से SQL को ADO.NET टीम को सौंप दिया गया है और इसलिए आप भविष्य में एपीआई का एकीकरण देख सकते हैं, या LINQ से SQL को इकाई फ्रेमवर्क में तब्दील कर दिया जा सकता है, या आप LINQ से SQL उपरोक्त को उपेक्षा से देख सकते हैं और अंततः बहिष्कृत हो गया।

12

जॉन,

मैं इकाइयों के लिए linq के साथ भी खेल रहा हूं। यह एसक्यूएल के साथ linq के साथ पकड़ने से पहले जाने के लिए एक लंबा रास्ता तय किया गया है। मुझे तालिका प्रति प्रकार विरासत सामग्री के लिए इकाइयों को linq का उपयोग करना पड़ा है। मुझे हाल ही में एक अच्छा लेख मिला जो पूरे 1 कंपनी 2 अलग ओआरएम प्रौद्योगिकियों की बात बताता है here

लेकिन अगर आप ऐसा करके एक तरह से, आलसी लोड हो रहा है क्या कर सकते हैं,:

// Lazy Load Orders 
var alice2 = data.Customers.First(c => c.Name == "Alice"); 

// Should Load the Orders 
if (!alice2.Orders.IsLoaded) 
    alice2.Orders.Load(); 

या तुम सिर्फ मूल क्वेरी में आदेश शामिल हो सकते हैं:

// Include Orders in original query 
var alice = data.Customers.Include("Orders").First(c => c.Name == "Alice"); 

// Should already be loaded 
if (!alice.Orders.IsLoaded) 
    alice.Orders.Load(); 

आशा है कि यह मदद करता है।

डेव

+2

मैं सहमत हूं, इस ब्लॉग पोस्ट को पूरी तरह से सूचित नहीं किया गया है। मेरा मानना ​​है कि उन्हें इसकी आलोचना करने से पहले एल 2 ई सीखना थोड़ा और समय लेना चाहिए था - ऐसा लगता है कि उन्होंने फैसला किया कि उन्हें लेख लिखने से पहले उन्हें पसंद नहीं आया, जिससे भारी उत्तेजना हुई क्योंकि उन्हें नहीं पता था कि उन्हें लोड करना है() ... – naspinski

2

यह बहुत ही समस्या के लिए कुछ दिनों खो दिया, मैं हमदर्दी है।

"गलती," यदि कोई है, तो यह अपेक्षा करने की उचित प्रवृत्ति है कि इस तरह की समस्याओं से अमूर्तता की एक परत इन्सुलेट करने जा रही है। LINQ से, इकाइयों तक, डेटाबेस परत पर जाकर, दोगुना।

एमएस-एसक्यूएल (लिंगटॉएसक्यूएल का उपयोग करके) को MySQL (LinqToEntities का उपयोग करके) में स्विच करने के लिए, उदाहरण के लिए, कोई यह समझता है कि LINQ, कम से कम, समान होने की लागत से बचाने के लिए नहीं होगा प्रोग्राम तर्क दोबारा लिखें।

। लोड() और/या LINQ के साथ कूड़े कोड के साथ। शामिल करें() बस क्योंकि हुड के तहत दृढ़ता तंत्र बदल गया है, विशेष रूप से एक चुप विफलता के साथ, थोड़ा परेशान लगता है। LINQ परत कम से कम लगातार व्यवहार करना चाहिए।

कई ओआरएम फ्रेमवर्क एक प्रॉक्सी ऑब्जेक्ट का उपयोग करते हैं जो गतिशील रूप से आलसी वस्तु को पारदर्शी रूप से लोड करने के बजाय पारदर्शी रूप से लोड करते हैं, हालांकि मैं संग्रह-लोड-लोड अपवाद से खुश हूं।

मैं जानबूझकर-आपके-लाभकारी बहाने के लिए इन्हें खरीदने के लिए नहीं खरीदता हूं; अन्य ओआरएम ढांचे आपको एनोटेट करने देते हैं कि आप जरूरी या आलसी लोडिंग चाहते हैं या नहीं। वही किया जा सकता है।

संबंधित मुद्दे