2015-11-05 16 views
9

हैलो मैं अपने प्रोजेक्ट के लिए MVC 5 और Entity Framework 6 का उपयोग कर रहा हूं। मैं निम्न चित्र में की तरह एक मॉडल है:सहसंबंधित इकाई द्वारा खोजें

diagram

और मैं Tag वस्तुओं का एक सेट से शुरू करके इकाई उत्पाद क्वेरी करने के लिए की जरूरत है। कृपया ध्यान दें कि Tag ऑब्जेक्ट एक सार श्रेणी है जो वास्तव में Table-Per-Entity रणनीति विरासत का उपयोग कर मैप किया गया है।

इस

मेरी समारोह विधि

public IEnumerable<Product> SerachByTag(IEnumerable<Tag> tagList); 

tagList पैरामीटर में के हस्ताक्षर वास्तव में वहाँ Tag कार्यान्वयन के ठोस उदाहरण हो जाएगा।

मैं यह प्रश्न कैसे बना सकता हूं?

उदाहरण के लिए मैं डेटा संरचना

[ 
    { tagType: 1, stringProperty: "abc" }, 
    { tagType: 2, intProperty: 9 } 
] 

और इतने पर निम्न इनपुट में प्राप्त कर सकते हैं। उत्पादों को फ़िल्टर करने का बेहतर तरीका कौन सा होगा? उदाहरण के लिए मैं निश्चित रूप से पहले हर एक मापदंड के लिए उत्पादों की एक सूची लागू हो सकते हैं और उसके बाद निम्न नमूना में की तरह इन परिणामों एक दूसरे को काटना:

var p1 = ctx.Tags 
      .OfType<FirstTagType>() 
      .Where(x => x.StringProperty.Equals("abc")) 
      .Select(x => x.Products); 
var p2 = ctx.Tags 
      .OfType<SecondTagType>() 
      .Where(x => x.IntProperty == 9) 
      .Select(x => x.Products); 
var results = p1.Intersect(p2); 

लेकिन इस मामले में मेरे सवाल का प्रदर्शन के बारे में है। यह क्वेरी कई फ़िल्टरों के साथ कैसे व्यवहार करती है?

+0

यदि आप उत्पाद के लिए क्वेरी कर रहे हैं (और टैग के ठोस प्रकार की परवाह नहीं करते हैं) तो आप केवल (सार) टैग dbset से पूछताछ करें। –

+0

@AlexKrupka: आपके उत्तर के लिए धन्यवाद। दुर्भाग्य से मुझे ठोस प्रकार को ध्यान में रखना होगा – Lorenzo

उत्तर

5

आप आपकी क्वेरी के लिए उत्पन्न एसक्यूएल की जाँच हैं, तो आप कुछ इसी तरह मिल जाएगा:

SELECT 
[Intersect1].[ProductId] AS [C1], 
[Intersect1].[ProductName] AS [C2] 
FROM (SELECT 
    [Extent3].[ProductId] AS [ProductId], 
    [Extent3].[ProductName] AS [ProductName] 
    FROM [dbo].[FirstTag] AS [Extent1] 
    INNER JOIN [dbo].[Tag] AS [Extent2] ON [Extent1].[TagId] = [Extent2].[TagId] 
    LEFT OUTER JOIN [dbo].[Product] AS [Extent3] ON [Extent2].[Product_ProductId] = [Extent3].[ProductId] 
    WHERE N'aaaa-9' = [Extent1].[StringProperty] 
INTERSECT 
    SELECT 
    [Extent6].[ProductId] AS [ProductId], 
    [Extent6].[ProductName] AS [ProductName] 
    FROM [dbo].[SecondTag] AS [Extent4] 
    INNER JOIN [dbo].[Tag] AS [Extent5] ON [Extent4].[TagId] = [Extent5].[TagId] 
    LEFT OUTER JOIN [dbo].[Product] AS [Extent6] ON [Extent5].[Product_ProductId] = [Extent6].[ProductId] 
    WHERE -9 = [Extent4].[IntProperty]) AS [Intersect1] 

यहाँ, आप देख सकते हैं कि आंतरिक चयन प्रश्नों कर रहे हैं तुम क्या करने की उम्मीद वास्तव में क्या। जॉइन विदेशी कुंजी पर आधारित होते हैं, और कॉलम पर इंडेक्स के साथ तेजी से होना चाहिए। तो यदि आपके पास कई फ़िल्टर हैं, तो आपको बस यह सुनिश्चित करने की आवश्यकता है कि वे सभी ठीक से अनुक्रमित कॉलम पर काम करें।

LINQ Intersect को SQL INTERSECT में अनुवादित किया गया है, जो "उत्पाद" तालिका के सभी कॉलम पर काम करता है। आप अपनी तरफ से वास्तविक निष्पादन योजना की जांच करना चाहेंगे, यह कई चीजों पर निर्भर हो सकता है।

मेरी ओर से जो कुछ मैं देखता हूं वह यह है कि SQL सर्वर पहली क्वेरी निष्पादित करता है, इसके परिणामस्वरूप यह "अलग सॉर्ट" कहता है, और फिर वास्तविक अंतर करने के लिए यह ProductId के साथ "बाएं सेमी जॉइन" करता है और ProductName (इसलिए उत्पाद तालिका में सभी कॉलम)। यह सबसे अच्छा नहीं हो सकता है, क्योंकि मेरा अनुमान है कि आपके पास सभी कॉलम पर कोई अनुक्रमणिका नहीं है।

var p1 = ctx.Tags 
    .OfType<FirstTag>() 
    .Where(x => x.StringProperty.Equals("aaaa-9")) 
    .Select(x => x.Product.ProductId); 
var p2 = ctx.Tags 
    .OfType<SecondTag>() 
    .Where(x => x.IntProperty == -9) 
    .Select(x => x.Product.ProductId); 

var query = ctx.Products.Where(p => p1.Intersect(p2).Contains(p.ProductId)); 

उत्पन्न अंतर्निहित SQL क्वेरी का उपयोग करता है:

एक तरीका यह अनुकूलन करने के लिए करने के लिए केवल प्राथमिक कुंजी पर एक दूसरे को काटना कर (कि तेजी से होना चाहिए), और फिर आईडी के आधार पर सभी उत्पाद डेटा लाने है EXISTS और उस की निष्पादन योजना एक आंतरिक शामिल (प्राथमिक कुंजी पर) का उपयोग करती है।

लेकिन, वास्तव में यह जांचने के बिना मैं वास्तव में यह अनुकूलन प्रक्रिया शुरू नहीं करूंगा कि आपके पास कोई प्रदर्शन समस्या है या नहीं।

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