Entwickler-Ecke
Datenbanken (inkl. ADO.NET) - LINQ und Summe nach Query
UGrohne - So 14.12.08 18:18
Titel: LINQ und Summe nach Query
Hi,
ich möchte nach meiner LINQ-Query eine Summe errechnen lassen und dafür nicht unbedingt wieder die Datenbank abfragen. Daher habe ich es mit einer Lambda-Expression über das LINQ-Resultset versucht:
C#-Quelltext
1: 2: 3: 4:
| var orderList = from order in aptusOfficeData.OrderHeader where (order.ID == orderId) select order; decimal orderSum = orderList.Sum(t => t.TotalDue); |
Dummerweise kommt bei der letzten Zeile folgende Fehlermeldung:
| Zitat: |
| Der Ausdruck "Table(OrderHeader).Where(order => (order.ID = Invoke(value(System.Func`1[System.Int32])))).Sum(t => t.TotalDue)" konnte nicht in SQL übersetzt und als lokaler Ausdruck behandelt werden. |
Nach Google-Recherchen sollte das eigentlich so funktionieren, nur die Fehlermeldung sagt mir nicht so richtig woran es liegt.
Kha - So 14.12.08 19:12
Der Ausdruck in der Exception sieht merkwürdig aus, woher kommt "orderId"?
UGrohne - Mo 15.12.08 09:50
Kha hat folgendes geschrieben : |
| Der Ausdruck in der Exception sieht merkwürdig aus, woher kommt "orderId"? |
order.ID ist der Primärschlüssel der Tabelle und orderId ist der Filter. Und wem das jetzt komisch vorkommt, der hat Recht. Hab nämlich gestern noch festgestellt, dass ich nur einen Datensatz habe und damit keine Summe brauche. Trotzdem würde ich gern wissen, warum das nicht funktioniert, weil demnächst werde ich ganz sicher auf dasselbe Problem stoßen.
In den ganzen Beispielen dazu im Netz funktioniert das einwandfrei, aber anscheinend versucht er hier wieder SQL auszuführen, aber das braucht er doch gar nicht :?:
Kha - Mo 15.12.08 15:03
UGrohne hat folgendes geschrieben : |
| und orderId ist der Filter. |
Ja, aber wie und wo definiert? Eine lokale oder Closure-Variable, ein Parameter, ein Feld? Der Fehler wird jedenfalls daran liegen, dass der Wert von "orderId" nicht in die Expression eingebunden ist, sondern aus irgendeinem Grund in eine Funktion ausgelagert wurde.
UGrohne hat folgendes geschrieben : |
| In den ganzen Beispielen dazu im Netz funktioniert das einwandfrei, aber anscheinend versucht er hier wieder SQL auszuführen, aber das braucht er doch gar nicht :?: |
SQL muss am Schluss auf jeden Fall herauskommen, etwas Anderes versteht die DB schließlich nicht ;) . Deshalb darf in der Query nur die Untermenge von C#-Ausdrücken benutzt werden, die auch direkt in SQL übersetzt werden kann.
UGrohne - Mo 15.12.08 16:18
Kha hat folgendes geschrieben : |
UGrohne hat folgendes geschrieben : | | und orderId ist der Filter. | Ja, aber wie und wo definiert? Eine lokale oder Closure-Variable, ein Parameter, ein Feld? Der Fehler wird jedenfalls daran liegen, dass der Wert von "orderId" nicht in die Expression eingebunden ist, sondern aus irgendeinem Grund in eine Funktion ausgelagert wurde. |
OrderId ist ein Parameter, der der Methode übergeben wird, also der sollte da noch verfügbar sein.
Kha hat folgendes geschrieben : |
UGrohne hat folgendes geschrieben : | | In den ganzen Beispielen dazu im Netz funktioniert das einwandfrei, aber anscheinend versucht er hier wieder SQL auszuführen, aber das braucht er doch gar nicht :?: | SQL muss am Schluss auf jeden Fall herauskommen, etwas Anderes versteht die DB schließlich nicht ;) . Deshalb darf in der Query nur die Untermenge von C#-Ausdrücken benutzt werden, die auch direkt in SQL übersetzt werden kann. |
Er macht daraus also wieder SQL und schickt das an die DB und geht nicht lokal durch die Menge in diesem Fall durch und summiert das selbst auf?
Kha - Mo 15.12.08 16:46
UGrohne hat folgendes geschrieben : |
Kha hat folgendes geschrieben : | UGrohne hat folgendes geschrieben : | | und orderId ist der Filter. | Ja, aber wie und wo definiert? Eine lokale oder Closure-Variable, ein Parameter, ein Feld? Der Fehler wird jedenfalls daran liegen, dass der Wert von "orderId" nicht in die Expression eingebunden ist, sondern aus irgendeinem Grund in eine Funktion ausgelagert wurde. |
OrderId ist ein Parameter, der der Methode übergeben wird, also der sollte da noch verfügbar sein. |
Hm, auch dann kann ich es nicht nachvollziehen:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9:
| static decimal? Sum(int orderId) { using (var context = new NorthwindDataContext()) { var orderList = from order in context.Orders where (order.OrderID == orderId) select order; return orderList.Sum(t => t.Freight); } } |
| Zitat: |
| orderList.queryExpression {Table(Order).Where(order => (order.OrderID = value(ConsoleApplication1.Program+<>c__DisplayClass0).orderId))} System.Linq.Expressions.Expression {System.Linq.Expressions.MethodCallExpression} |
Eine kleine Zwischenfrage :mrgreen: : Es geht schon um Linq2SQL und nicht EF?
UGrohne hat folgendes geschrieben : |
| Er macht daraus also wieder SQL und schickt das an die DB und geht nicht lokal durch die Menge in diesem Fall durch und summiert das selbst auf? |
Genau, nur das Result-Set wird überhaupt als Objekte instanziert, der Rest läuft als normales SQL auf dem Server. Sonst müsste ja vor der ersten Query erst einmal die komplette DB heruntergeladen und als Objekte dargestellt werden - damit hätte sich O/R sicherlich nicht so schnell durchgesetzt ;) .
UGrohne - Mo 15.12.08 19:22
Kha hat folgendes geschrieben : |
Hm, auch dann kann ich es nicht nachvollziehen:
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| static decimal? Sum(int orderId) { using (var context = new NorthwindDataContext()) { var orderList = from order in context.Orders where (order.OrderID == orderId) select order; return orderList.Sum(t => t.Freight); } } |
| Zitat: | | orderList.queryExpression {Table(Order).Where(order => (order.OrderID = value(ConsoleApplication1.Program+<>c__DisplayClass0).orderId))} System.Linq.Expressions.Expression {System.Linq.Expressions.MethodCallExpression} |
Eine kleine Zwischenfrage :mrgreen: : Es geht schon um Linq2SQL und nicht EF? |
Aber natürlich, das EF hab ich bisher links liegen gelassen für dieses Projekt.
Kha hat folgendes geschrieben : |
UGrohne hat folgendes geschrieben : | | Er macht daraus also wieder SQL und schickt das an die DB und geht nicht lokal durch die Menge in diesem Fall durch und summiert das selbst auf? | Genau, nur das Result-Set wird überhaupt als Objekte instanziert, der Rest läuft als normales SQL auf dem Server. Sonst müsste ja vor der ersten Query erst einmal die komplette DB heruntergeladen und als Objekte dargestellt werden - damit hätte sich O/R sicherlich nicht so schnell durchgesetzt ;) . |
Aber ein bestehendes Resultset könnte er doch für solche Operationen doch lokale durchgehen? Oder wenigstens knnte man es konfigurieren können, dass er es so macht ;).
Kha - Mo 15.12.08 20:58
UGrohne hat folgendes geschrieben : |
| Aber natürlich, das EF hab ich bisher links liegen gelassen für dieses Projekt. |
Das wird das ADO.NET-Team nicht gerne hören :( ;) .
UGrohne hat folgendes geschrieben : |
| Aber ein bestehendes Resultset könnte er doch für solche Operationen doch lokale durchgehen? Oder wenigstens knnte man es konfigurieren können, dass er es so macht ;). |
Wenn zwei Queries die gleichen Rows zurückliefern, bekommt man auch die gleichen Objekte zurück (Object Tracking); an die DB wird die Query aber afaik immer geschickt, es könnte sich ja was geändert haben ;) .
Für totales Cahing könntest du immer noch am Anfang ToList() benutzen und dann mit Linq to Objects weiterarbeiten. Das EF geht da wohl einen anderen Weg:
http://www.hackification.com/2008/12/03/linq-to-entities-the-blackberry-storm-of-orms/
UGrohne - Mo 15.12.08 21:50
Kha hat folgendes geschrieben : |
| Das wird das ADO.NET-Team nicht gerne hören :( ;) . |
Ausschlaggebend war für mich im Moment die Handhabung, weil ich ein DataSet schön um eigene Funktionen erweitern kann, beim EF geht das anscheinend nicht so ohne Weiteres bzw. ich hab bisher keine Möglichkeit gefunden.
Kha hat folgendes geschrieben : |
Wenn zwei Queries die gleichen Rows zurückliefern, bekommt man auch die gleichen Objekte zurück (Object Tracking); an die DB wird die Query aber afaik immer geschickt, es könnte sich ja was geändert haben ;) .
Für totales Cahing könntest du immer noch am Anfang ToList() benutzen und dann mit Linq to Objects weiterarbeiten. Das EF geht da wohl einen anderen Weg: http://www.hackification.com/2008/12/03/linq-to-entities-the-blackberry-storm-of-orms/ |
Den Artikel muss ich mir mal in Ruhe durchlesen ... also während des Weihnachtsurlaubs ... 2020 *g*. Ne, mit dem EF werde ich mich demnächst mal genauer beschäftigen.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!