2016-04-15 4 views
0

Beispiel verdeutlicht Ich habe eine Datenbank von Benutzern, die von einem Skript erstellt wird, das Active Directory durchsucht. Eines der anzuwendenden Felder ist ein "ScanDate" -Feld, das anzeigt, wann der Scan stattgefunden hat. Das Skript scannt durch mehrere Active Directory-Domänen.Wie verwende ich Group By und MAX in Linq, um mehrere Zeilen zurückzugeben?

ZIEL: Beziehen Sie eine IList aus der Datenbank, die die Liste der Benutzer für ALLE Domänen enthält, wobei ScanDate jedoch der MAX (ScanDate) für jede Domäne ist.

Dies stellt sicher, dass ich die frischesten Daten für jede Domäne erhalte.

Eine SQL-Abfrage, die für mich zu arbeiten scheint:

SELECT * 
FROM ADScans a 
WHERE a.ScanDate = (SELECT MAX(b.ScanDate) FROM ADScans b WHERE a.Domain = b.Domain) AND Enabled = 1 

jedoch Schwierigkeiten haben, dass ausgedrückt in LINQ

z.B .:

Kategorie | Datum

Cat1 4/4/16

Cat2 | 4/4/16

Cat3 | 4/4/16

Kat1 | 4/3/16

ich eine Liste erwarten:

Cat1 | 4/4/16

Kat2 | 4/4/16

Cat3 |

4/4/16

Einige Klärung

Ich würde erwarten, mehrere Zeilen pro Kategorie zurückgeführt haben - die MAX (Datum) gibt mir nicht nur eine. Ich möchte alle Zeilen für den MAX (Datum) jeder Kategorie erhalten.

+0

Ihre Frage nicht mehr klar. Wenn Sie mehrere Zeilen für jede Kategorie mit demselben Datum erhalten, sind diese Elemente Duplikate voneinander. Ist das was du willst? Bitte geben Sie ein besseres Beispiel. –

Antwort

0

Sie können GroupBy von DomainScanDate den max zu erhalten, dann mit diesem Datum nur die Zeilen halten.

Für ein Modell wie folgt aus:

die Scans mit der max ScanDate für seine Domain enthält
var result = scans.GroupBy(s => s.Domain) 
        .SelectMany(g => g.Where(s => s.ScanDate == g.Max(d => d.ScanDate))); 

Dies erzeugt eine Sammlung:

class ADScan 
{ 
    public int Domain { get; set; } 

    public DateTime ScanDate { get; set; } 
} 

Sie die Scans dies zu tun bekommen.

0

So etwas sollte funktionieren:

var result = 
    list 
    //Group by Category 
    .GroupBy(x => x.Category) 
    //For each Category, select Category and max Date within the Category 
    //This would create an anonymous object, you could do a "new Entity" instead if you want 
    .Select(g => new {Category = g.Key, Date = g.Max(x => x.Date)}) 
    .ToList(); 
0

Ich bin ein Idiot.

from u in this.db.ADScans 
where u.ScanDate == 
    (from s in this.db.ADScans where u.Domain == s.Domain select s.ScanDate).Max() 
    && u.Enabled 
select u; 
+0

Während dies funktionieren könnte, glaube ich, dass es weniger effizient sein wird, als gruppierte Artikel zu bestellen und jeweils den oberen zu wählen. Vielleicht möchten Sie die Leistung testen, bevor Sie diese Route gehen. – StriplingWarrior

+0

Eigentlich, jetzt, da ich es ansehe, ist dieser Ansatz falsch, es sei denn, Sie können garantieren, dass die "ScanDate" -Werte alle eindeutig sind. Wenn zwei ADScans über dasselbe ScanDate verfügen und eines davon das neueste für seine Domäne ist, gibt Ihre Abfrage beide zurück, auch wenn sich das andere in einer anderen Domäne befindet. – StriplingWarrior

+0

Ich würde beide wollen. Ich halte einen eindeutigen Eintrag für Domain + ScanDate + Username. Auf diese Weise kann ich die neueste Liste aller eindeutigen Benutzerkonten in jeder Domäne abrufen – appsecguy

0

Anstatt Max() verwenden, bestellen Sie einfach die Elemente in den Gruppen und nehmen Sie die Top-Artikel: da Sie die Einzelteile bestellen, es ist garantiert die höchste sein:

var mostRecentScanFromEachDomain = 
    from u in this.db.ADScans 
    where u.Enabled 
    group u by u.Domain into g 
    select g.OrderByDescending(u => u.ScanDate) 
     .FirstOrDefault();