2016-03-07 9 views
21

मैं लिंककैड में प्रश्नों के साथ प्रयोग कर रहा हूं। हमारे पास एक है एक कॉलम Side char(1) साथ तालिका Lot। जब मैं एसक्यूएल क्वेरी Lots.Where(l => l.Side == 'A') करने के लिए एक LINQ लिखते हैं, यह निम्नलिखित एसक्यूएल का उत्पादनकहां से उत्पन्न विभिन्न एसक्यूएल (एल => l.Side == 'ए') बनाम कहां (एल => l.Side.Equals ('ए')

-- Region Parameters 
DECLARE @p0 Int = 65 
-- EndRegion 
SELECT ..., [t0].[Side], ... 
FROM [Lot] AS [t0] 
WHERE UNICODE([t0].[Side]) = @p0 

हालांकि, Lots.Where(l => l.Side.Equals('A')) का उपयोग कर, यह

-- Region Parameters 
DECLARE @p0 Char(1) = 'A' 
-- EndRegion 
SELECT ..., [t0].[Side], ... 
FROM [Lot] AS [t0] 
WHERE [t0].[Side] = @p0 

यह पर प्रकट होता पैदा करता है (भोली यद्यपि) निरीक्षण, कि उत्तरार्द्ध मामूली तेजी से होगा, जैसा कि यह करता है UNICODE पर कॉल की आवश्यकता नहीं है।

int, smallint या varchar कॉलम वहाँ == या .Equals के साथ उत्पादन एसक्यूएल के बीच कोई अंतर नहीं है का उपयोग करना, क्यों char(1) है और इसी सी # प्रकार char अलग है?

क्या यह अनुमान लगाने का कोई तरीका है कि दिया गया कॉलम प्रकार समानता जांच के दो रूपों के साथ अलग SQL उत्पन्न करेगा या नहीं?

संपादित करें:

मैं हर प्रकार एमएस एसक्यूएल द्वारा समर्थित जाँच कर ली है, और केवल char(1) और nchar(1) इस व्यवहार प्रदर्शित करते हैं। दोनों को System.Char प्रकार द्वारा LinqToSql में दर्शाया गया है। यदि यह एक जानबूझकर निर्णय था, तो मैं binary(1) पर समान व्यवहार है, जो System.Byte द्वारा प्रतिनिधित्व किया जा सकता है (लेकिन इसके बजाय 1 की लंबाई के साथ System.Linq.Binary है उम्मीद है |

संपादित करें 2:। मामले में यह प्रासंगिक है, मैं कर रहा हूँ LINQPad का उपयोग कर बनाई एसक्यूएल देखने पर मैं यह सोचते था LINQPad सिस्टम के LinqToSql का प्रयोग करेंगे, लेकिन मैं आज महसूस किया कि कि इस धारणा त्रुटिपूर्ण किया जा सकता है

संपादित करें 3:।। मैं परियोजना वी.एस. एक त्वरित प्रणाली LinqToSql परीक्षण करने के लिए भाग गया, और हम एक ही परिणाम प्राप्त करें:

कोड:

static void Main(string[] args) 
{ 
    var db = new DataClasses1DataContext {Log = Console.Out}; 
    Console.Out.WriteLine("l.Side == 'A'"); 
    Console.Out.WriteLine("============="); 
    Console.Out.WriteLine(); 
    foreach (Lot ll in db.Lots.Where(l => l.Side == 'A')) 
    { 
     break; 
    } 
    Console.Out.WriteLine(); 
    Console.Out.WriteLine("---------------------------------------"); 
    Console.Out.WriteLine(); 

    Console.Out.WriteLine("l.Side.Equals('A')"); 
    Console.Out.WriteLine("=================="); 
    Console.Out.WriteLine(); 
    foreach (Lot ll in db.Lots.Where(l => l.Side.Equals('A'))) 
    { 
     break; 
    } 
    Console.In.Read(); 
} 

आउटपुट:

l.Side == 'A' 
============= 

SELECT ..., [t0].[Side], ... 
FROM [dbo].[Lot] AS [t0] 
WHERE UNICODE([t0].[Side]) = @p0 
-- @p0: Input Int (Size = -1; Prec = 0; Scale = 0) [65] 
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 4.6.1532.0 


--------------------------------------- 

l.Side.Equals('A') 
================== 

SELECT ..., [t0].[Side], ... 
FROM [dbo].[Lot] AS [t0] 
WHERE [t0].[Side] = @p0 
-- @p0: Input Char (Size = 1; Prec = 0; Scale = 0) [A] 
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 4.6.1532.0 

यह ध्यान रखें कि == 'A' संस्करण में, पैरामीटर, एक int के रूप में पारित हो जाता है, जबकि .Equals संस्करण में, यह char के रूप में पारित हो जाता है दिलचस्प है।

The dbml and table creation script are in this gist.

+0

क्या आप डीबीएमएल मैपिंग पोस्ट कर सकते हैं? – usr

+0

@usr यह LINQPad के माध्यम से था, जिसके लिए मुझे नहीं पता कि मानचित्रण को कैसे पुनर्प्राप्त किया जाए। – RoadieRich

उत्तर

12

इस बारे में कुछ भी नहीं है documentation: एसक्यूएल सर्वर में

असंतुलन: फिक्स्ड लंबाई चरित्र प्रकार। ट्रांजैक्ट-एसक्यूएल यूनिकोड और गैर-यूनिकोड श्रेणियों के बीच अंतर करता है और प्रत्येक श्रेणी में तीन अलग-अलग प्रकार होते हैं: निश्चित लंबाई nchar/char, चर लंबाई लंबाई narcharch/varchar, और बड़े आकार के ntext/पाठ। निश्चित लंबाई वर्ण प्रकारों को सीएलआर सिस्टम में मैप किया जा सकता है। अक्षर को पुनः प्राप्त करने के लिए प्रकार टाइप करें, लेकिन वे वास्तव में रूपांतरण और व्यवहार में समान प्रकार के अनुरूप नहीं हैं।

और L2S स्रोत कोड केवल एक ही स्थान पर स्ट्रिंग शाब्दिक "UNICODE" का उपयोग करता है:

enter image description here

ऐसा लगता है कि समारोह दिखाने के लिए एक आवश्यक पूर्व शर्त के साथ एक SqlUnary वाक्य रचना पेड़ नोड है प्रकार Convert:

enter image description here

मैं नहीं जानता आप IsNumeric स्थिति को कैसे संतुष्ट करने में कामयाब रहे। मुझे लगता है कि आपके पास एक प्रकार का मेल नहीं है। क्या स्तंभ वास्तव में System.Char के रूप में मैप किया गया है?

Equals कॉल शायद इस कोड पथ को ट्रिगर नहीं करता है। यह एक एल 2 एस बग है।

Equals स्रोत कोड में कई स्थानों पर अनुवादित है। यहाँ उनमें से एक है:

enter image description here

ऐसा लगता है कि यह किसी भी तर्क रूपांतरण नजरअंदाज तरह। यह परवाह नहीं है कि तर्क क्या है। यह शायद विभिन्न प्रश्नों के साथ विफल रहता है (इसलिए यह एक बग है)। मुझे आश्चर्य है कि क्या होता है यदि आप l.Side.Equals(1.2m) लिखते हैं। मुझे लगता है कि यह सचमुच एसक्यूएल में अनुवाद करता है।


अब मैंने इसे पुन: उत्पन्न किया है। कॉलम को string पर मानचित्र करें। यह जेनरेट एसक्यूएल को हल करता है। निष्पादन योजना से पता चलता है कि उत्पन्न होने वाले एसक्यूएल के साथ एक इंडेक्स खोज संभव है।

+0

'l.Side.Equals (1.2m)' किसी भी SQL उत्पन्न होने से पहले 'System.Cecimal' टाइप करने के लिए 'System.Decimal' प्रकार से कनवर्ट नहीं किया जा सकता है - कम से कम, बिना किसी दृश्यमान SQL आंतरिक में खुदाई। – RoadieRich

+0

मुझे शायद यह जोड़ना चाहिए कि मैं बनाया गया SQL देखने के लिए LINQPad का उपयोग कर रहा हूं, अगर इससे कोई फर्क पड़ता है। मुझे लगता है कि LINQPad सिस्टम L2S लाइब्रेरी का उपयोग करेगा, लेकिन मुझे एहसास हुआ कि धारणा संभवतः त्रुटिपूर्ण थी। – RoadieRich

+0

लिंककैड शायद असम्बद्ध बाइनरी का उपयोग करता है। आप एल 2 एस के रनटाइम मेटाडेटा सिस्टम के माध्यम से मैपिंग से पूछ सकते हैं। इसके लिए एमएसडीएन दस्तावेज है। लेकिन अगर आप अपने परीक्षण चलाने के लिए एक वीएस परियोजना बनाई तो यह बेहतर होगा। अभी मुझे नहीं पता कि कैसे आगे बढ़ना है कि लिंककैड सभी प्रकार के अजीब मैपिंग और आक्रामक तकनीकों का उपयोग कर सकता है। – usr

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