मैं अपनी टी-एसक्यूएल क्वेरी को LINQ में बदलने की कोशिश कर रहा हूं।

मेरी क्वेरी:

SELECT l.Id, s.SystemSerial, v.LicenseVersion, l.CreatedDate, STRING_AGG (sf.[Name], ',') as Features
FROM [system] AS s
LEFT OUTER JOIN SoftwareLicense AS l ON l.SystemId = s.id
LEFT OUTER JOIN SoftwareVersion as v ON l.SoftwareVersionId = v.Id
LEFT OUTER JOIN FeatureLicense as fl ON fl.SoftwareLicenseId = l.Id AND fl.IsActive = 1
LEFT OUTER JOIN SoftwareFeature as sf ON sf.Id = fl.SoftwareFeatureId
GROUP BY l.id, s.SystemSerial, v.LicenseVersion, l.CreatedDate

उपरोक्त क्वेरी निम्नलिखित लौटाती है:

267     DELL-H99DHM2        1.0     2019-05-06T13:19:59.3081543     Advanced,Internal
270     DESKTOP-SLL5NLC     1.0     2019-05-06T19:22:19.5161704     Standard,Video
271     DESKTOP-T67FIK1     1.0     2019-05-06T19:30:50.6251582     Advanced,Internal,Video
272     DESKTOP-T67FIK1     1.1     2019-05-07T11:30:50.2351512     Advanced

मेरी मूल LINQ क्वेरी (STRING_AGG जोड़ने से पहले) इस तरह दिखती थी:

var allSystemsAndLicenses = (from s in _context.Systems
                            join sl in _context.SoftwareLicenses on s.Id equals sl.SystemId into sll
                            from sl2 in sll.DefaultIfEmpty()
                            join sv in _context.SoftwareVersions on sl2.SoftwareVersionId equals sv.Id into svv
                            from sv2 in svv.DefaultIfEmpty()
                            join fl in _context.FeatureLicenses on sl2.Id equals fl.SoftwareLicenseId into fll
                            from fl2 in fll.DefaultIfEmpty().Where(a => a.IsActive)
                            join sf in _context.SoftwareFeatures on fl2.SoftwareFeatureId equals sf.Id into sff
                            from sf2 in sff.DefaultIfEmpty()
                            select new SystemLicenseResult
                            {
                                LicenseId = sl2.Id,
                                SerialNumber = s.SystemSerial,
                                LicenseVersion = sv2.LicenseVersion + " (" + sv2.Software.Name + ")",
                                LicenseExpiryDate = sl2.CreatedDate,
                                CreatedDate = sl2.CreatedDate
                            });

मैं अपने सी # कोड में STRING_AGG (sf.[Name], ',') as Features को LINQ के रूप में प्रस्तुत करने का तरीका जानने का प्रयास कर रहा हूं। मुझे लगता है कि मुझे या तो linq की GroupBy क्षमता का उपयोग करने की आवश्यकता है या किसी चयन के अंदर किसी प्रकार का चयन करना है?

किसी भी मदद की सराहना की जाती है।

1
Metal Wing 31 जिंदा 2020, 18:41
4
ऐसा करने का एक तरीका हो सकता है लेकिन व्यक्तिगत रूप से, मैं ऑब्जेक्ट मॉडल में एक सूची के रूप में सुविधाओं को वापस कर दूंगा और वास्तव में आवश्यक होने पर अल्पविराम से अलग सूची बनाने से निपटूंगा (जो एक दृश्य मॉडल समस्या हो सकती है) , डेटा समस्या के बजाय)।
 – 
Neil
31 जिंदा 2020, 18:50
क्या आप अनुमान लगा सकते हैं कि यह प्रदर्शन के हिसाब से कैसा प्रदर्शन करेगा? यह क्वेरी वर्तमान में ~1000 पंक्तियां लौटाती है। मेरे पास जो वास्तविक ~ 200 सिस्टम हैं, उन्हें नीचे ट्रिम करने के लिए, मुझे नए मॉडल का निर्माण करते समय डेटाबेस से प्राप्त होने वाले परिणाम सेट पर लूप करने की आवश्यकता होगी?
 – 
Metal Wing
31 जिंदा 2020, 19:34

2 जवाब

सबसे बढ़िया उत्तर

मुझे लगता है कि मैंने हल निकाल लिया! मेरा कोड इस प्रकार है:

var allSystemsAndLicenses = (from s in _context.Systems
    join sl in _context.SoftwareLicenses on s.Id equals sl.SystemId into sll
    from sl2 in sll.DefaultIfEmpty()
    join sv in _context.SoftwareVersions on sl2.SoftwareVersionId equals sv.Id into svv
    from sv2 in svv.DefaultIfEmpty()
    join fl in _context.FeatureLicenses on sl2.Id equals fl.SoftwareLicenseId into fll
    from fl2 in fll.DefaultIfEmpty().Where(a => a.IsActive)
    join sf in _context.SoftwareFeatures on fl2.SoftwareFeatureId equals sf.Id into sff
    from sf2 in sff.DefaultIfEmpty()
    select new SystemLicenseResult
    {
        LicenseId = sl2.Id,
        SerialNumber = s.SystemSerial,
        LicenseVersion = sv2.LicenseVersion + " (" + sv2.Software.Name + ")",
        LicenseExpiryDate = sl2.CreatedDate,
        LicenseFeatures = sf2.Name,
        CreatedDate = sl2.CreatedDate
    });

// I have some predicates defined that I am not putting here, but they do exist.
var filteredResults = allSystemsAndLicenses.Where(predicates);

var groupedResult = filteredResults.GroupBy(a => a.LicenseId);
var result = groupedResult.ToList()
    // Because the ToList(), this select projection is not done in the DB
    .Select(eg => new SystemLicenseResult
        {
            LicenseId = eg.Key,
            SerialNumber = eg.First().SerialNumber,
            LicenseFeatures = string.Join(",", eg.Select(i => i.LicenseFeatures))
        })

ऐसा लगता है कि टी-एसक्यूएल कथन क्या करता है वही परिणाम दृश्य लौटाता है!

2
Metal Wing 31 जिंदा 2020, 22:53

बस ध्यान दें कि यह वास्तव में SQL STRING_AGG सिंटैक्स में परिवर्तित नहीं होता है। ईएफ पूरी सूची खींचता है और फिर उन तारों को स्मृति में जोड़ता है।

इसका मतलब यह है कि यदि आपके समूहबद्ध आइटम में कई अन्य फ़ील्ड हैं, और कई चाइल्ड स्ट्रिंग्स जिन्हें संयोजन की आवश्यकता है, तो सभी "समूहीकृत" फ़ील्ड्स को प्रत्येक स्ट्रिंग को संयोजित करने के लिए दोहराया जाएगा। अर्थात। आपका SerialNumber, LicenseVersion आदि प्रति LicenseFeature डुप्लिकेट किया जाएगा (जेनरेट किए गए sql की जांच करें)।

इसका मतलब यह हो सकता है कि आपके डेटाबेस सर्वर और आपके ईएफ क्लाइंट के बीच बहुत अधिक "डुप्लिकेट" डेटा चल रहा है।

यदि यह एक समस्या हो सकती है (परिदृश्य में कुछ समूहीकृत फ़ील्ड शामिल हैं, जिनमें से प्रत्येक में बहुत सारे चाइल्ड स्ट्रिंग हैं), क्वेरी को 2 अलग-अलग प्रश्नों में विभाजित करने और मेमोरी में मैन्युअल रूप से संयोजित करने पर विचार करें।

ऐसे परिदृश्यों में जहां प्रति समूहित पंक्ति में केवल कुछ तार होंगे, तो केवल 1 राउंड ट्रिप होने से तेज़ होगा।

0
brenwebber 23 मार्च 2020, 12:43