2009-06-05 12 views
3

Stellen Sie sich vor, es gibt zwei Tabellen.LINQ zu SQL SubSelect wie Abfrage

Order 
+----------------+ 
| ID    | 
| Name   | 
+----------------+ 

OrderStatus 
+----------------+ 
| ID    | 
| OrderId  | 
| StatusId  | 
+----------------+ 

Eine Bestellung kann mehr als einen OrderStatus haben, der OrderStatusHistory heißen könnte. Ich werde einen StronglyTypeObject Auftrag habe, die als

namespace my.project 
{ 
    public class Order 
    { 
     Int64 OrderId { get; set; } 
     String Name { get; set; } 
     Int64 StatusId { get; set; } 
    } 
} 

Diese StatusID im Auftrag Objekt sollten folgen descripted der aktuelle (zuletzt) ​​StatusID von der Orderstatus Tabelle sein.

Ich habe versucht, eine IQueryable Liste von Objekten mit LINQ zu erstellen. Hier ist meine, nicht funktioniert;), Linq-Code

var result = from r in dbContext.ORDER 
      select new Order 
      { 
       OrderId = r.ID, 
       Name = r.Name, 
       StatusId = dbContext.OrderStatus 
          .Where(p => p.OrderId == r.ID).Last().StatusId 
      } 

Ich habe auch mit Max versucht, Arbeit (p => p.XXX), aber es hat nicht geklappt. Hat jemand einen Hinweis auf dieses Problem?

Jede Hilfe wäre sehr willkommen ...

Gordon

+0

Dies veranschaulicht, warum ich Linq und ähnliche ORM-Lösungen kritisiert habe. Hier ist ein Problem, das eine allgemein bekannte und relativ einfache Lösung in einer gut etablierten Sprache hat. Um einige theoretische Vorteile zu erhalten, verzichten Sie auf echte Produktivität. Haben die Gewinne, die Sie von Linq erhalten haben, mehr Zeit als nötig, um eine redundante (und idiosynkratische) Art der Abfrage von Daten zu lernen? Siehe http://stackoverflow.com/questions/458802/doesnt-linq-to-sql-miss-the-point-arent-orm-mappers-subsonic-etc-sub-opti für die Diskussion. –

Antwort

2

Based auf deinen Kommentar, ich habe die folgenden aktualisiert, um zuerst zu verwenden, und in diesem Fall müssen Sie einen OrderByDescending auf dem Schlüssel tun, um es in der richtigen Reihenfolge zu bekommen.

var result = from r in dbContext.ORDER 
     select new Order 
     { 
      OrderId = r.ID, 
      Name = r.Name, 
      StatusId = dbContext.OrderStatus 
         .Where(p => p.OrderId == r.ID) 
         .OrderByDescending(p => p.ID) 
         .First() 
         .StatusId 
     } 

Auch, wenn Sie eine FK Beziehung definiert haben, sollte es viel einfacher sein, die letzte StatusID zu erhalten, ohne ein Zwischen Objekt zu erstellen. In diesem Fall denke ich, dass Sie Last (wenn die Objekte vorgeladen sind) verwenden können, da Sie LINQtoObjects und nicht LINQToSQL ausführen. YMMV.

var currentStatus = order.OrderStatuses.Last().StatusId; 

Letzteres könnte als Methode für eine partielle Klasse für ORDER hinzugefügt werden, so dass Sie darauf verweisen können.

var currentStatus = order.CurrentStatus; 

public partial class ORDER 
{ 
    public int64 CurrentStatus 
    { 
     get 
     { 
      return this.OrderStatuses.Last().StatusId; 
     } 
    } 
} 
+0

Danke für Ihre sehr hilfreiche Antwort. Aus der Logik der LINQ Query hatte ich genau das geschrieben wie Sie. Das Problem, das ich gerade habe, ist, dass die Anweisung eine System.NotSupportedException auslöst. Der Queryoperator "Last" wird nicht unterstützt.Das verstehe ich nicht. – Gordon

+0

Ok, dann OrderByDescending und stattdessen First verwenden. Ich werde aktualisieren. – tvanfosson

1

in Ordnung, wie etwa diese: (nehmen Sie zwei, absteigend sortieren und nehmen Sie die erste .. top 1)

var result = from r in dbContext.ORDER 
     select new Order 
     { 
      OrderId = r.ID, 
      Name = r.Name, 
      StatusId = dbContext.OrderStatus 
           .Where(p => p.OrderId == r.ID) 
           .OrderByDescending(p => p.OrderID) 
           .Select(p => p.StatusId) 
           .FirstOrDefault() 
     } 
+0

Das ist der ähnliche Ansatz, den ich verwendet habe. Es wählt die Max() - Status-ID aus der OrderStatus-Tabelle aus. Das Problem ist, dass ein OrderStatus sein kann 1 = order_received, 2 = order_payed, 3 = order_shipped, 4 = order_changed. Nachdem also die StatusId auf 4 gesetzt wurde, wird sie nach einiger Arbeit von den Verkäufern wieder auf 2 wechseln, sobald die Zahlung der Änderung wiederholt wird. Die Abfrage wird uns im Beispiel immer 4 geben. Deshalb habe ich Last() benutzt, um die letzte StatusID zu bekommen. – Gordon

+0

Das löst eine Ausnahme aus "System.NotSupportedException: QueryOperator" Last "wird nicht unterstützt". Irgendwelche Ideen? – Gordon