Konvertieren Sie den LINQ-Ausdruck in SQL-Text ohne DB-Kontext

.net c# expression-trees linq sql

Frage

LINQ to SQL oder LINQ to Entities können LINQ bereits in eine SQL-Textzeichenfolge konvertieren. Aber ich möchte, dass meine Anwendung die Konvertierung durchführt, ohne den db-Kontext zu verwenden, der wiederum eine aktive Datenbankverbindung erfordert, die beide Anbieter benötigen.

Ich möchte einen LINQ-Ausdruck in eine äquivalente SQL-Zeichenfolge für WHERE und ORDER BY Klauseln ohne eine DB-Kontextabhängigkeit konvertieren, damit die folgende Repository-Schnittstelle funktioniert:

public interface IStore<T> where T : class 
{
     void Add(T item);
     void Remove(T item);
     void Update(T item);
     T FindByID(Guid id);

     //sure could use a LINQ to SQL converter!
     IEnumerable<T> Find(Expression<Func<T, bool>> predicate);
     IEnumerable<T> FindAll();
}

FRAGE

Es ist in erster Linie der Ausdruck traversal und transform, für den ich mich interessiere. Kennt jemand eine existierende Bibliothek (nugget?), Die ich integrieren kann, um in einem solchen benutzerdefinierten Kontext verwendet zu werden?

So wie es ist, habe ich bereits mein eigenes funktionierendes "LINQ transformierte zu SQL Text" Tool erstellt, ähnlich wie dieses Ausdrucksbaum zu SQL Beispiel, das in meinem obigen Repository funktioniert. Es erlaubt mir, Code wie folgt zu schreiben:

IRepository<Person> repo = new PersonRepository();
var maxWeight = 170;
var results = repo.Find(x => (x.Age > 40 || x.Age < 20) && x.Weight < maxWeight);

Aber mein Code und dieses Beispiel sind primitiv (und dieses Beispiel selbst beruht auf einem LINQ to SQL db-Kontext). Beispielsweise behandeln beide keine "LIKE" -Anweisungen.

Ich erwarte oder brauche kein Generator-Tool, das alle erdenklichen LINQ-Abfragen abwickelt. Zum Beispiel mache ich mir keine Sorgen über die Handhabung und Generierung von Joins oder Includes. Tatsächlich kann mein eigener benutzerdefinierter Code mit weiteren ~ 20 Stunden alle Fälle abdecken, die mir wichtig sind (hauptsächlich "WHERE" - und "ORDER BY" -Aussagen).

Aber gleichzeitig habe ich das Gefühl, dass ich meinen eigenen benutzerdefinierten Code dafür nicht schreiben sollte. Wenn ich feststelle, dass ich meine eigenen schreibe, wäre ich immer noch interessiert, wenn mich jemand auf bestimmte Klassen verweisen könnte, die ich reflektieren und nachahmen kann (NHibernate, EF usw.). Ich frage nach bestimmten Klassen zu sehen, wenn Sie sie kennen, weil ich nicht stundenlang den Code eines massiven Werkzeugs durchforsten will, nur um den Teil zu finden, den ich brauche.

Nicht, dass es wichtig wäre, aber wenn jemand wissen möchte, warum ich nicht einfach LINQ to SQL oder LINQ to Entities benutze, verwende ich für meine spezifische Anwendung einfach ein Tool wie Dapper .

USE CASES Ob ich das Tool selbst erstellen oder eine Bibliothek von Drittanbietern finden möchte, hier sind Gründe, warum eine "LINQ to SQL Textzeichenfolge" nützlich wäre:

  • Das Prädikat, das ich in die IRepository.Find Methode IRepository.Find , hat Intellisense- und grundlegende Kompilierzeitüberprüfung.
  • Meine vorgeschlagene IStore-Schnittstelle kann für den DB-Zugriff oder den Web-Service-Zugriff implementiert werden. Um zu klären, ob ich das LINQ "WHERE / ORDER BY" -Prädikat in eine SQL "WHERE / ORDER BY" -Klausel konvertieren kann, dann ...
    • Die SQL-Zeichenfolge könnte direkt von Dapper verwendet werden.
    • Die SQL-Zeichenfolge kann im Gegensatz zu einem LINQ-Ausdruck an einen WCF-Dienst gesendet werden, der für direkten DB-Zugriff verwendet wird (der selbst möglicherweise nicht Dapper verwendet).
    • Die SQL-Zeichenfolge kann mit benutzerdefiniertem Code in eine LINQ-Anweisung vom WCF-Dienst deserialisiert werden. Eric Lippert kommentiert dies .
  • Die Benutzeroberfläche kann IQueryable-Mechaniken verwenden, um ein Prädikat für das Repository dynamisch zu generieren

Kurz gesagt, ein solches Tool hilft, die "Spezifikation" oder das "Abfrageobjekt" Konzept von Repositories gemäß DDD zu erfüllen, und zwar ohne eine Abhängigkeit von EF oder LINQ zu SQL zu nehmen.

Akzeptierte Antwort

Das ist etwas, auf das ich vor einiger Zeit kurz eingegangen bin. Sie können sich unter http://iqtoolkit.codeplex.com/ und / oder http://expressiontree.codeplex.com/ nach Ideen umsehen. Wie von anderen erwähnt, ist die Erstellung von Linq-Abfrageanbietern alles andere als trivial, wenn Sie Ihren Bereich nicht auf die minimalen Funktionen beschränken, die Sie wirklich benötigen.

Wenn sich Ihre Ziele auf "Spezifikation" oder "Abfrageobjekt" von Repositories gemäß DDD beziehen, ist dies möglicherweise nicht die beste Vorgehensweise. Anstelle von CRUD-artigen abstrahierten Technologien kann es produktiver sein, sich auf Wege zu konzentrieren, wie das Verhalten der Domäne ausgedrückt werden kann, mit einem Minimum an direkten Abhängigkeiten von technologiebezogenen Abstraktionen. Wie Eric Evans kürzlich diskutierte, bedauert er die Konzentration auf technische Bausteine ​​wie Repositories in seinen ersten Beschreibungen von DDD.


Beliebte Antwort

Dies zu tun ist wirklich extrem kompliziert, besonders wenn Sie gerade jetzt nicht viel über Expression-Bäume wissen (was IQueryable zur Darstellung von Abfragen verwendet).

Aber wenn Sie wirklich anfangen möchten (oder einfach nur eine Vorstellung davon bekommen, wie viel Arbeit es wäre), schauen Sie sich Matt Warrens 17-teilige Serie an, die einen IQueryable-Anbieter aufbaut .



Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow