Verwenden der C # -Funktion in der Entity Framework-Abfrage

8

In meinem C # -Code habe ich zwei WHERE-Abfragen, von denen ich beide auf ein IQueryable zugreifen kann und die ganze Sache auf SQL kompiliert haben, und beide haben eine Menge gemeinsamer Logik.

Ich glaube, das ist KEINE Duplizierung dieser ähnlichen Frage: Verwendung der Funktion in Select-Klausel der Entity Framework-Abfrage , weil in meinem Szenario kann die fragliche Funktion in SQL konvertiert werden - EF merkt einfach nicht, dass es das kann.

Die Abfragen sind ungefähr:

%Vor%

AND

%Vor%

Also eine grundlegende BusinessLogic-Regel für "besitzt eine Vorlage" und dann eine Folge davon für "besitzt DataReturn, wenn Firma mit Vorlage übereinstimmt"

Wie Sie sehen können, denken Sie nur an die C #, diese könnten leicht umstrukturiert werden als:

%Vor%

So reduzieren Sie die Duplizierung (Yay!)

Aber dann wird sich EF beschweren, dass es nicht weiß, was es mit UserOwnsTemplate machen soll, trotz der Tatsache, dass es die Logik in SQL perfekt verarbeiten kann.

AFAICT gibt es keinen schönen Weg, dies zu lösen. Ich denke, meine Optionen sind:

  • Verwandle UserOwnsTemplate in eine UDF, eine in der Datenbank definierte SQL-Funktion.
    • Aber ich kann kein UDF aus einem C # lamda erstellen, ich muss das SQL definieren, was mühseliger wäre.
  • Weisen Sie Expression<Func<Template,bool>> , das UserOwnsTemplate definiert, als Variable zu, und erstellen Sie dann relevante Expression<Func<DataReturn ,bool>> für die DataReturn-Version von Hand mit Expression.AndAlso , um die beiden "Klauseln" zusammen zu kleben.
    • Meta-Programmierung. Ughhh. Ich habe das schon mal in einem anderen Projekt gemacht und es war abscheulich zu tun, und ein Alptraum zu halten.
  • Lebe mit der Duplizierung.
    • Wahrscheinlich wird passieren, wenn SO nichts anderes raten kann. ;)

Kann jemand andere verfügbare Optionen sehen?

Kann ich etwas tun, um EF zu zwingen, die Funktion in SQL zu analysieren? (Der Begriff "Inling" kommt mir in den Sinn, aber ich weiß nicht 100%, was ich damit meine?)

Kann jemand eine Möglichkeit sehen, ret.Request.Template in ein IQueryable umzuwandeln, so dass ich einfach die andere WhereIsOwnedBy-Erweiterungsmethode darauf aufrufen kann?

Irgendwelche anderen Vorschläge überhaupt?

    
Brondahl 14.10.2015, 11:33
quelle

2 Antworten

1

Sie können Ihre Syntax beibehalten und es funktionieren lassen, aber Sie müssen eine zusätzliche Methode für das äußere IQueryable & lt; & gt;.

aufrufen

Der Trick besteht darin, die IQueryable & lt; & gt; .Expression manuell durch eine Kopie zu ersetzen, in der Sie den Funktionsaufruf durch den entsprechenden Ausdruck & gt; ersetzen.

Die Idee ist also, so etwas zu tun:

%Vor%

Und dann können Sie das tun:

%Vor%     
Guillaume86 08.01.2016 21:52
quelle
0

Das Problem ist, dass Ihre Methode Teil der Ausdrucksbaumstruktur wird und dass EF sie nicht auswerten kann. Grundsätzlich ist es möglich, Teile des Ausdrucksbaums auszuwerten, bevor die Abfrage ausgelöst wird. Sehen Sie sich Re-Linq an: Ссылка Es hat eine Klasse PartialEvaluatingExpressionTreeVisitor, die alle partiellen Ausdrucksbäume auswerten kann, dh es wird Ihre Methode finden, werten Sie es aus und injizieren Sie den eigentlichen Ausdrucksbaum. Dies wird zu bestimmten Kosten für die Leistung kommen, aber es kann nicht signifikant sein, und Sie müssen sauberes Design im Vergleich zu Leistung messen.

    
Roland 14.10.2015 20:40
quelle