2010-11-24 151 views

回答

25

ExecuteNonQuery Method返回受INSERT,UPDATEDELETE影響的行數。如前所述,此方法將用於執行DML(數據操作語言)語句。

ExecuteReader Method將返回SELECT的結果集。這個方法用於查詢一堆結果,比如表,視圖等等。

ExecuteScalar Method將在SELECT語句的第一行第一列中返回單個值。如果您希望僅返回查詢中的一個值,則使用此方法。

總之,在使用ExecuteNonQuery方法時,您沒有SELECT聲明的結果是正常的。改爲使用ExecuteReader。使用ExecuteReader方法,將會知道通過返回的SqlDataReader對象的實例返回了多少行。

int rows = 0; 

if (reader.HasRows) 
    while (reader.Read()) 
     rows++; 

return rows; // Returns the number of rows read from the reader. 
6

我沒有看到任何方式來做到這一點。使用ExecuteScalarselect count(*) where ...來計算符合原始SELECT查詢條件的行。下面的例子,從here轉述:

using (SqlCommand thisCommand = 
    new SqlCommand("SELECT COUNT(*) FROM Employee", thisConnection)) 
{ 
    Console.WriteLine("Number of Employees is: {0}", 
     thisCommand.ExecuteScalar()); 
} 

如果需要行也,你已經使用了ExecuteReader,我想象。

+0

我無法更改其動態構建的sql查詢 – Lyle 2010-11-26 15:50:28

3

改爲使用ExecuteReader方法。這將返回一個SqlDataReader,它有一個HasRows屬性。

ExecuteNonQuery不應該用於SELECT聲明。

1

現在已經很晚了,但最近我遇到了這個問題,並認爲這對後來的其他人(如我)尋求相同問題的幫助會有所幫助。無論如何,我相信你實際上可以使用你正在嘗試的方式使用ExecuteNonQuery。但是...你必須調整你的底層SELECT查詢到一個存儲過程,而不是SELECT查詢和一個設置爲等於行數的輸出參數。

作爲MSDN文檔中所述:

雖然爲ExecuteNonQuery返回任何行,任何輸出參數或返回映射到參數的值被填充數據。

鑑於此,我是這麼做的。順便說一句,如果這裏有任何缺陷,我都會喜歡那裏的專家的反饋,但它似乎適用於我。

首先,你的存儲過程應該有兩個SELECT語句:一個來回報您的數據集和其他依賴於輸出參數返回的記錄數:

CREATE PROCEDURE spMyStoredProcedure 
(
    @TotalRows int output 
) 
AS 
BEGIN 
    SELECT * FROM MyTable; //see extra note about this line below. 
    SELECT @TotalRows COUNT(*) FROM MyTable; 
END 

其次,添加以下代碼(在VB。淨,使用SqlCommand等..)。

Dim cn As SqlConnection, cm As SqlCommand, dr As SqlDataReader 
Dim myCount As Int32 

cn = New SqlConnection("MyConnectionString") 
cn.Open() //I open my connection beforehand, but a lot of people open it right before executing the queries. Not sure if it matters. 

cm = New SqlCommand("spMyStoredProcedure", cn) 
cm.CommandType = CommandType.StoredProcedure 
cm.Parameters.Add("@TotalRows", SqlDbType.Int).Direction = ParameterDirection.Output 
cm.ExecuteNonQuery() 

myCount = CType(cm.Parameters("@TotalRows").Value, Integer) 
If myCount > 0 Then 
    //Do something. 
End If 

dr = cm.ExecuteReader() 
If dr.HasRows Then 
    //Return the actual query results using the stored procedure's 1st SELECT statement 
End If 
dr.Close() 
cn.Close() 
dr = Nothing 
cm = Nothing 
cn = Nothing 

就是這樣。

額外的說明。我認爲你可能希望獲得「MyCount」金額來做一些事情,而不是確定是否繼續返回查詢。原因是因爲用這種方法,你並不需要那麼做。由於在獲取計數後我正在使用「ExecuteReader」方法,因此可以使用數據閱讀器的「HasRows」屬性確定是否繼續返回預期的數據集。然而,要返回一個數據集,你需要一個返回一個數據集的SELECT語句,這也是我的存儲過程中第一個SELECT語句的原因。

順便說一句,有關使用「的ExecuteNonQuery」方法,這個方法的很酷的事情是,你可以關閉DataReader的,之前用它來獲得總行之前數關閉DataReader的(你不能讀取輸出參數,正是我想要做的,這種方法解決了這個問題)。我不確定在解決這個問題時是否存在性能問題或缺陷,但正如我所說的......它對我有用。 = D

+0

是的,由於在`SqlCommand`中執行了兩次SQL,性能受到了影響。如果有DML語句,它們將執行兩次。另外,在執行SqlCommand之前,確實沒有理由打開連接;這只是意味着你要保持連接打開時間更長。你可以將它移動到參數聲明之後。並且通過最後一個「End If」的Connection.Open()應該位於Try/Catch中,以便在發生異常時可以在Finally塊中正確關閉Reader和Connection。 – 2015-01-22 20:47:35