web-dev-qa-db-de.com

EF4 - Die ausgewählte gespeicherte Prozedur gibt keine Spalten zurück

Ich habe Abfrage in einer gespeicherten Prozedur, die einige Verbindungsserver mit etwas dynamischem SQL aufruft. Ich verstehe, dass EF das nicht mag, deshalb habe ich alle Spalten aufgelistet, die zurückgegeben werden würden. Dennoch mag es das immer noch nicht. Was mache ich hier falsch? Ich möchte nur, dass EF die von der gespeicherten Prozedur zurückgegebenen Spalten erkennen kann, damit ich die benötigten Klassen erstellen kann.

Bitte beachten Sie den folgenden Code, der die letzten Zeilen meiner gespeicherten Prozedur ausmacht:

SELECT
    #TempMain.ID,
    #TempMain.Class_Data,
    #TempMain.Web_Store_Class1,
    #TempMain.Web_Store_Class2,
    #TempMain.Web_Store_Status,
    #TempMain.Cur_1pc_Cat51_Price,
    #TempMain.Cur_1pc_Cat52_Price,
    #TempMain.Cur_1pc_Cat61_Price,
    #TempMain.Cur_1pc_Cat62_Price,
    #TempMain.Cur_1pc_Cat63_Price,
    #TempMain.Flat_Length,
    #TempMain.Flat_Width,
    #TempMain.Item_Height,
    #TempMain.Item_Weight,
    #TempMain.Um,
    #TempMain.Lead_Time_Code,
    #TempMain.Wp_Image_Nme,
    #TempMain.Wp_Mod_Dte,
    #TempMain.Catalog_Price_Chg_Dt,
    #TempMain.Description,
    #TempMain.Supersede_Ctl,
    #TempMain.Supersede_Pn,
    TempDesc.Cust_Desc,
    TempMfgr.Mfgr_Item_Nbr,
    TempMfgr.Mfgr_Name,
    TempMfgr.Vendor_ID
FROM
    #TempMain
        LEFT JOIN TempDesc ON #TempMain.ID = TempDesc.ID
        LEFT JOIN TempMfgr ON #TempMain.ID = TempMfgr.ID
59
cjbarth

EF unterstützt nicht den Import gespeicherter Prozeduren, deren Ergebnismenge aus folgenden Elementen besteht:

  • Dynamische Abfragen
  • Temporäre Tische

Der Grund ist, dass zum Importieren der Prozedur EF sie ausführen muss . Ein solcher Vorgang kann gefährlich sein, da er einige Änderungen in der Datenbank auslösen kann. Aus diesem Grund verwendet EF einen speziellen SQL-Befehl, bevor die gespeicherte Prozedur ausgeführt wird:

SET FMTONLY ON

Durch Ausführen dieses Befehls gibt die gespeicherte Prozedur nur "Metadaten" über Spalten in ihrer Ergebnismenge zurück und führt ihre Logik nicht aus. Da die Logik jedoch nicht ausgeführt wurde, gibt es keine temporäre Tabelle (oder erstellte dynamische Abfrage), sodass die Metadaten nichts enthalten.

Sie haben zwei Möglichkeiten (außer derjenigen, bei der die gespeicherte Prozedur neu geschrieben werden muss, um diese Funktionen nicht zu verwenden):

  • Definieren Sie den zurückgegebenen komplexen Typ manuell (ich denke, es sollte funktionieren)
  • Verwenden Sie einen Hack und fügen Sie einfach die gespeicherte Prozedur an den Anfang SET FMTONLY OFF. Dadurch kann der Rest des SP-Codes normal ausgeführt werden. Stellen Sie nur sicher, dass Ihr SP keine Daten ändert, da diese Änderungen während des Imports ausgeführt werden! Nach erfolgreichem Import entfernen Sie diesen Hack.
140
Ladislav Mrnka

Durch Hinzufügen dieses nichtlogischen Codeblocks wurde das Problem behoben. Obwohl es nie Hit wird

IF 1=0 BEGIN
    SET FMTONLY OFF
END

Warum mag mein typisiertes Dataset keine temporären Tabellen?

http://social.msdn.Microsoft.com/Forums/en-US/adodotnetdataset/thread/fe76d511-64a8-436d-9c16-6d09ecf436ea/

Oder Sie können einen benutzerdefinierten Tabellentyp erstellen und diesen zurückgeben.

CREATE TYPE T1 AS TABLE 
( ID bigint NOT NULL
  ,Field1 varchar(max) COLLATE Latin1_General_CI_AI NOT NULL
  ,Field2 bit NOT NULL
  ,Field3 varchar(500) NOT NULL
  );
GO

Dann in der Prozedur:

DECLARE @tempTable dbo.T1

INSERT @tempTable (ID, Field1, Field2, Field3)
SELECT .....

....

SELECT * FROM @tempTable

Nun sollte EF den zurückgegebenen Spaltentyp erkennen können.

12

Stellen Sie sicher, dass die Prozedur tatsächlich ausgeführt wird. In meinem Fall habe ich die Prozedur glücklich und fehlerfrei in SQL Server Management Studio ausgeführt und dabei komplett vergessen, dass ich mit Administratorrechten angemeldet war. Sobald ich versuchte, die Prozedur mit dem Hauptbenutzer meiner Anwendung auszuführen, fand ich in der Abfrage eine Tabelle, auf die der Benutzer nicht zugreifen konnte.

2
Chris Matthews

Stellen Sie außerdem sicher, dass Ihre gespeicherte Prozedur tatsächlich funktioniert, indem Sie sie zuerst in SSMS ausführen. Ich hatte einige gespeicherte Prozeduren importiert und einige abhängige Skalarfunktionen vergessen, sodass EF feststellen konnte, dass die Prozedur keine Spalten zurückgab. Scheint ein Fehler zu sein, den ich früher hätte fangen sollen, aber EF gibt Ihnen in diesem Fall keine Fehlermeldung.

1
Derreck Dean

Was ich hinzufügen würde ist:

Dass der Import auch fehlschlägt, wenn die gespeicherten Prozeduren über Parameter verfügen und keine Ergebnismenge für die Standardparameterwerte zurückgibt.

Meine gespeicherte Prozedur hatte 2 Float-Parameter und würde nichts zurückgeben, wenn beide Parameter 0 sind.

Um diese gespeicherte Prozedur zum Entitätsmodell hinzuzufügen, habe ich den Wert dieser Parameter in der gespeicherten Prozedur so festgelegt, dass garantiert einige Zeilen zurückgegeben werden, unabhängig von den Parametern.

Nachdem ich diese gespeicherte Prozedur zum Entitätsmodell hinzugefügt hatte, machte ich die Änderungen rückgängig.

1
tmanthey

beide Lösungen: 1- Definieren Sie den zurückgegebenen komplexen Typ manuell (ich denke, es sollte funktionieren) Verwenden Sie einen Hack und fügen Sie einfach die gespeicherte Prozedur an den Anfang von SET FMTONLY OFF.

funktionierte nicht mit mir, aber es funktionierte mit anderen!

meine Prozedur endet mit dieser Zeile: 

SELECT machineId, production [AProduction]
        , (select production FROM #ShiftBFinalProd WHERE machineId = #ShiftAFinalProd.machineId) [BProduction]
        , (select production FROM #ShiftCFinalProd WHERE machineId = #ShiftAFinalProd.machineId) [CProduction]
     FROM #ShiftAFinalProd
     ORDER BY machineId

Vielen Dank

1
Ahmed Mostafa

Interessante Randnotiz: Hatte dasselbe Problem, das ich zuerst mit Tabellenvariablen gelöst habe, anstatt mit Temp-Tabellen (nur für den Import). Das war für mich nicht besonders intuitiv und warf mich ab, als ich anfangs meine beiden SProcs beobachtete: einen mit Temp-Tabellen und einen mit Tabellenvariablen. 

(SET FMTONLY OFF hat für mich nie funktioniert, also habe ich meine SProcs vorübergehend geändert, um die Spalteninformationen zu erhalten, anstatt mich mit dem Hack auf der EF-Seite wie einer FYI zu beschäftigen.)

Meine beste Option war wirklich, den komplexen Typ manuell zu erstellen und ihm den Funktionsimport zuzuordnen. Funktionierte hervorragend, und der einzige Unterschied bestand darin, dass eine zusätzliche FactoryMethod zum Erstellen der Eigenschaften im Designer enthalten war. 

1
user1076406
SET FMTONLY OFF 

arbeitete für mich für eine der Verfahren, aber für andere Verfahren fehlgeschlagen. Die folgenden Schritte helfen mir, mein Problem zu lösen

  1. In einer gespeicherten Prozedur habe ich eine temporäre Tabelle mit demselben Spaltentyp erstellt und alle von der dynamischen Abfrage zurückgegebenen Daten in die temporäre Tabelle . Eingefügt und die temporären Tabellendaten ausgewählt. 

    Create table #temp
    (
       -- columns with same types as dynamic query    
    )
    
    EXEC sp_executeSQL @sql 
    
    insert into #temp 
        Select * from #temp 
    
    drop table #temp
    
  2. Vorhandener komplexer Typ, Importfunktion und gespeicherte Prozedurinstanz für alte gespeicherte Prozedur und aktualisiertes Entitätsmodell für aktuelle neue Prozedur gelöscht.

  3. Wenn Sie die importierte Funktion im Entity-Modal für den gewünschten komplexen Typ bearbeiten, erhalten Sie dort alle Spalteninformationen, die für die vorherige gespeicherte Prozedur nicht abgerufen werden.

  4. sobald Sie mit der Typerstellung fertig sind, können Sie die temporäre Tabelle aus der gespeicherten Prozedur löschen und anschließend Entity Framework aktualisieren.

0
PVIJAY

In Entity Framework führt sql beim Abrufen von Spalteninformationen die Prozedur mit der Übergabe von Nullwerten im Parameter aus. Ich habe also mit Null unterschiedlich umgegangen, indem ich eine temporäre Tabelle mit allen erforderlichen Spalten erstellt und alle Spalten ohne Wert zurückgegeben habe, wenn Null an die Prozedur übergeben wird.

In meiner Prozedur gab es eine dynamische Abfrage, so etwas

declare @category_id    int
set @category_id = (SELECT CATEGORY_ID FROM CORE_USER where USER_ID = @USER_ID)
declare @tableName varchar(15)
declare @sql VARCHAR(max)     
declare  @USER_IDT  varchar(100)    
declare @SESSION_IDT  varchar(10)

 IF (@category_id = 3)     
set @tableName =  'STUD_STUDENT'
else if(@category_id = 4)
set @tableName = 'STUD_GUARDIAN'


if isnull(@tableName,'')<>'' 
begin

set @sql  = 'SELECT  [USER_ID], [FIRST_NAME], SCHOOL_NAME, SOCIETY_NAME, SCHOOL_ID,
SESSION_ID, [START_DATE], [END_DATE]
from  @tableName
....
EXECUTE   (@sql)
END

ELSE
BEGIN
SELECT  * from #UserPrfTemp
END

Ich habe die Spalteninformationen nicht in .__ erhalten. Mein Fall nach dem Set FMTONLY OFF Trick.

Dies ist eine temporäre Tabelle, die ich erstellt habe, um die leeren Daten zu erhalten ... Jetzt bekomme ich die Spalteninformationen

Create table #UserPrfTemp
(
[USER_ID] bigint, 
[FIRST_NAME] nvarchar(60),
SCHOOL_NAME nvarchar(60),
SOCIETY_NAME nvarchar(200)
.....
}
0
Rajdeep

Entity Framework versucht, die Spalten abzurufen, indem Sie Ihre gespeicherte Prozedur ausführen und NULL für jedes Argument übergeben. 

  1. Stellen Sie sicher, dass die gespeicherte Prozedur unter allen Umständen etwas zurückgibt. Beachten Sie, dass es für Entity Framework möglicherweise intelligenter war, die gespeicherte Prozedur mit Standardwerten für die Argumente im Gegensatz zu NULLs auszuführen.

  2. ER führt folgende Schritte aus, um die Metadaten der Tabelle abzurufen:

    FMTONLY EINSTELLEN

  3. Dies unterbricht Ihre gespeicherte Prozedur unter verschiedenen Umständen, insbesondere wenn eine temporäre Tabelle verwendet wird.

  4. Um ein Ergebnis als komplexen Typ zu erhalten; Bitte versuchen Sie es durch Hinzufügen

    FMTONLY OFF einstellen;

Das hat für mich funktioniert - hoffe es funktioniert auch für Sie.

Empfohlen von https://social.msdn.Microsoft.com/Forums/de/e7f598a2-6827-4b27-a09d-aefe733b48e6/entity-model-add-function-import-stored-preturn-returns- Spalten? Forum = Adodotnetentityframework

0
Kiran Nandan

In meinem Fall hat SET FMTONLY OFF nicht funktioniert. Die Methode, der ich folgte, ist, ich habe die Sicherung der ursprünglichen gespeicherten Prozedur genommen und nur mit dem Spaltennamen wie der folgenden Abfrage ersetzt.

Select Convert(max,'') as Id,Convert(max,'') as Name

Erstellen Sie nach dieser Änderung eine neue Funktion importieren, komplexer Typ in Entity Framework ..__ Wenn die Funktion import und komplexer Typ erstellt wurde, ersetzen Sie die obige Abfrage durch Ihre ursprüngliche gespeicherte Prozedur.

0
Darshan Jadyal

In meinem Fall wurde das Problem durch das Hinzufügen von SET NOCOUNT ON; am Anfang des Verfahrens behoben. Es ist sowieso die beste Praxis.

0
Endrju