2016-01-20 54 views
0

我有一個存儲過程,用於選擇並返回一個年份列表。在sql服務器我這樣稱呼它:在c上檢索存儲過程的結果#

DECLARE @return_value int 

EXEC @return_value = [dbo].[TestName] 
     @del= 0 

SELECT 'Return Value' = @return_value 

爲了接收列表。

我的SP是這樣的:

USE [TestTable] 
GO 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 

ALTER PROCEDURE [dbo].[TestName] (@delvarchar(7)) 

AS 
BEGIN 

        SELECT YEAR( [added]) AS year FROM [MyTable] 


        GROUP BY YEAR( [added]) 
        ORDER BY YEAR( [added]) DESC 

END 

我想要做的從C#一樣,雖然並以列表值傳遞。

我試圖爲:

using (var conn = new SqlConnection(constr)) 
using (var command = new SqlCommand("TestName", conn) 
{ 
    CommandType = CommandType.StoredProcedure 
}) 
{ 
    command.Parameters.AddWithValue("@del", del); 
    SqlParameter retval = command.Parameters.Add("@return_value", SqlDbType.VarChar); 
    retval.Direction = ParameterDirection.ReturnValue; 
    conn.Open(); 
    command.ExecuteNonQuery(); 
    int retunvalue = (int)command.Parameters["@return_value"].Value; 
    conn.Close(); 

    return retunvalue; 
} 

,這並不會返回任何值,而是它只返回0。我在做什麼錯了,我怎麼能得到指定的變量內的列表?

編輯下面約翰漢娜的通知代碼,我有這樣的事情:

 public List<string> getYears(string constr, int del) 
     { 
      using (var conn = new SqlConnection(constr)) 
      using (var command = new SqlCommand("TestName", conn) 
      { 
       CommandType = CommandType.StoredProcedure 
      }) 
      { 
       command.Parameters.AddWithValue("@del", del); 
       List<string> retunvalue = new List<string>(); 
       conn.Open(); 

       SqlDataReader reader; 
       reader = command.ExecuteReader(); 
       conn.Close(); 

       return retunvalue; 
      } 
     } 

並通過以探討reader添加一個斷點我看到它是隻包含錯誤:

Depth = '(reader).Depth' threw an exception of type 'System.InvalidOperationException'

至於克里希納的回答,dtList是空的,計數爲0,我不知道如何實施Badhon的建議。

+0

C#代碼看起來是正確的讀取返回值。您應該發佈SP以及問題可能在那裏(例如,您可能使用SELECT而不是RETURN返回值)。 –

回答

3

ExecuteNonQuery()之所以這樣稱呼是因爲它用於某些沒有查詢的數據。您得到的0是命令更改的行數。

改爲使用ExecuteReader(),您將收回SqlDataReader對象,您可以調用Read()來遍歷行,然後檢查每個對象的詳細信息。

如果要返回到另一種方法使用ExecuteReader(CommandBehavior.CloseConnection)然後而非Close()Dispose()您完成後,Close()Dispose()讀者,並且將關閉連接,然後連接。

如果您只有一行有一列(或者由於某種原因,只關心第一行的第一列,即使存在更多),那麼ExecuteScalar()是獲取該單一值的便捷方式。

+0

嗨,喬恩,我編輯了我的問題,包括通過嘗試你的建議得到了什麼。 – dearn44

+0

我的建議也包括調用'Read()'。繼續調用'Read()'直到它返回false。每次調用返回true後,獲取該行的值。 –

+0

的確,我應該更加小心。 – dearn44

0

你不應該使用的ExecuteNonQuery,而使用ExecuteDataSet如下:

public List<DSM_DocPropIdentify> GetDocPropIdentify(string docPropIdentifyID, string action, out string errorNumber) 
    { 
     errorNumber = string.Empty; 
     List<DSM_DocPropIdentify> docPropIdentifyList = new List<DSM_DocPropIdentify>(); 
     DatabaseProviderFactory factory = new DatabaseProviderFactory(); 
     SqlDatabase db = factory.CreateDefault() as SqlDatabase; 
     using (DbCommand dbCommandWrapper = db.GetStoredProcCommand("GetDocPropIdentify")) 
     { 
      // Set parameters 
      db.AddInParameter(dbCommandWrapper, "@DocPropIdentifyID", SqlDbType.VarChar, docPropIdentifyID); 
      db.AddOutParameter(dbCommandWrapper, spStatusParam, DbType.String, 10); 
      // Execute SP. 
      DataSet ds = db.ExecuteDataSet(dbCommandWrapper); 

      if (!db.GetParameterValue(dbCommandWrapper, spStatusParam).IsNullOrZero()) 
      { 
       // Get the error number, if error occurred. 
       errorNumber = db.GetParameterValue(dbCommandWrapper, spStatusParam).PrefixErrorCode(); 
      } 
      else 
      { 
       if (ds.Tables[0].Rows.Count > 0) 
       { 
        DataTable dt1 = ds.Tables[0]; 
        docPropIdentifyList = dt1.AsEnumerable().Select(reader => new DSM_DocPropIdentify 
        { 
         DocPropIdentifyID = reader.GetString("DocPropIdentifyID"), 
         DocPropertyID = reader.GetString("DocPropertyID"), 
         DocCategoryID = reader.GetString("DocCategoryID"), 
         DocTypeID = reader.GetString("DocTypeID"), 
         OwnerID = reader.GetString("OwnerID"), 
         IdentificationCode = reader.GetString("IdentificationCode"), 
         IdentificationSL = reader.GetString("IdentificationSL"), 
         AttributeGroup = reader.GetString("AttributeGroup"), 
         IdentificationAttribute = reader.GetString("IdentificationAttribute"), 
         IsRequired = reader.GetInt16("IsRequired"), 
         IsAuto = reader.GetInt16("IsAuto"), 
         SetOn = reader.GetString("SetOn"), 
         SetBy = reader.GetString("SetBy"), 
         ModifiedOn = reader.GetString("ModifiedOn"), 
         ModifiedBy = reader.GetString("ModifiedBy"), 
         Status = reader.GetInt32("Status"), 
         Remarks = reader.GetString("Remarks") 
        }).ToList(); 
       } 
      } 
     } 
     return docPropIdentifyList; 
    } 
0

是dbo.TestName將返回一個表或值。如果這返回給你一個表,那麼你將不得不執行DataAdapter或執行DataReader。此時應更換上述聲明 作爲

DataTable dtList=new DataTable(); 
SqlDataAdapter adapter=new SqlDataAdapter(); 
adapter.SelectCommand=command; 
adapter.Fill(dtList); 

然後你就可以通過數據表進行迭代,並添加到您的列表

List<Object> listObj=new List<Object>(); 
foreach(var rows in dtList.Rows) 
{ 
    listObj.Add(rows["Column_name"]); 
} 

我分析您的查詢,結果發現,該聲明

DECLARE @return_value int 

EXEC @return_value = [dbo].[TestName] 
     @del= 0 

SELECT 'Return Value' = @return_value 

返回多個表。您可以刪除最後一條冗餘的語句。

SELECT 'Return Value' = @return_value 

數據表現在將填充值。

讓我知道這是否有效。

+0

它返回一個包含年份的表格,而不是單個值。 – dearn44

+0

@ dearn44你能顯示你的存儲過程的功能嗎,這樣會有幫助。 –

+0

完成後,我編輯了包括我的SP在內的問題。 – dearn44