Wie bekomme ich Linq zu SQL, um die Ergebnismenge einer dynamischen Stored Procedure zu erkennen?

8

Ich benutze Linq-to-SQL mit einem SQL Server-Backend (natürlich) als ORM für ein Projekt. Ich muss die Ergebnismenge von einer gespeicherten Prozedur abrufen, die von einer dynamisch erstellten Tabelle zurückgegeben wird. So sieht der Proc aus:

%Vor%

Ich habe diese Prozedur nicht geschrieben, kann aber eine Änderung beeinflussen, wenn es ein wirklich ernstes Problem gibt.

Mein derzeitiges Problem ist, dass der Designer diese Funktion generiert, wenn ich diese Prozedur meinem Modell hinzufüge:

%Vor%

sieht nicht so aus wie die Ergebnismenge, die ich erhalte, wenn ich den Prozess manuell ausführe:

Kann mir jemand sagen, was hier schief läuft?

Dies ist im Grunde das gleiche Problem wie diese Frage

Danke Marc für deine Antwort. Ich werde über die von Ihnen vorgeschlagenen Änderungen nachdenken.

Das Problem war die temporäre Tabelle. Linq zu Sql weiß einfach nicht, was sie damit machen sollen. Dies war besonders schwierig zu diagnostizieren, da Visual Studio Informationen über gespeicherte Prozeduren zwischenspeichert. Wenn es zum ersten Mal fehlschlug, eine Ergebnismenge zu finden, setzte es die Rückgabe als Standard-Integer-Typ und wurde nicht aktualisiert, wenn ich Änderungen an der gespeicherten Prozedur vornahm. Um VS zu veranlassen, eine Änderung zu erkennen, müssen Sie:

  • Löschen Sie proc aus der dbml
  • Löschen Sie die Serververbindung vom Server Explorer
  • Speichern Sie die dbml, um eine Neukompilierung zu erzwingen
  • Schließen Sie das Projekt und starten Sie VS neu.
  • Erstellen Sie die Serververbindung neu und importieren Sie den proc

Sie müssen vielleicht nicht alle diese Schritte machen, aber das hat bei mir funktioniert. Was Sie tun müssen, wenn Sie eine temporäre Tabelle verwenden müssen, ist die Erstellung eines Barebone-Prozesses, der einfach das richtige Schema zurückgibt und dann nach dem Import in den OR-Designer so ändert, wie Sie möchten.

>     
Adam Lassek 30.01.2009, 16:38
quelle

2 Antworten

5

Erstens - WICHTIG - Ihr SQL ist anfällig für die Injektion; Der innere Befehl sollte parametrisiert werden:

%Vor%

Dies übergibt den Wert von @L_author in dem Parameter @author im dynamischen Befehl - verhindert Injektionsangriffe.

Zweitens - Sie brauchen die temporäre Tabelle nicht wirklich. Es tut nichts für Sie ... Sie nur EINFÜGEN und AUSWÄHLEN. Vielleicht einfach EXEC und lass die Ergebnisse natürlich zum Aufrufer fließen?

Unter anderen Umständen wäre eine Tabellenvariable besser geeignet, aber dies funktioniert nicht mit INSERT / EXEC.

Sind die Spalten für jeden Anruf gleich? Wenn dies der Fall ist, schreibe entweder den dbml manuell oder verwende einen temporären SP (nur mit "WHERE 1 = 0" oder etwas), damit SET FMT_ONLY ON funktionieren kann.

Wenn nicht (verschiedene Spalten pro Verwendung), dann gibt es keine einfache Antwort. Verwenden Sie in diesem Fall möglicherweise reguläres ADO.NET ( ExecuteReader / IDataReader - und vielleicht sogar DataTable.Fill ).

Natürlich könntest du LINQ die Belastung nehmen lassen ... (C #):

%Vor%

usw.

    
Marc Gravell 30.01.2009, 22:12
quelle
5

Es gibt keine wirklich einfache Möglichkeit, dies zu tun. Ich hatte in der Vergangenheit das gleiche Problem. Ich denke, das Problem ist, dass Linq to Sql keine Möglichkeit hat herauszufinden, welcher Typ zurückgegeben wird, da Sie die SELECT-Anweisung zur Ausführungszeit aufbauen. Was ich getan habe, um dies zu umgehen, war in der gespeicherten Proc, ich habe nur eine Auswahl und wählte alle Spalten, die ich möglicherweise benötigt. Dann hatte ich Linq zu Sql die Funktion basierend darauf generieren. Dann ging ich zurück zu SQL und änderte den gespeicherten Prozess zurück, so wie er sein sollte. Der Trick besteht darin, Ihre DBML nicht neu zu generieren.

    
BFree 30.01.2009 16:45
quelle