Laden...

SQL Query in Linq Lambda Expression

Erstellt von Fab4guy vor 3 Jahren Letzter Beitrag vor 3 Jahren 431 Views
F
Fab4guy Themenstarter:in
54 Beiträge seit 2016
vor 3 Jahren
SQL Query in Linq Lambda Expression

Hallo zusammen,

ich probiere jetzt seit einiger Zeit bereits diese SQL-Abfrage in C# zu überführen.
Leider hatte ich bisher keinen Erfolg.

So sieht meine SQL-Abfrage aus. Diese funktioniert auch und liefert das gewünscht Ergebnis.


SELECT count(id) as numberOfOrders, 
		SUM(DATEDIFF(DAY, allocatedDate, orderClosedDate)) as average
  FROM orders
  WHERE (allocatedDate is not null AND orderClosedDate is not null and orderClosed = 1) AND 
		(YEAR(allocatedDate) = 2020 AND 
		YEAR(orderClosedDate) = 2020) AND 
		(partNumber LIKE '341911%')

Laut meinen Internet-Recherchen muss ich immer in C# Linq, wenn ich einen Count oder SUM machen will, mit GroupBy arbeiten.
Zumindest habe ich noch kein Beispiel ohne GroupBy gefunden.

Das ist mein bisherigere Stand. Allerdings liefert der, wie erwartet wegen dem GroupBY, das falsche Ergebnis.


            var result = await this.Db.Order
                .GroupBy(g => new { g.Id, g.AllocatedDate, g.OrderClosedDate, g.OrderClosed, g.partNumber})
                .Where(w => (w.Key.AllocatedDate != null && w.Key.OrderClosedDate != null && w.Key.OrderClosed == 1) &&
                (SqlFunctions.DatePart("yyyy", w.Key.AllocatedDate) == 2020 && SqlFunctions.DatePart("yyyy", w.Key.OrderClosedDate) == 2020) &&
                (w.Key.partNumber.StartsWith("341911")))
                .Select(s => new 
                {
                    NumberOfOrders = s.Count(),
                    Average = (int)s.Sum(sum => SqlFunctions.DateDiff("day", sum.AllocatedDate.Value, sum.OrderClosedDate.Value))
                }).ToListAsync();


Kann da jemand helfen?
Viele Grüße

16.807 Beiträge seit 2008
vor 3 Jahren

Das ist korrekt, Du brauchst bei Linq für ein Sum auf die Selektion das GroupBy.
Es sind nicht alle T-SQL Queries 1:1 mit einem ORM darstellbar. Du kannst das aber in eine View auslagern und die View aufrufen.

PS: wenn Du mit EF arbeitest, dann ist die Empfehlung EF.Functions statt SqlFunctions zu verwenden.

Was Du aber probieren kannst (weiß nicht, ob es in diesem Fall funktioniert), sind eingebettete Referenzen in Linq.


var query = this.Db.Order
    .Where(w => (w.Key.AllocatedDate != null && w.Key.OrderClosedDate != null && w.Key.OrderClosed == 1) &&
    (SqlFunctions.DatePart("yyyy", w.Key.AllocatedDate) == 2020 && SqlFunctions.DatePart("yyyy", w.Key.OrderClosedDate) == 2020) &&
    (w.Key.partNumber.StartsWith("341911")));

var data = query.Select( _ => new {
   NumberOfOrders = query.Count(), // hier dein Count auf Id
   Avarage = query.Sum(datedif...) // hier das DateDiff
);

Damit kann man sich viele Queries "hin optimieren", die der Provider sonst oft hinwurstelt. Fast jeder Foren-Query hier basiert auf diesem "Hack".
Hab jetzt hier kein Intellisense, um das zuende zu schreiben. Hoffe die Art und Weise ist jedoch ersichtlich.

F
Fab4guy Themenstarter:in
54 Beiträge seit 2016
vor 3 Jahren

Wieder was gelernt.
Mit der View hast du natürlich recht. Wäre wohl mein nächster Schritt gewesen, wenn ich hier keine Antwort bekommen hätte.

Aber dein zweiter Vorschlag "Hack" funktioniert tadellos. Werde wohl erstmal damit weiter machen.

Vielen Dank für die Aufklärung. 🙂