2012-09-07 11 views
6

kann ich eine Hand erhalten, die das Folgende in eine LINQ-Anweisung konvertiert.Konvertieren einer SQL-Anweisung in LINQ-To-SQL

SELECT reports.* FROM [dbo].[ReportLists] rl 
INNER JOIN [dbo].[ReportItems] ri ON rl.Id = ri.ReportListId 
INNER JOIN [dbo].[Reports] reports ON ri.Id = reports.ReportItemId 
WHERE 
    reports.createdDate 
IN (
    SELECT 
     MAX(report_max_dates.createdDate) 
    FROM 
     [dbo].[Reports] report_max_dates 
    GROUP BY 
     report_max_dates.seedLot 
    ) 

Zur Zeit habe ich es so weit nach unten:

db.ReportLists.Select(rl => db.ReportItems 
          .Where(ri => ri.ReportListId == rl.Id) 
          .Select(ri => db.Reports 
              .Where(r => r.ReportItemId == ri.Id) 
              .GroupBy(r => new { r.seedLot }) 
              .Select(g => g.OrderByDescending(x => x.createdDate).FirstOrDefault()))); 

Das Problem mit dem oben LINQ ist, dass es Einträge zurückgibt, der Titel geändert haben. Innerhalb der Datenbank behalte ich den Verlauf aller Datensätze (daher die Notwendigkeit, dass der erste in der createdDate Reihenfolge absteigend ist. Wenn ich einen Bericht von Titel x in Titel y ändere, erscheint er unter beiden Titeln, wenn ich nur den aktuellsten Datensatz haben möchte daher der einer unter dem Titel y sein.

EDIT Sorry für den Mangel an Details. ich habe eine Bericht Tabelle, die Informationen über den Bericht hält (seedlot eine Kennung ist). Jedes Mal, wenn ein Bericht bearbeitet wird, einen neuen Rekord (In diesem Fall gibt der maximale Eintrag für das createdDate an, dass der Bericht der aktuellste anzuzeigende Datensatz ist. Die Berichte werden dann in Titel oder ReportItems gruppiert. Diese Berichtselemente werden dann gruppiert Halten Sie den Titel und die zugehörigen Berichte.Diese reportItems werden in einer ReportList wie th gehalten at Ich kann den JSON in einem gewünschten Format ausdrucken und enthält nur eine Statusspalte und eine ID, auf die die ReportItems verweisen.

Wenn ein Bericht von Titel a nach Titel b verschoben wird, wird ein neuer Datensatz mit dem Titel-Fremdschlüssel eingegeben, der mit dem Titel verknüpft ist, in den er geändert wurde. Wenn dies geschieht, gibt der oben angegebene LINQ den Datensatz unter jedem einzelnen ReportItem zurück, wenn er nur den neuesten Eintrag für Titel b zurückgeben soll (aus dem obigen Beispiel). Darüber hinaus gibt die LINQ-Anweisung nur den neuesten Datensatz für das createdDate zurück.

Hier sind meine Klassenstrukturen (die die DB-Struktur als auch nachahmen)

public class ReportList { 
    public int Id {get;set;} 
    public string status {get;set;} 
    public List<ReportItem> {get;set;} 
} 

public class ReportItem { 
    public int Id {get;set} 
    public string title {get;set;} 
    public List<Report> {get;set;} 
} 

public class Report { 
    public int Id {get;set;} 
    public string Lot {get;set;} 
    ... Other data ... 
    public DateTime createdDate {get;set;} 
} 

Danke, Dman

+1

Also bin ich richtig zu verstehen, dass seed_lot unterscheidet wirklich unterschiedliche Berichte voneinander * und * berichtet, dass eine Namensänderung aufgetreten sind? Das heißt, soweit report_max_dates gilt, unterscheidet sich ein umbenannter Bericht nicht von wirklich unterschiedlichen (nicht verwandten) Berichten? –

+0

Bitte geben Sie mehr Details. Erkläre, was du willst. Es ist schwierig, dies aus einem SQL-Snippet und einer fehlerhaften linq-Abfrage abzuleiten. Und erklären Sie, wie Sie die verschiedenen Versionen eines Berichts zusammenhalten. –

+0

Es scheint mir, dass Sie eine Kette von Update-Datensätzen durchqueren müssen, um die * neueste * Version eines Reports basierend auf seinem seed_lot bei Inkarnation zu erhalten, was die LINQ-Version dieser (viel?) Schwieriger als es zunächst erscheinen könnte . –

Antwort

0

Das Datenbankschema geändert, um es ein wenig zu verflachen und ein wenig Verzweigung herauszunehmen.

Bericht ist jetzt die Wurzel und ich habe nur eine Tabelle von Titeln, die an die Berichte angefügt werden.

Danke an alle für die Vorschläge tho!

0

Wenn ich es richtig verstanden hat, dann Sie neuesten Bericht von seedlot wollen, dann ich d Verwendung nächste:

from r in Reports 
group r by r.CreateDate into g 
select g.OrderByDescending(r1=>r1.CreateDate).FirstOrDefault() 

nicht ganz sicher, warum brauchen Sie ReportItem und ReportList, wenn Sie nicht, sie in Folge sind, von Ihnen zu ihnen durchqueren kann mit Navigationseigenschaften des Berichts

+0

Ich brauche die ReportList und ReportItems so, dass das JSON-Objekt wie vom empfangenden Ende benötigt formatiert wird. Meine innerste LINQ-Anweisung tut dies bereits. – DMCApps

0

Ah. Aha. Ihr Innerer Join sortiert diejenigen Datensätze aus, die in der ReportItems-Tabelle keine ID und ReportItems enthalten, die in der ReportLists-Tabelle keine ID enthalten. Da Sie in Linq keine Syntax für den inneren Join verwenden, sind sie nicht gleichwertig. Haben Sie versucht, dies:

var reports = from rl in db.ReportLists 
       from ri in rl.ReportItems 
       from r in ri.Reports 
       where (
        from report in db.Reports 
        group report by report.seedLot into g 
        select g.Max(rep => rep.createdDate)).Contains(r.CreatedDate) 
       select rl; 

Ich bin nicht 100%, die ich auf dieser Gruppe die Syntax Recht haben mit Enthält (ich weiß nicht viel Gruppierung von Tag zu Tag tun). Und wenn der LINQ-Provider das Max (oder Contains, obwohl es sollte) nicht unterstützt, wird es alles clientseitige ziehen und das ist eine Menge von Daten über den Draht zu schieben.

+0

Entschuldigung, diese Staatsmänner tun nicht genau, was ich benötige. Obwohl sie die Top-Berichte ohne Duplikate zurückgeben (meine innere linq-Anweisung tut das auch schon), brauche ich die Berichte in einem reportItem unter ihrem jeweiligen Titel, nicht als Liste von Berichten, sondern als reportList, die alle enthält die reportItems, die dann alle ihre entsprechenden Berichte für diesen Titel enthält. – DMCApps

+0

Ah. Alles, was Sie tun müssen, ist die Rückkehr zu rl statt r. –

+0

Immer noch nicht ganz :(. Dies gibt 6 Berichtslisten (eine für jeden Bericht) zurück. Was ich brauche, ist eine Berichtsliste, die 2 reportItems enthält (da ich 2 Titel habe), die jeweils 3 Berichte enthalten (seit ich 3 Berichte habe) jeder Titel) ANMERKUNG diese Werte sind spezifisch für wie ich derzeit die DB eingerichtet habe und wird sich ändern, wenn mehr Daten eingehen/Änderungen. Vielen Dank für die fortgesetzte Anstrengung tho! – DMCApps

0

Die Details, die Sie zur Verfügung stellen, machen es viel klarer, obwohl nicht vollständig, so gebe ich zwei Alternativen.Die Navigationseigenschaften in handliches kommen, wie jetzt sehr präzise umfassende Syntax möglich:

from rl in context.ReportLists 
from ri in rl.ReportItems 
from r in ri.Reports 
group r by r.Lot into g 
select g.OrderByDescending(x => x.createdDate).FirstOrDefault() 

oder (da Sie von Title in ReportItems zu Gruppe scheinen):

from rl in context.ReportLists 
from ri in rl.ReportItems 
group ri by ri.Title into g 
select g.Select(x => x.Reports 
         .OrderByDescending(x => x.createdDate).FirstOrDefault()) 

unter der Haube erzeugt dies auch SQL Joins, aber Sie brauchen nicht die peinliche Syntax. In linq fließender Syntax läuft es auf SelectMany() s herunter.

Wie Sie sehen, kann ich immer noch nicht die Rolle von Lot und Title herausfinden, aber ich hoffe, dass die Alternativen etwas Substanz geben, um Ihren eigenen Spezifikationen zu formen.

+0

Entschuldigung diese Aussagen tun nicht genau, was ich benötige.Obwohl sie die Top-Berichte ohne Duplikate zurückgeben (meine innere linq-Anweisung tut das auch schon), brauche ich die Berichte in einem reportItem unter ihrem jeweiligen Titel, nicht als Liste von Berichten, sondern als reportList, die alle enthält die reportItems, die dann alle ihre entsprechenden Berichte für diesen Titel enthalten (die das maximale Datum haben). – DMCApps

+0

Wenn Sammlungen teilweise gefüllt werden sollen, benötigen Sie ['DataLoadOptions'] (http://msdn.microsoft.com/de-de/library/bb534361), insb. 'AssociateWith'. Oder Sie sollten bidirektionale Navigationseigenschaften erstellen, damit Sie das reportItem und die reportList durch den Bericht zurückholen können. –