2011-05-02 76 views
2

在一些編程環境正從一個SQL查詢中的標量值很簡單:SQL查詢來標結果在C#

RowCount = Connection.Execute("SELECT Count(*) FROM TableA").Fields(0).Value 

在C#中,給予一個SqlConnection變量conn已經打開,有沒有簡單的方法做同樣的事情,而不費力地創建一個SqlCommand,一個DataReader,並且總共需要5條線才能完成這項工作?

+0

也許我會繼承SqlConnection類來爲它提供Execute和ExecuteScalar方法。 :) – ErikE 2011-05-02 19:58:36

回答

11

SqlCommand有一個ExecuteScalar方法,它可以做你想做的事情。

cmd.CommandText = "SELECT COUNT(*) FROM dbo.region"; 
Int32 count = (Int32) cmd.ExecuteScalar(); 
+0

謝謝。命令對象是否需要通過'Dispose'或''using'塊專門處理? – ErikE 2011-05-02 19:39:49

+0

是的,我相信。 SqlCommand從DbCommand獲取IDisposable。 – Joe 2011-05-02 19:41:17

+3

我給你答案獎是因爲你首先給了'ExecuteScalar',儘管包含'using'信息會很好。 – ErikE 2011-05-02 19:47:07

1

ExecuteScalar這樣可以節省至少從DataReader

static public int AddProductCategory(string newName, string connString) 
{ 
    Int32 newProdID = 0; 
    string sql = 
     "INSERT INTO Production.ProductCategory (Name) VALUES (@Name); " 
     + "SELECT CAST(scope_identity() AS int)"; 
    using (SqlConnection conn = new SqlConnection(connString)) 
    { 
     SqlCommand cmd = new SqlCommand(sql, conn); 
     cmd.Parameters.Add("@Name", SqlDbType.VarChar); 
     cmd.Parameters["@name"].Value = newName; 
     try 
     { 
      conn.Open(); 
      newProdID = (Int32)cmd.ExecuteScalar(); 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine(ex.Message); 
     } 
    } 
    return (int)newProdID; 
} 

(從this MSDN documentation article拍攝的實施例)

+1

你晚了幾秒,所以我會標記你。爲什麼在'Int32'和'int'之間切換?他們不一樣嗎?爲什麼不使用一個? – ErikE 2011-05-02 19:50:47

+0

謝謝,Erik。這是MSDN的一個例子。 Int32和int是一樣的。 – 2011-05-02 20:51:09

3

如果可以使用LINQ2SQL(或的EntityFramework)可以簡化實際詢問詢問

using (var context = new MyDbContext("connectionString")) 
{ 
    var rowCount = context.TableAs.Count(); 
} 

如果LINQ2SQL是,有大量的太比手動創建所有SqlCommands其他好處的選項等

1

調查Command.ExecuteScalar:

using(var connection = new SqlConnection(myConnectionString)) 
{ 
    connection.Open(); 
    using(var command = connection.CreateCommand()) 
    { 
     command.CommandType = CommandType.Text; 
     command.CommandText = mySql; 
     var result = (int)command.ExecuteScalar(); 
    } 
} 

如果你感覺真的很懶惰,封裝這一切在一種擴展方法,就像我們一樣。

編輯:按照要求,一個擴展方法:

public static T ExecuteScalar<T> (this SqlConnection connection, string sql) 
{ 
    if (connection == null) 
    { 
     throw new ArgumentNullException("connection"); 
    } 

    if (string.IsNullOrEmpty(sql)) 
    { 
     throw new ArgumentNullException("sql"); 
    } 

    using(var command = connection.CreateCommand()) 
    { 
     command.CommandText = sql; 
     command.CommandType = CommandType.Text; 
     return (T)command.ExecuteScalar(); 
    } 
} 

注意,這個版本假設你已經正確建立SQL提前。我可能會創建一個單獨的重載此擴展方法,它有兩個參數:存儲過程名稱和List。這樣,您可以保護自己免受不必要的SQL注入攻擊。

+0

你有沒有可以分享的擴展方法的例子? – 2011-05-02 19:40:14

1

您不需要DataReader。這個例子拉回了標量值:

Object result; 
using (SqlConnection con = new SqlConnection(ConnectionString)) { 
     con.Open(); 
     using (SqlCommand cmd = new SqlCommand(SQLStoredProcName, con)) { 
     result = cmd.ExecuteScalar(); 
     } 
}