Ich habe die folgende gespeicherte Prozedur, und wenn ich versuche, Funktionsimport auszuführen, werden in meiner gespeicherten Prozedur keine Spalten angezeigt. Was vermisse ich? Irgendwelche Vorschläge?
Der Proc:
ALTER PROCEDURE [healthc].[ev_kc_Products_Search]
(
@SearchString VARCHAR(1000)
)
AS
SET NOCOUNT ON
DECLARE @SQL VARCHAR(max),
@SQL1 VARCHAR(max),
@Tag VARCHAR(5)
CREATE TABLE #T
( ID INT,
VendorName VARCHAR(255),
ItemName VARCHAR(255),
Type VARCHAR(2),
Sequence TINYINT
)
SET @SQL = '
INSERT #T
SELECT VendorID ID,
Name VendorName,
NULL ItemName,
''V'' Type,
0 Sequence
FROM tblVendors
WHERE '+REPLACE(@SQL1,@Tag,'Name')+'
UNION ALL
BLAH BLAH BLAH'
EXEC(@SQL)
SELECT ID, VendorName, ItemName, Type FROM #T
Fügen Sie diese Zeile am Anfang Ihrer gespeicherten Prozedur ein:
SET FMTONLY OFF
Sie können dies entfernen, nachdem Sie den Import abgeschlossen haben.
Was passiert hier hinter den Kulissen?
Während des Imports der Funktion -> Spalteninformationen abrufen ... Visual Studio führt die gespeicherte Prozedur mit allen Parameterwerten als NULL aus (Sie können dies mithilfe von MS SQL Profiler überprüfen).
In Schritt 1 werden die resultierenden Spalten der gespeicherten proc mit Datentyp und Längeninformationen zurückgegeben.
Sobald die Spalteninformationen abgerufen wurden, wird durch Klicken auf die Schaltfläche "Neuen komplexen Typ erstellen" der komplexe Typ des SP erstellt.
In Ihrem Fall sind die gespeicherten proc-Parameter nicht nullfähig. Daher schlägt der Aufruf von Visual Studio fehl und gibt keine Spalten zurück.
Wie soll ich damit umgehen?
IF (1 = 0) BEGIN FMTONLY OFF Wenn @ param1 Null ist und @ param2 Null ist, dann Start wählen cast (null als varchar (10)) als Spalte1, Besetzung (null als Bit) als Spalte2, cast (null als Dezimalzahl) als Column3 END END
Um genau zu sein (in Ihrem Fall):
IF (1 = 0) BEGIN FMTONLY OFF Wenn @SearchString NULL ist, dann START wählen cast (null als int) als ID, cast (null als varchar (255)) als VendorName, cast (null als varchar (255)) als ItemName cast (null als varchar (2)) als Typ END END
geben Sie einfach den folgenden Code an den Anfang:
IF (1=2)
SET FMTONLY OFF
Hinweis: Es funktioniert in EF 6.1.3 und Visual Studio 2015 Update 3
Sie haben dieses Problem aufgrund der temporären Tabelle. Alles, was Sie tun müssen, ist:. 1. Ändern Sie Ihre gespeicherte Prozedur, um den Select-Status ohne die temporäre Tabelle zurückzugeben. 2. Gehen Sie zur Funktion importieren und rufen Sie die Spalteninformationen ab . 3. Ändern Sie Ihre gespeicherte Prozedur wieder in das Original.
Als schnelle und schmutzige Methode, um EF zu veranlassen, die Spalten zu finden, kommentieren Sie die where-Klausel in Ihrer gespeicherten Prozedur aus (fügen Sie möglicherweise eine TOP 1 hinzu, um das Zurückgeben von alles zu stoppen), fügen Sie die Prozedur zur EF hinzu und erstellen Sie den Complex Type wo wieder Klausel.
Ich möchte Sudhanshu Singhs Antwort etwas hinzufügen: Es funktioniert sehr gut, aber wenn Sie komplexere Strukturen haben, kombinieren Sie es mit einer Tabellendeklaration.
Ich habe erfolgreich Folgendes verwendet (platzieren Sie es ganz am Anfang Ihres gespeicherten Vorgangs):
CREATE PROCEDURE [EY].[MyStoredProc]
AS
BEGIN
SET NOCOUNT ON;
IF (1=0)
BEGIN
SET FMTONLY OFF
BEGIN
-- declaration + dummy query
-- to allow EF obtain complex data type:
DECLARE @MyStoredProcResult TABLE(
ID INT,
VendorName VARCHAR(255),
ItemName VARCHAR(255),
Type VARCHAR(2),
Sequence TINYINT
);
SELECT * FROM @MyStoredProcResult WHERE (1=0)
END
END
-- your code follows here (SELECT ... FROM ...)
-- this code must return the same columns/data types
--
-- if you require a temp table / table variable like the one above
-- anyway, add the results during processing to @MyStoredProcResult
-- and then your last statement in the SP can be
-- SELECT * FROM @MyStoredProcResult
END
Hinweis dass der 1=0
garantiert, dass er niemals ausgeführt wird, aber die EF zieht die Struktur davon ab.
Nachdem Sie Ihre gespeicherte Prozedur gespeichert haben, öffnen Sie die EDMX-Datei in Visual Studio, aktualisieren Sie das Datenmodell und rufen Sie den Entity Frameworks-Modellbrowser auf. Suchen Sie im Modellbrowser nach Ihrer gespeicherten Prozedur, öffnen Sie den Dialog "Funktionsimport bearbeiten", wählen Sie "Gibt eine Sammlung von ... Komplexen zurück", und klicken Sie auf die Schaltfläche "Spalteninformationen abrufen".
Es sollte die Struktur wie oben definiert angezeigt werden. Wenn dies der Fall ist, klicken Sie auf "Neuen komplexen Typ erstellen", und es wird ein solcher mit dem Namen der gespeicherten Prozedur erstellt, z. "MyStoredProc_Result" (angehängt durch "_Result").
Jetzt können Sie es in der Combobox von "Liefert eine Sammlung von ... Komplexen" im selben Dialog auswählen.
Wenn Sie etwas aktualisieren müssen, aktualisieren Sie zuerst SP. Anschließend können Sie zum Dialogfeld "Funktionsimport bearbeiten" zurückkehren und auf die Schaltfläche "Aktualisieren" klicken (Sie müssen nicht alles von Grund auf neu erstellen).
Wenn Sie eine temporäre Tabelle verwenden, kann die Entität (EDMX) nicht verstehen, was los ist.
Geben Sie also ein leeres Ergebnis mit dem Spaltennamen zurück, kommentieren Sie Ihre gesamte gespeicherte Prozedur aus und führen Sie sie im SQL-Manager aus. Rufen Sie dann den komplexen Typ in Visual Studio ab. Setzen Sie die gespeicherte Prozedur nach dem Speichern in den ursprünglichen Zustand zurück (unkommentiert).
viel Glück/
Ich hatte dieses Problem. Ich musste einen benutzerdefinierten Tabellentyp erstellen und diesen zurückgeben.
CREATE TYPE T1 AS TABLE
( ID INT,
VendorName VARCHAR(255),
ItemName VARCHAR(255),
Type VARCHAR(2),
Sequence TINYINT
);
GO
Ihre gespeicherte Prozedur sieht jetzt so aus:
ALTER PROCEDURE [healthc].[ev_kc_Products_Search]
(
@SearchString VARCHAR(1000)
)
AS
SET NOCOUNT ON
DECLARE @SQL VARCHAR(max),
@SQL1 VARCHAR(max),
@Tag VARCHAR(5)
@T [schema].T1
SET @SQL = 'SELECT VendorID ID,
Name VendorName,
NULL ItemName,
''V'' Type,
0 Sequence
FROM tblVendors
WHERE '+REPLACE(@SQL1,@Tag,'Name')+'
UNION ALL
BLAH BLAH BLAH'
INSERT INTO @T
EXEC(@SQL)
SELECT ID, VendorName, ItemName, Type FROM @T
Fügen Sie einfach die select-Anweisung ohne das Angebot hinzu, führen Sie die gespeicherte Prozedur aus, rufen Sie das Modell aktualisieren auf, bearbeiten Sie den Import Ihrer Funktion und erhalten Sie Spalteninformationen. Dies sollte die neuen Spalten füllen. Aktualisieren Sie die Ergebnismenge und kehren Sie zu Ihrer gespeicherten Prozedur zurück und entfernen Sie die gerade hinzugefügte Auswahlliste. Und führe die gespeicherte Prozedur aus. Auf diese Weise werden Ihre Spalten in der Ergebnismenge aufgefüllt. Sehen Sie unten, wo Sie die Auswahlliste ohne Anführungszeichen hinzufügen müssen.
ALTER PROCEDURE [healthc].[ev_kc_Products_Search]
(
@SearchString VARCHAR(1000)
)
AS
SET NOCOUNT ON;
SELECT VendorID ID,
Name VendorName,
NULL ItemName,
''V'' Type,
0 Sequence
FROM tblVendors
DECLARE @SQL VARCHAR(max),
@SQL1 VARCHAR(max),
@Tag VARCHAR(5)
CREATE TABLE #T
( ID INT,
VendorName VARCHAR(255),
ItemName VARCHAR(255),
Type VARCHAR(2),
Sequence TINYINT
)
SET @SQL = '
INSERT #T
SELECT VendorID ID,
Name VendorName,
NULL ItemName,
''V'' Type,
0 Sequence
FROM tblVendors
WHERE '+REPLACE(@SQL1,@Tag,'Name')+'
UNION ALL
BLAH BLAH BLAH'
EXEC (@SQL)
SELECT ID, Lieferantenname, Artikelname, Typ FROM #T
Ich hoffe, das hilft jemandem da draußen.