2011-05-13 52 views
22

我有以下存儲過程,當我嘗試導入函數時,它表示我的存儲過程不返回任何列。我錯過了什麼?有什麼建議麼?爲什麼Entity Framework不能查看我的存儲過程的列信息?

的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 
+2

可能重複[實體框架無法處理一個簡單的表變量?](http://stackoverflow.com/questions/5997033/entity-framework-cant-handle-a-simple-table-variable) – 2011-05-13 20:10:45

+4

是的,這正是問題。我將SET FMTONLY OFF添加到存儲過程的頂部,並找到了列。謝謝。 – RodneyRoadRunner 2011-05-13 20:43:01

回答

30

請告訴我這裏發生的幕後?

  1. 雖然做函數導入 - >獲取列信息... Visual Studio中執行與(通過MS SQL事件探查器還可以進行交叉檢查)的所有PARAM值NULL的存儲過程。

  2. 執行步驟1時,存儲的proc的結果列將返回其數據類型和長度信息。

  3. 獲取列信息後,單擊「創建新複雜類型」按鈕將創建爭用中SP的複雜類型。

在你的情況下,存儲的proc params不能爲空,因此Visual Studio調用失敗並且不返回任何列。

如何處理?

 
IF (1=0) 
BEGIN 
    SET FMTONLY OFF 
    if @param1 is null and @param2 is null then 
     begin 
      select 
      cast(null as varchar(10)) as Column1, 
      cast(null as bit) as Column2, 
      cast(null as decimal) as Column3 
     END 
END 

爲了準確(你的情況):

 
IF (1=0) 
BEGIN 
    SET FMTONLY OFF 
    if @SearchString is null then 
     BEGIN 
      select 
      cast(null as int) as ID, 
      cast(null as varchar(255)) as VendorName, 
      cast(null as varchar(255)) as ItemName, 
      cast(null as varchar(2)) as Type 
     END 
END 

參考:http://mysoftwarenotes.wordpress.com/2011/11/04/entity-framework-4-%E2%80%93-the-selected-stored-procedure-returns-no-columns-part-2/

+0

不錯,謝謝!!! ...... – levi 2013-03-26 19:17:46

+0

謝謝你的提示!一個問題:爲什麼你需要'如果@SearchString爲空然後'?如果我理解正確,你只需在開始時使用'IF(1 = 0)'來防止執行(總是爲false)並允許列掃描。在我的情況下,它沒有null檢查工作。 – Matt 2014-08-28 15:22:13

+0

使用NULL參數執行的存儲過程的信息是黃金!當使用VS將應用程序移植到新環境時,我有一個缺失的表,導致存儲過程在EF試圖調用它來獲取列值來構建複雜類型時失敗。你的回答讓我下降到SSMS中的一個新的查詢窗口,並用空輸入參數執行存儲的proc,重複EF做的帽子,從而發現EF無聲無息地吞嚥我的愚蠢錯誤。 – markaaronky 2016-11-07 14:30:12

1

作爲一個快速和骯髒的方式,使EF找到列,註釋掉在where子句中的存儲過程(可能會添加一個TOP 1以阻止它返回所有內容),將該proc添加到EF並創建複雜類型,然後再次取消註釋where子句。

41

嘗試加入這行來存儲過程的開頭:

SET FMTONLY OFF 

您已完成導入後,您可以刪除此。

+0

不適用於EF 5,雖然它應該是 – 2015-03-13 06:17:12

2

你有這個問題,由於臨時表。 所有你需要做的是: 1.改變你的存儲過程,返回沒有臨時表的select語句。 2.轉到函數導入並獲取列信息。 3.將存儲過程更改回原始狀態。

1

我想向Sudhanshu Singh的回答添加一些內容:它工作得很好,但如果您有更復雜的結構,請將其與表格聲明結合使用。

我已經使用了成功地追蹤(將其放置在你的存儲procecure的開始):

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 

注意1=0保證它永遠不會被執行,但EF從扣除結構它。

保存存儲過程後,在Visual Studio中打開EDMX文件,刷新數據模型,轉到實體框架模型瀏覽器。在模型瀏覽器中,找到您的存儲過程,打開「編輯功能導入」對話框,選擇「返回...複雜的集合」,然後單擊「獲取列信息」按鈕。

它應該顯示出上面定義的結構。如果確實如此,則點擊「創建新複合體類型」,並且它將創建一個帶有存儲過程名稱的例如「MyStoredProc_Result」(附加「_Result」)。

現在,您可以在同一個對話框的「返回...複雜集合」的組合框中選擇它。

每當您需要更新某些內容時,首先更新SP,然後您可以回到編輯功能導入對話框並單擊「更新」按鈕(您不需要重新創建所有內容)。

1

如果您使用臨時表,實體(EDMX)不能理解正在發生的事情。

所以用列名返回空結果,註釋掉所有存儲過程並在sql manager中執行,然後在visual studio中獲得複雜類型。保存後,將存儲過程返回到原始狀態(未註釋)。

好運/

0

我有這個問題,我所要做的就是創建一個用戶定義的表類型並返回。

CREATE TYPE T1 AS TABLE 
( ID  INT, 
    VendorName VARCHAR(255), 
    ItemName  VARCHAR(255), 
    Type  VARCHAR(2), 
    Sequence  TINYINT 
); 
GO 

存儲過程會是這個樣子的:

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 
0

只需添加SELECT語句不帶,執行存儲過程,去獲得更新模型,編輯功能導入並獲得列信息。這應該填充新的列。更新結果集並返回到您存儲的proc並刪除剛剛添加的選擇列表。並執行存儲的過程。這樣您的列將填充到結果集中。 請參閱下面的內容添加無引號的選擇列表。

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,VENDORNAME,ITEMNAME,鍵入#T

我希望這有助於有人在那裏。

5

的完整性和製作簡單@benshabatnoam的答案,只要把下面的代碼在開始時:

IF (1=2) 
    SET FMTONLY OFF 

注:它在EF 6.1.3和Visual Studio 2015年更新3

+1

Thx,man。你爲我節省了很多時間;) – DespeiL 2016-12-21 16:15:17

相關問題