मेरे पास एक नेस्टेड डेटा मॉडल है और मैं इससे एक शीर्ष स्तर की संपत्ति द्वारा समूहीकृत डेटा प्राप्त करना चाहता हूं। उदाहरण के लिए मेरे मॉडल:

public class Scan {
    public long Id {get; set;}
    public int ProjectId { get; set; }
    public int ScanUserId { get; set; }
    public ICollection<ScanItem>? Items { get; set; }
}

public class ScanItem
{
    public long Id { get; set; }
    public long InventoryScanId { get; set; }
    public double Qty { get; set; }
}

मैं स्कैन.ScanUserId द्वारा समूहीकृत सभी स्कैन प्राप्त करना चाहता हूं और फिर प्रति उपयोगकर्ता उदाहरण के लिए ScanItems.Qty का योग प्राप्त करना चाहता हूं। मेरी क्वेरी इस तरह दिखती है और ईएफ निम्न त्रुटि देता है:

LINQ एक्सप्रेशन 'AsQueryable ((अनहेल्ड पैरामीटर: x) आइटम्स)' को 'नेविगेशन एक्सपैंडिंग एक्सप्रेशन विज़िटर' द्वारा संसाधित करना विफल रहा

from scan in Scans
        .Include(x=>x.ScanUser)
        .Include(x=>x.Items)
    group scan by new { scan.ScanUser.Name, scan.ScanUser.Id } into g
    select new
    {
        UserId = g.Key.Id,
        Name = g.Key.Name,
        LastSyncTime = g.Max(x => x.ScanDate),
        ScanItems = g.Sum(x=>x.Items.Sum(i=>i.Qty))
    }

क्लाइंट साइड पर इसका मूल्यांकन किए बिना मैं नेस्टेड टेबल के गुणों पर कुल कार्य कैसे चला सकता हूं?

2
Perrier 14 जिंदा 2020, 16:54

1 उत्तर

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

EF Core अभी भी GroupBy परिणाम (समूहीकरण) पर नेस्टेड समुच्चय का अनुवाद नहीं कर सकता।

आपको क्वेरी सिंटैक्स group element by key में GroupBy (या element के तत्व चयनकर्ता का उपयोग करके पहले से नेस्टेड समुच्चय की गणना करनी होगी):

from scan in Scans
group new { scan.ScanDate, Qty = scan.Items.Sum(i => i.Qty) } // <--
by new { scan.ScanUser.Name, scan.ScanUser.Id } into g
select new
{
    UserId = g.Key.Id,
    Name = g.Key.Name,
    LastSyncTime = g.Max(x => x.ScanDate),
    ScanItems = g.Sum(x => x.Qty) // <--
}

**अद्यतन करें: ** SqlServer के लिए उपरोक्त LINQ क्वेरी इस तरह SQL क्वेरी में अनुवाद करती है:

 SELECT [s1].[Id] AS [UserId], [s1].[Name], MAX([s0].[ScanDate]) AS [LastSyncTime], SUM((
      SELECT SUM([s].[Qty])
      FROM [ScanItem] AS [s]
      WHERE [s0].[Id] = [s].[InventoryScanId])) AS [ScanItems]
  FROM [Scan] AS [s0]
  INNER JOIN [ScanUser] AS [s1] ON [s0].[ScanUserId] = [s1].[Id]
  GROUP BY [s1].[Name], [s1].[Id]

जैसा कि टिप्पणी में उल्लेख किया गया है, SQL निष्पादन अपवाद उत्पन्न करता है "एक समग्र या एक उपश्रेणी वाले अभिव्यक्ति पर एक समग्र कार्य नहीं कर सकता।"

तो आपको वास्तव में एक और दृष्टिकोण की आवश्यकता है - समूहीकरण से पहले परिणाम सेट को फ़्लैट करने के लिए left join का उपयोग करें, और फिर उस सेट पर समूह/समुच्चय निष्पादित करें:

from scan in Scans
from item in scan.Items.DefaultIfEmpty() // <-- left outer join
group new { scan, item } by new { scan.ScanUser.Name, scan.ScanUser.Id } into g
select new
{
    UserId = g.Key.Id,
    Name = g.Key.Name,
    LastSyncTime = g.Max(x => x.scan.ScanDate),
    ScanItems = g.Sum(x => (double?)x.item.Qty) ?? 0
};

जो अब उम्मीद के मुताबिक मान्य SqlServer SQL क्वेरी का अनुवाद करता है:

  SELECT [s1].[Id] AS [UserId], [s1].[Name], MAX([s].[ScanDate]) AS [LastSyncTime], COALESCE(SUM([s0].[Qty]), 0.0E0) AS [ScanItems]
  FROM [Scan] AS [s]
  LEFT JOIN [ScanItem] AS [s0] ON [s].[Id] = [s0].[InventoryScanId]
  INNER JOIN [ScanUser] AS [s1] ON [s].[ScanUserId] = [s1].[Id]
  GROUP BY [s1].[Name], [s1].[Id]
5
Ivan Stoev 14 जिंदा 2020, 15:26