Autor Beitrag
UGrohne
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Veteran
Beiträge: 5502
Erhaltene Danke: 220

Windows 8 , Server 2012
D7 Pro, VS.NET 2012 (C#)
BeitragVerfasst: So 14.12.08 18:18 
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:
ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: So 14.12.08 19:12 
Der Ausdruck in der Exception sieht merkwürdig aus, woher kommt "orderId"?

_________________
>λ=
UGrohne Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Veteran
Beiträge: 5502
Erhaltene Danke: 220

Windows 8 , Server 2012
D7 Pro, VS.NET 2012 (C#)
BeitragVerfasst: Mo 15.12.08 09:50 
user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Mo 15.12.08 15:03 
user profile iconUGrohne hat folgendes geschrieben Zum zitierten Posting springen:
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.

user profile iconUGrohne hat folgendes geschrieben Zum zitierten Posting springen:
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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Veteran
Beiträge: 5502
Erhaltene Danke: 220

Windows 8 , Server 2012
D7 Pro, VS.NET 2012 (C#)
BeitragVerfasst: Mo 15.12.08 16:18 
user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconUGrohne hat folgendes geschrieben Zum zitierten Posting springen:
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.

user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconUGrohne hat folgendes geschrieben Zum zitierten Posting springen:
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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Mo 15.12.08 16:46 
user profile iconUGrohne hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconUGrohne hat folgendes geschrieben Zum zitierten Posting springen:
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:
ausblenden 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?
user profile iconUGrohne hat folgendes geschrieben Zum zitierten Posting springen:
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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Veteran
Beiträge: 5502
Erhaltene Danke: 220

Windows 8 , Server 2012
D7 Pro, VS.NET 2012 (C#)
BeitragVerfasst: Mo 15.12.08 19:22 
user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
Hm, auch dann kann ich es nicht nachvollziehen:
ausblenden 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.

user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconUGrohne hat folgendes geschrieben Zum zitierten Posting springen:
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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Mo 15.12.08 20:58 
user profile iconUGrohne hat folgendes geschrieben Zum zitierten Posting springen:
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 :( ;) .

user profile iconUGrohne hat folgendes geschrieben Zum zitierten Posting springen:
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: www.hackification.co...berry-storm-of-orms/

_________________
>λ=
UGrohne Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Veteran
Beiträge: 5502
Erhaltene Danke: 220

Windows 8 , Server 2012
D7 Pro, VS.NET 2012 (C#)
BeitragVerfasst: Mo 15.12.08 21:50 
user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
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.

user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
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: www.hackification.co...berry-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.