2008-11-11 10 views
28

.NET 3.5, सी #क्या LINQ से SQL एक XML फ़ील्ड डीबी-सर्वरसाइड क्वेरी कर सकता है?

मेरे पास "खोज" सुविधा वाला एक वेब ऐप है। खोजे जाने वाले कुछ फ़ील्ड तालिका में प्रथम श्रेणी के कॉलम हैं, लेकिन उनमें से कुछ वास्तव में एक्सएमएल डेटा प्रकार के अंदर घोंसला वाले फ़ील्ड हैं।

पहले, मैंने अपनी खोज के लिए गतिशील रूप से एसक्यूएल बनाने के लिए एक प्रणाली बनाई थी। मेरे पास एक अच्छी कक्षा पदानुक्रम था जिसने एसक्यूएल अभिव्यक्तियों और सशर्त बयान बनाए। एकमात्र समस्या यह थी कि यह एसक्यूएल इंजेक्शन हमलों से सुरक्षित नहीं था।

मैं रोब कॉनरी के उत्कृष्ट आलेख (http://blog.wekeroad.com/2008/02/27/creating-in-queries-with-linq-to-sql/) पढ़ रहा था, जिसने इंगित किया कि एकाधिक क्वेरी सर्वर के लिए एक एकल TSQL क्वेरी में संयुक्त हो सकती हैं यदि IQueryable परिणाम कभी समझा नहीं जाता है। यह मुझे यह सोचने के लिए मिला कि मेरा गतिशील खोज निर्माण बहुत जटिल था - मुझे बस कई LINQ अभिव्यक्तियों को गठबंधन करने की आवश्यकता थी।

उदाहरण (काल्पनिक) के लिए:

लेखक: आईडी (पूर्णांक), अंतिम नाम (varchar (32)), FirstName (varchar (32))

context.Author.Where(xx => xx.LastName == "Smith").Where(xx => xx.FirstName == "John") 

निम्नलिखित में परिणाम क्वेरी:

SELECT [t0].[ID], [t0].[LastName], [t0].[FirstName] 
FROM [dbo].[Author] AS [t0] 
WHERE ([t0].[LastName] = Smith) AND ([t0].[FirstName] = John) 

मुझे एहसास हुआ कि यह है कि SQL से सुरक्षित है एक सरल गतिशील क्वेरी पीढ़ी के लिए एकदम सही समाधान हो सकता है इंजेक्शन - मैं अपने IQueryable परिणाम पर बस लूप करता हूं और अपनी अंतिम एकल-निष्पादन अभिव्यक्ति प्राप्त करने के लिए अतिरिक्त सशर्त अभिव्यक्ति निष्पादित करता हूं।

हालांकि, मुझे XML डेटा के मूल्यांकन के लिए कोई समर्थन नहीं मिल रहा है। TSQL में, प्राप्त करने के लिए एक XML नोड से एक मूल्य है, हम जैसे

XMLField.value('(*:Root/*:CreatedAt)[1]', 'datetime') = getdate() 

कुछ करना होगा लेकिन मैं इस मूल्यांकन बनाने के बराबर LINQ एसक्यूएल को नहीं मिल रहा। क्या कोई अस्तित्व में है? मुझे पता है कि मैं सभी गैर-एक्सएमएल स्थितियों डीबी पक्ष का मूल्यांकन कर सकता हूं, और फिर मेरा एक्सएमएल मूल्यांकन कोड पक्ष कर सकता हूं, लेकिन मेरा डेटा इतना बड़ा है कि ए) प्रदर्शन पर खींचने के लिए बहुत सारे नेटवर्क यातायात हैं और बी) मैं बाहर निकल जाऊंगा- मेमोरी अपवाद अगर मैं एक्सएमएल पहले डीबी पक्ष का मूल्यांकन कुछ परिणाम सेट को बाहर करने के लिए नहीं कर सकता।

विचार? सुझाव?

बोनस प्रश्न - यदि एक्सएमएल मूल्यांकन वास्तव में संभव है डीबी पक्ष, FLWOR समर्थन के बारे में क्या?

+1

तो, मैं प्रत्येक के लिए देखो यह 2013 के अंत है - अपडेट? –

+1

@ बेंजामिनग्रेनबाम यह लंबे समय से रहा है क्योंकि मैंने इस सवाल के बारे में सोचा है। जब मैंने तब और अब के बीच नौकरियां बदल दीं तो इसके लिए मेरा उपयोग केस गायब हो गया। जितना अच्छा मैं याद कर सकता हूं, मैंने नीचे दी गई डैनियलएम दृष्टिकोण का उपयोग किया, जो उपयोगकर्ता द्वारा परिभाषित फ़ंक्शन को कॉल करना था। ऐसा नहीं कह सकता क्योंकि मैंने तब से LINQ में कोई प्रत्यक्ष समर्थन देखा है (लेकिन मैं या तो नहीं देख रहा हूं) – Matt

+1

दिलचस्प - मैं 5 साल बाद एक बक्षीस के साथ नए उत्तरों को मछली पकड़ने की कोशिश करूंगा। –

उत्तर

12

अब यह एक दिलचस्प सवाल है।

अभी, आप SQL सर्वर को सीधे लिंक से एक्सएमएल फ़ंक्शंस करने के लिए निर्देश नहीं दे सकते। हालांकि, आप उपयोगकर्ता परिभाषित कार्यों का उपयोग करने के लिए लिंक प्राप्त कर सकते हैं ... तो, आप एक्सएमएल को संसाधित करने के लिए एक udf सेट कर सकते हैं, सही डेटा प्राप्त कर सकते हैं, और फिर अपने लिंक एक्सप्रेशन में इसका उपयोग कर सकते हैं। यह सर्वर पर निष्पादित होगा और आप जो चाहते हैं उसे करना चाहिए। एक महत्वपूर्ण सीमा है, यद्यपि: जिस XML पथ को आप ढूंढ रहे हैं (xmlColumn.value या इसी तरह का पहला पैरामीटर) को फ़ंक्शन में बनाया जाना चाहिए क्योंकि इसे स्ट्रिंग शाब्दिक होना चाहिए, इसे किसी से बनाया नहीं जा सकता इनपुट पैरामीटर (उदाहरण के लिए)। तो आप यूडीएफ लिखने के बारे में जानते हुए फ़ील्ड प्राप्त करने के लिए यूडीएफ का उपयोग कर सकते हैं, लेकिन XML कॉलम से डेटा प्राप्त करने के सामान्य उद्देश्य के रूप में नहीं।

कार्यान्वयन पर अधिक जानकारी के लिए Scott Gutherie's excellent Blog series on Linq to SQL के सहायक उपयोगकर्ता परिभाषित कार्य (यूडीएफ) अनुभाग देखें।

उम्मीद है कि इससे मदद मिलती है।

+0

धन्यवाद डैनियल, यह चाल है! मैंने थोड़ी देर पहले उस लेख को पढ़ा था, लेकिन जब मैंने निष्पादन से पहले कई प्रश्नों को एक साथ जोड़ने के बारे में ऊपर वर्णित आलेख पढ़ा तो यह मेरे साथ क्लिक नहीं किया। – Matt

4

डैनियल के उत्तर को स्पष्ट करने के लिए - आप तब तक ऐसा करने के लिए फ़ंक्शन का उपयोग नहीं कर सकते जब तक कि क्वेरी का XPath भाग ठीक न हो जाए। इस पर मेरी ब्लॉग प्रविष्टि देखें: http://conficient.wordpress.com/2008/08/11/linq-to-sql-faq-xml-columns-in-sql/

मूल रूप से आप LINQ से SQL के माध्यम से एक XML स्तंभ क्वेरी नहीं कर सकते हैं। हालांकि यह XElement प्रकार देता है, लेकिन आप इस कॉलम पर फ़िल्टर करने का प्रयास करते समय कोई भी SQL अनुवाद नहीं कर सकते हैं।

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

इससे ऐसा करने के केवल दो अन्य वैकल्पिक तरीके सामने आते हैं: इनलाइन एसक्यूएल स्टेटमेंट (जो LINQ रखने के मूल्य को अस्वीकार करता है) और ऐसा करने के लिए .NET CLR में SQL लायब्रेरी फ़ंक्शन लिखना।

+0

उस ब्लॉग पर भी एक अपडेट देखें: http://conficient.wordpress.com/2011/01/20/querying-xml-fields-in-linq-to-sql/ – PaulG

+0

उत्तर को स्पष्ट करने का सबसे अच्छा तरीका करना है बस यही: इसे स्पष्ट करने के लिए उत्तर संपादित करें, या यदि आपने (उस समय) संपादन अधिकार नहीं हैं, तो समस्या को ध्वजांकित करने के लिए टिप्पणी करें। (क्या यह था कि दिसंबर 2008 में एसओ ने कैसे काम किया था? मुझे नहीं पता, मैं आठ महीने बाद शामिल हुआ। :-) जब मैं शामिल हुआ, लेकिन उस समय एसओ तेजी से बढ़ रहा था और बदल रहा था।) –

-1

यह सबसे अच्छा नहीं है सभी प्रश्नों के लिए नहीं है, और पूरी तरह से LINQ नहीं है, लेकिन काम करता है और तेजी से होता है:

एक xml एसक्यूएल क्षेत्र ".ToString" स्वीकार करते हैं, तो आप कर सकते हैं:

Dim txt as String = "<File>3</File>" 
Return (From P In DC.LPlanningRefs Where P.Details.ToString.Contains(txt) Select P).FirstOrDefault 

मैं इसका इस्तेमाल लाइनों को सीमित करने के लिए लौट आए, और लौट आए लाइनों