2017-09-20 1 views
-1

bieten, was die beste Praxis ist Sub-Abfrage in LINQ, zum Beispiel ich diese folgenden Abfrage verwenden zu konvertieren:Wie SQL Unterabfrage in LINQ

select VerID = (select top 1 x.INTERNALPACKINGSLIPID from 
        CUSTPACKINGSLIPVERSION x where a.RECID = x.CUSTPACKINGSLIPJOUR 
        order by x.VERSIONDATETIME desc), 
     c.LINENUM, c.RECID, * 
from CUSTPACKINGSLIPJOUR a inner join CUSTPACKINGSLIPTRANS c 
     on a.PACKINGSLIPID = c.PACKINGSLIPID 

Antwort

1

ich simulierte Du Datenbank mit Klassen die Syntax korrekt zu erhalten. Nehmen Sie bei Bedarf Änderungen vor. Es gibt keine beste Methode. Einige Leute mögen es, Wo statt Joins zu verwenden. Ich mag Joins.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      List<CUSTPACKINGSLIPVERSIONs> CUSTPACKINGSLIPVERSION = new List<CUSTPACKINGSLIPVERSIONs>(); 
      List<CUSTPACKINGSLIPJOURs> CUSTPACKINGSLIPJOUR = new List<CUSTPACKINGSLIPJOURs>(); 
      List<CUSTPACKINGSLIPTRANSs> CUSTPACKINGSLIPTRANS = new List<CUSTPACKINGSLIPTRANSs>(); 

      var VerId = (from vId in CUSTPACKINGSLIPVERSION 
         join slipId in CUSTPACKINGSLIPJOUR on vId.INTERNALPACKINGSLIPID equals slipId.RECID 
         join cId in CUSTPACKINGSLIPTRANS on vId.INTERNALPACKINGSLIPID equals cId.PACKINGSLIPID 
         select new { vid = vId, slipId = slipId, cId = cId }) 
         .GroupBy(x => x.vid.VERSIONDATETIME) 
         .OrderBy(x => x.Key) 
         .FirstOrDefault() 
         .Select(x => new { linenum = x.cId.LINENUM, recid = x.cId.RECID }) 
         .ToList(); 
     } 
    } 
    public class CUSTPACKINGSLIPVERSIONs 
    { 
     public int INTERNALPACKINGSLIPID { get; set; } 
     public DateTime VERSIONDATETIME { get; set; } 
    } 
    public class CUSTPACKINGSLIPJOURs 
    { 
     public int RECID { get; set; } 
     public int PACKINGSLIPID { get; set; } 
    } 
    public class CUSTPACKINGSLIPTRANSs 
    { 
     public int PACKINGSLIPID { get; set; } 
     public int LINENUM { get; set; } 
     public int RECID { get; set; } 
    } 
} 
+0

Ich weiß nicht, ob ich Ihre Frage falsch interpretiert hatte: es gibt erste Aufzeichnung von 'lineum' &' recid', aber das OP hat '*' in 'SELECT', was bedeutet, dass er alle' CUSTPACKINGSLIPJOUR' Spalten auswählen möchte, dann alle 'LINENUM' +' RECID' zurückgibt und nur einen einzelnen Datensatz von 'zurückgibt INTERNALPACKINGSLIPID'. –

+0

Ich kann nicht sagen, was * in diesem Fall bedeutet. Es könnte eine Eigenschaft oder 100 Eigenschaften sein. Das Original hat immer wieder 1 ausgewählt und ich kann nicht sagen, ob das eine Zeile oder viele Zeilen sind. Ich habe das Beste gemacht, was ich konnte mit der Menge an Informationen gepostet. – jdweng

+0

Ich habe den Code so geändert, dass er nach Datum gruppiert ist, sodass Sie alle Zeilen für das letzte Datum erhalten. – jdweng

0

Sie haben dies in Ihrer Abfrage, und ich gehe davon aus es ist ein Tippfehler: a.RECID = x.CUSTPACKINGSLIPJOUR weil CUSTPACKINGSLIPJOUR der Name Sammlung ist. Daher habe ich stattdessen SomeId verwendet. Aber das sollte Ihnen die Idee geben:

Machen Sie eine Unterabfrage innerhalb der Projektion. Sie müssen auch bestellen, indem Sie absteigen und dann den ersten Datensatz nehmen - das wird wie top 1 sein. Hier ist die Abfrage:

var query = from a in CUSTPACKINGSLIPJOUR 
      join c in CUSTPACKINGSLIPTRANS on a.PACKINGSLIPID equals c.PACKINGSLIPID 
      select new 
      { 
       VerID = (from x in CUSTPACKINGSLIPVERSION 
         where a.RECID == x.SomeId select x) 
         .OrderByDescending(o => o.VERSIONDATETIME) 
         .First().INTERNALPACKINGSLIPID, 
       c.LINENUM, 
       c.RECID 
      }; 

Sie es mit den folgenden Sammlungen testen:

var CUSTPACKINGSLIPJOUR = new List<CUSTPACKINGSLIPJOUR> { new CUSTPACKINGSLIPJOUR { PACKINGSLIPID = 1, RECID = 1 }, 
     new CUSTPACKINGSLIPJOUR { PACKINGSLIPID = 2, RECID = 2 }}; 
     var CUSTPACKINGSLIPTRANS = new List<CUSTPACKINGSLIPTRANS> 
     { 
      new CUSTPACKINGSLIPTRANS { LINENUM = 1, RECID = 1, PACKINGSLIPID = 1 } 
     }; 
     var CUSTPACKINGSLIPVERSION = new List<CUSTPACKINGSLIPVERSION> 
     { 
      new CUSTPACKINGSLIPVERSION { INTERNALPACKINGSLIPID = 1, SomeId = 1, VERSIONDATETIME = DateTime.Today.AddDays(-1) }, 
      new CUSTPACKINGSLIPVERSION { INTERNALPACKINGSLIPID = 2, SomeId = 1, VERSIONDATETIME = DateTime.Today } 
     }; 

Es wird die gleiche Abfrage, wenn Sie eine DbSet<T> verwenden.

0

Angenommen, Sie jene Setup:

public class TBL_CUSTPACKINGSLIPVERSION 
{ 
    public int CUSTPACKINGSLIPVERSION_ID { get; set; } 
    public int INTERNALPACKINGSLIPID { get; set; } 
    public DateTime VERSIONDATETIME { get; set; } 
} 
public class TBL_CUSTPACKINGSLIPJOUR 
{ 
    public int RECID { get; set; } 
    public int PACKINGSLIPID { get; set; } 
} 
public class TBL_CUSTPACKINGSLIPTRANS 
{ 
    public int PACKINGSLIPID { get; set; } 
    public int LINENUM { get; set; } 
    public int RECID { get; set; } 
} 

var CUSTPACKINGSLIPVERSION = new List<TBL_CUSTPACKINGSLIPVERSION>(); 
var CUSTPACKINGSLIPJOUR = new List<TBL_CUSTPACKINGSLIPJOUR>(); 
var CUSTPACKINGSLIPTRANS = new List<TBL_CUSTPACKINGSLIPTRANS>(); 

Dann können Sie die kombinierte Abfrage, wie unten in Beispiel gegeben Einrichtung (angenommen CUSTPACKINGSLIPVERSION_ID die Identitätsschlüssel ist, der zwischen CUSTPACKINGSLIPJOUR & CUSTPACKINGSLIPTRANS im Vergleich verwendet):

Beachten Sie, dass Ihre Abfrage * am Ende der SELECT-Anweisung enthält, die angeben kann, dass die Abfrage alle Datensätze aus beiden zurückgibt Tabellen beteiligt in join Klausel. Wenn Sie nur ganze Datensätze von CUSTPACKINGSLIPJOUR zurückkehren möchten, aber nicht alle CUSTPACKINGSLIPTRANS zurückkehren, sind a in die select new Anweisung (enthält SQL Nutzung von a.*):

select new { 
    VerID = (from x in CUSTPACKINGSLIPVERSION 
      where a.RECID == x.CUSTPACKINGSLIPVERSION_ID // should be an identity column/primary key to compare with 
      orderby x.VERSIONDATETIME descending 
      select x).FirstOrDefault().INTERNALPACKINGSLIPID, 
    c.LINENUM, 
    c.RECID, 
    a // used if you want to return all records from CUSTPACKINGSLIPJOUR 
}).ToList();