2017-04-13 5 views
1

Ich habe Problem beim Konvertieren einer SQL-Abfrage in LINQ. Ich glaube, ich habe 95% davon in LINQ jedoch mit Ausgabe auf einKonvertieren von SQL-Abfrage in LINQ - Operator '&&' kann nicht auf Operanden vom Typ 'Int' und 'Bool'

SQL

SELECT 
    table1.Column1 
FROM 
    table 1 table1 
LEFT OUTER JOIN 
    table 2 table2 ON table2.Column1 = table1.Column1 
        AND table2.Column2 = 1838 
WHERE 
    table1.Column2 = 1 
    AND table1.Column3 = 24029 
    AND (table2.[Column3] IS NULL OR table2.[Column3] = 1) 

LINQ so weit kommen repliziert

var query = from table1 in table 1 
      join table2 in table 2 on table1.Column1 equals table2.Column1 && table2.Column2 == 1838 into result 
      from table2 in result.DefaultIfEmpty() 
      where table1.Column2 == 1 && table1.Column3 == 24029 && (table2.Column3 == null || table2.Column3 == 1) 
      select table1.Column1; 

Wenn ich die Abfrage ausführen ich erhalte eine Fehlermeldung bei dieser

Linie
join table2 in table 2 on table1.Column1 equals table2.Column1 && tabl2.Column2 == 1838 into result 

Fehler:

CS0019 Operator '&&' cannot be applied to operands of type 'int' and 'bool'

Irgendwelche Vorschläge bitte?

+5

Der beste Rat ist, verwenden könnte - nicht. LINQ ist nur eine Abfragesprache. * Entity Framework * hingegen ist ein * ORM *. Es ordnet * Objekte * Tabellen zu. Erstellen Sie korrekte * Entitäten * mit Relationen und Navigationseigenschaften, und EF generiert die JOIN-Anweisungen. –

+1

Unter der Annahme, dass Ihre Entitäten Order und LineItem sind, könnte jedes LineItem eine Order-Eigenschaft haben. Eine Bestellung sollte eine LineItems-Sammlung haben. Wenn Sie eine Bestellung und alle Werbebuchungen laden möchten, können Sie einfach die Bestellung laden. Seine LineItems würden damit geladen werden –

+1

Diese 'Aus Tabelle 1 Tabelle1' sieht nicht gültig aus. Auch nicht "aus Tabelle 1 in Tabelle 1". In solchen Namen darf es keine Leerzeichen geben. Auch 'table2.Column2 = 1838' sollte eigentlich in der where cause sein, nicht die on-Klausel des Joins im sql und absolut nicht in der Linq-Join. – juharr

Antwort

2

Linq ist strenger als SQL, wenn es um die on-Klausel eines Joins geht. Im Grunde vergleicht es das Zeug auf der einen Seite der equals mit der anderen Seite. equals ist nicht wie == und Sie können nicht mehr Logik mit logischen Operatoren bis zum Ende verketten. Der beste Ansatz besteht darin, die Spalten, die die Beziehung zwischen den Tabellen bilden, in die on-Klausel des Joins einzufügen.

join table2 in table_2 on table1.Column1 equals table2.Column1 into result 

Dann wird die table2.Column2 == 1838 bewegen, um die where

where table2.Column2 == 1838 
     && table1.Column2 == 1 
     && table1.Column3 == 24029 
     && (table2.Column3 == null || table2.Column3 == 1) 

Alternativ kann diese auch funktionieren würde, aber wirklich ist nicht Best Practice.

join table2 in table_2 
on new {table1.Column1, Column2 = 1838} 
equals new {table2.Column1, table2.Column2 } into result 

Wie das ist, wie Sie mehrere Vergleiche tun, aber beachten Sie, es wird nur die Gleichheit im Gegensatz zu SQL tun, dass Sie jede Art von logischer Klausel zu tun erlauben würde.

Alternativ, wenn Sie verwenden EF und die Tische haben eine Fremdschlüsselbeziehung sollten Sie Navigationseigenschaften haben, und Sie können für composite key join ist etwas anderes wie

from table1 in table_1 
from table2 in table1.table_2s.DefaultIfEmpty() 
.... 
+0

Danke @juharr für die Erklärung und Korrektur. So kam die Idee, dass nur ein Gleicher in der Join-Anweisung erlaubt ist. Ich werde versuchen, es in die Where-Klausel zu verschieben und zu sehen, ob ich dieselben Ergebnisse erzielen kann. Auch danke für den Rat bezüglich EF werde ich das prüfen. – Kevin

+0

Eine Frage, warum brauchen wir nicht, den Tabellenreferenznamen in diese Zeile für die zweite Spalte 'on new {table1.Column1, Column2 = 1838}' zu setzen? – Kevin

+1

@Kevin In diesem Fall erstellen wir eine anonyme Klasse und der Wert der zweiten Eigenschaft ist 1838 und der Name ist "Column2", so dass es mit der anderen anonymen Klasse übereinstimmt. Grundsätzlich, wenn Sie eine Eigenschaft in einer anonymen Klasse referenzieren, wird dieser Eigenschaftsname verwendet, aber für konstante Werte müssen Sie die Eigenschaft benennen. Eine andere Art zu schreiben wäre 'new {Column1 = table1.Column1, Column2 = 1838} ist gleich new {Column1 = table2.Column1, Column2 = table2.Column2}' – juharr

4

Die LINQ-Syntax. Anstatt also falsch

join table2 in table_2 on table1.Column1 equals table2.Column1 && table2.Column2 == 1838 into result 

Sie so etwas wie dieses

join table2 in table_2 
on new { table1.Column1, Column2 = 1838 } equals new { table2.Column1, table2.Column2 } 
into result 
+0

Hmm ... Is dass ein "tief gleich" oder nur eine Referenz gleich ist? –

+1

@RobertHarvey C# anonoymous Typen haben Wert Vergleich Semantik. Die gleiche Technik wird für die Gruppe nach zusammengesetztem Schlüssel verwendet, so dass es scheinbar nicht funktionieren würde, wenn es eine Referenzgleichheit wäre. –

+1

@RobertHarvey Auch in diesem Fall ist es wahrscheinlich, dass es in SQL umgewandelt wird. – juharr

Verwandte Themen