2011-05-02 77 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(); 
     } 
}