So rufen Sie eine gespeicherte Prozedur in EF Core 3.0 über FromSqlRaw auf

9

Ich bin kürzlich von EF Core 2.2 auf EF Core 3.0 migriert.

Leider habe ich keine Möglichkeit gefunden, eine gespeicherte Prozedur aufzurufen, die eine Entität zurückgibt.

In EF Core 2.0 war Folgendes möglich:

var spParams = new object[] { "bla", "xx" };
var createdPath = ModelContext.Paths.FromSql("AddNodeWithPathProc  @p0, @p1", spParams).Single();

In EF Core 3.0 wird die Methode FromSQLdurch ersetzt FromSqlRaw. Es ist mir jedoch nicht gelungen, eine gespeicherte Prozedur erfolgreich aufzurufen und den Wert dann zu verarbeiten. Dies ist nützlich, wenn die gespeicherte Prozedur Daten in die Datenbank einfügt.

In EF Core 3.0 verwende ich diesen Code:

var createdPath = ModelContext.Paths.FromSqlRaw("AddNodeWithPathProc @p0, @p1", spParams).Single();

Es wird jedoch eine Ausnahme ausgelöst, da die generierte SQL ungültig ist und ungefähr so ​​aussieht:

exec sp_executesql N'SELECT TOP(2) [p].[PathId], [p].[Level], [p].[NodeId], [p].[NodePath], [p].[NodePathString]
FROM (
     @sql @p0, @p1
) AS [p]',N'@p0 nvarchar(4000),@p1 nvarchar(4000), @sql nvarchar(100)',@p0=N'1a',@p1=N'', @sql=N'AddNodeWithPathProc'

Ich habe einige Variationen ausprobiert, aber ohne Erfolg.

Ich fange an zu denken, dass es nicht möglich ist, gespeicherte Prozeduren mit auszuführen ModelContext.[IQueryable].FromSqlRaw. Meiner Meinung nach besiegt diese Art einen der Hauptgründe dafür FromSqlRaw, dass LINQ für normale Select-Anweisungen normalerweise gut genug ist.

Weiß jemand, wie man gespeicherte Prozeduren in Kombination mit FromSqlRawin EF Core 3.0 verwendet? Jede Hilfe wird sehr geschätzt.

Danke im Voraus

PS: Ich weiß, dass Sie eine gespeicherte Prozedur mit ausführen können this.Database.ExecuteSqlRaw(SQL, parameters). Auf diese Weise ist es jedoch nicht möglich, Entitäten abzurufen, die von der gespeicherten Prozedur abgefragt werden.

Dan
quelle
2
Versuchen Sie .ToList () anstelle von .Single (). .Single () generiert den Wrapper "TOP (2)".
David Browne - Microsoft
Meine vorübergehende Problemumgehung ist im Moment folgende: this.ModelContext.ExecuteRawSql ("EXEC AddNodeWithPathProc @ p0, @ p1", spParams); var createdPath = ModelContext.Paths.FromSqlRaw ("SELECT TOP 1 * FROM dbo.Path ORDER BY PathID DESC"). Single (); Dies ist jedoch keine akzeptable Lösung für die Produktion.
Dan
ja .. ToList () funktioniert .. vielen Dank :-)
Dan

Antworten:

5

Lösung (dank David Browne hätten Sie es als Antwort posten sollen):

Single durch ToList zu ersetzen funktioniert :-)

var createdPath = ModelContext.Paths.FromSqlRaw("AddNodeWithPathProc  {0}, {1}", nodeTitle, parentPathString).ToList();
Dan
quelle
1
var result=context.yourmodelclass.FromSqlInterpolated($"StoredProcedureName {param1},{param2}").tolist();

Bei Bedarf können Sie mehrere Parameter hinzufügen. Hinweis:

  • context => Ihr Name der Datenbank.
  • yourmodelclass => die Klasse im Modellordner, die Sie zum Abrufen des Ausgabeergebnisses aus dem Ergebnis der gespeicherten Prozedur erstellen.
Mohammad Irtaza
quelle
0

Ich bin nicht dort, wo ich testen kann, aber ich denke, dass Folgendes funktionieren wird:

var createdPath = ModelContext.Paths.FromSqlRaw("AddNodeWithPathProc {0}, {1}", parm1 parm2).Single();
Edney Holder
quelle
1
Nein, das funktioniert nicht. Habe es gerade getestet. Die SQL, die ungültig ist :-(. Ich glaube, sie hat etwas mit der generierten SQL zu tun. Wenn ich die SQL mit dem Profiler überprüfe, folgt sie immer dem Schema: sp_executesql 'SELECT * FROM {mySqlPassedInMethod}. Ich würde nicht wissen, wie eine gespeicherte Prozedur in diesem Code übergeben wird. Entweder erkennt die .net-Methode, dass die übergebene SQL-Zeichenfolge für eine gespeicherte Prozedur bestimmt ist, und passt die generierte SQL entsprechend an, oder es gibt einen Weg in T-SQL, den ich nicht kenne wissen von (ich bin kein Experte)
Dan
0

versuchen Sie, SqlParameter zu trennen:

SqlParameter param1 = new SqlParameter("@p0","value");
SqlParameter param2 = new SqlParameter("@p1","value");

var createdPath = ModelContext.Paths.FromSqlRaw("AddNodeWithPathProc @p0 @p1", param1, 
param2).Single();
ISTech
quelle
hat unten eine Lösung für Ihr gelöschtes Posting veröffentlicht.
jdweng
Ich habe es gerade versucht und es schlägt fehl :-(. Der Fehler lautet: "System.InvalidCastException: 'Die SqlParameterCollection akzeptiert nur Objekte vom Typ SqlParameter, keine Objekte vom Typ SqlParameter.'". Es wurde keine SQL an den SQL-Server gesendet (gemäß SQL Profiler)
Dan
@jdweng Vielen Dank :) Diese Lösung habe ich, wenn ich mich bei meiner Software anmelde und die letzte aktualisierte XML-Datei mit dem letzten Datum herunterlade, aber ich benötige alle Daten der Raten, ohne sie zu verpassen. Ich habe also eine andere Möglichkeit, Daten festzulegen und eine Excel-Datei mit den Raten herunterzuladen, aber ich weiß nicht, wie ich das implementieren soll. einen Dienst auf dem Server ausführen? Vielleicht werden Benutzer eine Woche lang keine Software verwenden, sodass ich die ganze Woche der Wechselkurse verpasst habe.
ISTech
@ISTech: Schauen Sie sich die folgende Seite an: boi.org.il/de/Markets/Pages/explainxml.aspx Sie können der URL ein Datum hinzufügen. boi.org.il/currency.xml?rdate=20120101
jdweng
@ISTech: Ich habe den folgenden Code aktualisiert, um einen bestimmten Zeitraum festzulegen.
JDWeng
0

Es ist extrem seltsam ... kurz vor ein paar Tagen habe ich das gleiche Problem und folge diesem Beitrag. Ich hatte diesen Anruf:

 public IEnumerable<TableChange> GetTableLastChanges(string tableName, string keyColumn, out int synchronizationVersion)
    {
        var parameters = new[] {
            new SqlParameter("@table_name", SqlDbType.VarChar) { Direction = ParameterDirection.Input, Value = tableName },
            new SqlParameter("@key_column", SqlDbType.VarChar) { Direction = ParameterDirection.Input, Value = keyColumn },
            new SqlParameter("@synchronization_version", SqlDbType.BigInt) { Direction = ParameterDirection.InputOutput, Value = 0 }
        };

        var changes = this.TableChanges.FromSqlRaw("[dbo].[GetTableLastChanges] @table_name, @key_column, @synchronization_version OUTPUT", parameters).ToList();

        synchronizationVersion = Convert.ToInt32(parameters[2].Value);

        return changes;
    }

Im Moment ist alles in Ordnung und dieser Anruf funktioniert wie erwartet. Daher sollte ich zugeben, dass es kein Problem mit der Rückgabe von Datensätzen und Parametern für EF auf Core 3 gibt.

juriko
quelle