Feinheiten von Lambda-Ausdrücken in C #

Was ich in dem Artikel geschrieben habe, habe ich ungefähr 10 Stunden gefangen, es waren 10 Stunden kontinuierliches Debuggen, was sich auf einen schrittweisen Vergleich der funktionierenden und nicht funktionierenden Versionen des Codes reduzierte, nicht einmal das, um jede Zeile aus dem Debug-Fenster der funktionierenden und nicht funktionierenden Versionen des Codes zu vergleichen


Für einen Programmierer, der mit Ausdrucksbäumen nicht vertraut ist, enthält ein guter Einführungsartikel zu msdn einige Schritte zum Erstellen eines Baums, die ich im Artikel weggelassen habe.


In diesem Fall ist dieser Test grün (das EF-Add-In ist aktiviert und stürzt ab, wenn die Abfrage nicht vollständig in SQL übersetzt werden kann ).



  • Zunächst muss die Zuordnung des PupilName- Felds definiert werden, wenn es nicht definiert ist. Der Abfrageanbieter erkennt nicht, worauf die PupilName- Eigenschaft projiziert werden muss, um an SQL ORDER BY angehängt zu werden.
  • Zweitens muss der Anbieter diese Zuordnung analysieren, zum Beispiel funktioniert sie nicht, EF beginnt zu fluchen (standardmäßig schwört sie nicht, es werden Entitäten im Speicher ausgelöst - LINQ to Object , dies kann jedoch aktiviert werden ):




Und die Sache ist, dass der Abfrageanbieter nicht versteht, nach welchen Eigenschaften der Entität wir sortieren möchten. Wenn die Zuordnung jedoch korrekt geschrieben ist, wird der Anbieter damit umgehen, eine SQL- Abfrage senden, eine Antwort erhalten und die Ergebnisse deserialisieren.


Manchmal ist es notwendig, Ausdrücke selbst zu schreiben, d. H. Ähnliches:



Ich werde Ihnen zeigen, wie Sie diesen Ausdruck schreiben. Es ist nicht so schwierig. Der obige Link enthält mehrere ähnliche Beispiele:



Wir sammeln das Lambda Schritt für Schritt, zuerst einen Parameter, eine Eigenschaft und kleben dann alles.
In welchem ​​Fall funktioniert dies nicht und der Test ist grün (der Anbieter kann den Ausdruck nicht analysieren)?


Weiß nicht Keine Sorge, ich wusste es auch nicht und am Ende habe ich ungefähr 10 Stunden damit verbracht, es zu verstehen.
Hier ist ein Hinweis, das wird funktionieren:



PupilDto erbt von PupilDtoBase


Die Sache ist, dass PropertyInfo aus der Basisklasse übernommen werden muss, wenn die PupilName- Eigenschaft selbst zur Basisklasse gehört, sodass C # einen Lambda-Ausdruck erstellt und EF sie unter Verwendung von Sprachstandards analysiert


Beweise

Was zeigt der Debugger , wenn Sie ein reguläres Lambda in OrderBy schreiben:



Und in unserem Fall so:



AutoMapper und IncludeBase


Wenn Sie versuchen, den Code nicht zu duplizieren, sind Sie wahrscheinlich auf die Vererbung von DTO und IncludeBase gestoßen :



Es gibt eine noch komplexere Situation:



Und dieser Test wird grün sein:



Und die Sache ist die gleiche, wieder wird PropertyInfo von der Oberfläche gezogen:



Beweise

Die ReflectedType der Age- Eigenschaft ist eine Schnittstelle. IPupilDto , C # erstellt ein Lambda, in dem die Age-Eigenschaft eine Eigenschaft der PupilDto-Klasse ist, nicht die Schnittstelle. Der Automapper erstellt jedoch ein Lambda:



Wie kann man dieses Problem lösen? Wenn IncludeBase Automapper mit einer Schnittstelle nicht zu uns passt (wenn Sie die Zuordnung im Speicher verwenden - dies hat keine Auswirkungen auf Sie), müssen Sie diese API verlassen. Ich habe dieses Problem gelöst, indem ich die Zuordnung in der Erweiterungsmethode wie folgt hervorgehoben habe:



Dann findet der Auto-Mapper selbst eine geeignete Typ-Eigenschaft nach Namen und erstellt ein „korrektes“ Lambda
Vielen Dank für Ihre Aufmerksamkeit!

Source: https://habr.com/ru/post/de453720/


All Articles