2015-08-21 108 views
30

我試圖從數據庫上下文對象調用的動態SQL存儲過程(使用實體框架6.1.1)獲取內容表,以便填充GridView控件。我無法檢索數據。使用實體框架從存儲過程獲取數據

這是存儲過程。這是一個關於存儲過程中的SQL注入的學生演示,所以我知道這是可注射的,它很好。

ALTER PROCEDURE dbo.SearchProducts 
    @SearchTerm VARCHAR(max) 
AS 
BEGIN 
    DECLARE @query VARCHAR(max) 
    SET @query = 'SELECT * FROM dbo.Products WHERE Name LIKE ''%' + @SearchTerm + '%''' 
    EXEC(@query) 
END 

的C#代碼後面我然後用它來執行存儲過程是:

var db = new MyEntities(); 
var TEST_SEARCH_TERM = "product"; 
var result = db.SearchProducts(TEST_SEARCH_TERM); 

MyGridView.DataSource = result; 
MyGridView.DataBind(); 

執行時,在Visual Studio中的數據庫資源管理器,存儲過程工作正常。但是當在正在運行的ASP.NET應用程序中執行時,由於result返回-1而不是包含存儲過程的SELECT產生的對象的IEnumerableDataSet,所以我在DataBind()方法中出現異常。

如何檢索數據並填充我的GridView

+0

在您的edmx中,轉到功能導入 - > SearchProducts,然後雙擊它。什麼是返回類型設置爲? – Vahlkron

+0

返回類型未設置。這是(無)。 – mak

+0

聽起來像它需要設置爲複雜。我可能會提出的唯一建議是,因爲我沒有EF,所以當我這樣做時,會給我提出問題,請將*改爲明確地在SP中選擇所需的列。也許EF看着這個來確定你的返回類型。然後更新您的EDMX,以便更改反映在EF中。 – Vahlkron

回答

27

使用以下步驟來解決這個問題:

  1. 需要導入存儲過程的功能。右鍵單擊實體模型的工作空間區域,然後選擇Add -> Function Import
  2. 在添加功能導入對話框中,輸入您希望您的存儲過程來在你的模型被稱爲例如Search_Products,從下拉列表中選擇你的程序,並選擇程序的返回值是Entities的名稱和從下拉列表中選擇Products
  3. 然後在後面的代碼:

    var db = new MyEntities(); 
    var TEST_SEARCH_TERM = "product"; 
    var result = db.Search_Products(TEST_SEARCH_TERM);//Search_Products is the name that you specified in Function Import dialog 
    
    MyGridView.DataSource = result; 
    MyGridView.DataBind(); 
    

你得到-1的結果的原因是,實體框架不能支持存儲過程返回值的開箱。我認爲存儲過程返回值的支持取決於實體框架的版本。此外,實體框架沒有豐富的存儲過程支持,因爲它是一個ORM,而不是SQL替代品。

+4

所有代碼語言的母親。我不知道爲什麼現在可以工作。我希望這保持穩定。感謝x1000老兄。 +100的聲望當之無愧。 – mak

0

確認您的EDMX具有返回類型: 轉到功能導入 - > SearchProducts,並雙擊它。

爲了使用複雜返回類型,實體框架將要求您在存儲過程中明確定義列名,而不是使用*。

一旦您的存儲過程被修改爲定義列名稱,您可以在項目中更新模型。 (請注意,執行SP的一個完整的下降,然後將其添加回你的EDMX可能是最好的途徑。)

編輯

也許你可以修改你的SP類似如下:

ALTER PROCEDURE dbo.SearchProducts 
    @SearchTerm VARCHAR(max) 
AS 
BEGIN 
    SELECT * FROM dbo.Products WHERE Name LIKE '%' + @SearchTerm + '%' 
END 
+0

當試圖向模型中的此存儲過程添加複雜類型時,模型瀏覽器不允許您添加它,因爲「選定的存儲過程不會返回任何列」 – mak

+0

您可以像上面那樣修改它,或者您有有@query?....除了你應該專門聲明你的列。 – Vahlkron

+0

所以...通過將返回類型定義爲「產品」類型的實體來實現它。現在我想要的是返回類型是一個複雜的類型,而不是一個實體。伊瑪試試你的建議。 無論如何,你的解決方案幫助,我會在我最後一次嘗試後接受。 – mak

3

我之前遇到過使用動態SQL的存儲過程。如果我添加'SET FMTONLY OFF'行,我已經成功地使用了複雜類型;' (請參閱https://msdn.microsoft.com/en-us/library/ms173839.aspx)將其添加到EF模型之前存儲過程的頂部。一旦你有你的複雜類型的模型設置,一定要刪除這一行。

例子:

ALTER PROCEDURE dbo.SearchProducts 
    @SearchTerm VARCHAR(max) 
AS 
BEGIN 
    SET FMTONLY OFF; 
    DECLARE @query VARCHAR(max) 
    SET @query = 'SELECT * FROM dbo.Products WHERE Name LIKE ''%' + @SearchTerm + '%''' 
    EXEC(@query) 
END 
+0

是的,試過了,沒有幫助我。 但我發現它很有趣,因爲它讓我明白了EF的內部運作以及它如何獲得元數據來構建結果集。 – mak