多个SQL查询 asp.net c#

9
我需要在一个函数内运行多个查询,我是否需要为每个查询创建一个新的SqlConnection?或者只有一个连接但不同的SqlCommands也可以工作吗?
谢谢,
编辑:这样会有效吗?
       using (SqlConnection conn = new SqlConnection(connectionString))
      {
        conn.Open();

        using (SqlCommand cmd = new SqlCommand(query1, conn))
        {
            cmd.ExecuteNonQuery();
        }

        using (SqlCommand cmd = new SqlCommand(query2, conn))
        {
            cmd.ExecuteNonQuery();
        }

        using (SqlCommand cmd = new SqlCommand(query3, conn))
        {
            cmd.ExecuteNonQuery();
        }

    }

最好让我们看看你的代码,这样我们才能给出更好的建议。 - Muhammad Akhtar
我看到了你的另一个问题,不要将值作为内联传递给SQL语句,这可能会导致SQL注入。 - kobe
1
如果你把所有东西都放在 using 语句块中,就不需要手动释放它们了。SqlConnection 和 SqlCommand 实现了 IDisposable 接口。因此可以移除 "conn.Close(); conn.Dispose(); cmd.Dispose();" 这行代码 :D - Jeremy
5个回答

8

MDSN文档为基础:

使用:
using (SqlConnection connection = new SqlConnection(connectionString))
{
    connection.Open();

    string sql1 = "SELECT ID,FirstName,LastName FROM VP_PERSON";
    string sql2 = "SELECT Address,City,State,Code FROM VP_ADDRESS";

    using (SqlCommand command = new SqlCommand(sql1,connection))
    {
        //Command 1
        using (SqlDataReader reader = command.ExecuteReader())
        {
            // reader.Read iteration etc
        }

    } // command is disposed.

    using (SqlCommand command = new SqlCommand(sql2,connection))
    {

        //Command 1
        using (SqlDataReader reader = command.ExecuteReader())
        {
            // reader.Read iteration etc
        }

    } // command is disposed.

   // If you don't using using on your SqlCommands you need to dispose of them 
   // by calling command.Dispose(); on the command after you're done.

} // the SqlConnection will be disposed

谢谢您的帮助,我只是想知道在 using (SqlCommand command = new...) 部分中可以放什么,只有查询执行和处理命令吗? - QPTR
将你的SqlDataReader放进去,使用它,然后处理掉它。或者更好的方法是将SqlDataReader放在using语句块中。 - Jeremy

4
无论你选择哪种方式都无所谓。 SqlConnections由操作系统池化。你可以连续打开和关闭连接数千次而不会产生任何性能或其他的惩罚。
它的工作原理是:
  1. 应用程序请求创建一个数据库连接 (var c = new SqlConnection(...))
  2. 操作系统连接池查看是否有空闲的连接。如果有,则您将获得对其的引用。如果没有,它将启动一个新的连接。
  3. 应用程序表明已经完成了连接 (c.Dispose())
  4. 操作系统会在一定的时间内保持连接的打开状态,以防止您的应用程序或其他应用程序尝试创建到相同资源的另一个连接。
  5. 如果该连接保持空闲状态直到超时期限过去,那么操作系统最终会关闭并释放该连接。
这就是为什么你第一次连接数据库时可能需要花费一秒钟才能开始处理命令。但是,如果你关闭它然后重新打开它,那么连接立即可用。更多信息可参考: http://msdn.microsoft.com/en-us/library/8xx3tyca(v=vs.110).aspx 现在,关于你的代码,一般来说,每次调用SqlCommand时都会打开一个SqlConnection;然而,在SqlConnection using子句内部进行多个SqlCommand调用是完全可接受的/合理的。
只要记住,你不希望在你的代码中保持一个SqlConnection对象的存在时间比绝对必要的时间长。这可能会导致很多潜在问题,特别是如果你正在进行Web开发。这意味着,与将该对象保存并通过各种方法传递它相比,你的代码更好地打开和关闭100个SqlConnection对象。

2

拥有一个 SqlConnection 和多个 SqlCommands 是可行的,但是在尝试运行其他命令之前,必须确保处理来自先前命令返回的任何 SqlDataReaders

using (SqlConnection conn = new SqlConnection())
{
    conn.Open()

    using (SqlCommand cmd = new SqlCommand("SELECT myrow FROM mytable", conn))
    {
        using (SqlDataReader reader = cmd.ExecuteReader())
        {
            // Handle first resultset here
        }
    }

    using (SqlCommand cmd = new SqlCommand("SELECT otherrow FROM othertable", conn))
    {
        using (SqlDataReader reader = cmd.ExecuteReader())
        {
            // Handle second resultset here
        }
    }
}

或者你可以将你的命令合并到一个批处理中,同时处理多个结果集,像这样:

using (SqlConnection conn = new SqlConnection())
{
    conn.Open()
    using (SqlCommand cmd = new SqlCommand("SELECT myrow FROM mytable; SELECT otherrow FROM othertable", conn))
    {
        using (SqlDataReader reader = cmd.ExecuteReader())
        {
            // Handle first resultset here, and then when done call
            if (reader.NextResult())
            {
                // Handle second resultset here
            }
        }
    }
}

当您处理多个结果集时,将此类查询批处理在一起可以显着提高性能,但这会增加调用代码的复杂性。

我是asp.net的新手,我们还没有介绍SqlDataReaders。目前我只使用SqlConnection,然后通过组合查询和新连接创建SqlCommand,之后使用SqlDataAdapter检索数据或ExecuteNonQuery。我应该只确保连接和命令的处理吗? - QPTR
@QPTR 我以前没有使用过 SqlDataAdapter,所以我不确定,但我认为在运行另一个查询之前,您必须处理掉一个 SqlDataAdapter。抱歉,我不确定这一点 - 但是在这个领域更有经验的人应该能够帮助您解决问题。 - Justin
@qptr,自动处理了资源释放,无需额外操作。 - kobe
好的,我会尝试把我的查询执行代码放在 using 里面,非常感谢你的帮助! - QPTR

2

仅打开一个SQLConnection

使用关键字Using,因为它会自动处理连接。

如果为每个连接打开连接,则可能会出现性能问题。

示例:

using (SqlConnection con = new SqlConnection(connectionString))
    {
        //
        // Open the SqlConnection.
        //
        con.Open();
        //
        // The following code shows how you can use an SqlCommand based on the SqlConnection.
        //
        using (SqlCommand command = new SqlCommand("SELECT TOP 2 * FROM Dogs1", con))
        using (SqlDataReader reader = command.ExecuteReader())
        {
        while (reader.Read())
        {
            Console.WriteLine("{0} {1} {2}",
            reader.GetInt32(0), reader.GetString(1), reader.GetString(2));
        }
        }
    }

再举一个例子:

public  DataTable GetData()
        {
            DataTable dt = new DataTable();
            using (SqlConnection con = new SqlConnection("your connection here")
            {
                con.Open();
                using (SqlCommand cmd = con.CreateCommand())
                {
                    cmd.CommandType = CommandType.StoredProcedure;
                    cmd.CommandText = "your stored procedure here";                    
                    using (SqlDataAdapter da = new SqlDataAdapter(cmd))
                    {
                        da.Fill(dt);
                    }
                }
            }
            return dt;
        }

我可以这样使用吗:'SqlConnection con = new SqlConnection(connectionString); con.Open();string cmdText = "query" SqlCommand cmd = new SqlCommand(cmdText, con); cmd.ExecuteNonQuery();cmd.Dispose(); con.Close(); con.Dispose();'然后创建另一个连接并重复该过程。我是asp.net的新手,不理解DataReaders的用法。 - QPTR
1
QPTR,不要创建另一个连接,这可能会影响性能。无论如何,为什么要打开另一个连接,你已经打开了一个连接到数据库,难道你想打开多个数据库吗? - kobe
@qptr,如果你需要更多帮助,请告诉我。 - kobe
@aptr,没问题。你能运行并查看数据库中的结果吗? - kobe
这个答案有些错误和误导性。数据库连接是池化的,因此你无论采用哪种方式连接都没有关系。而且打开/关闭它们也不会有任何性能损失。 - NotMe
显示剩余10条评论

0

纯粹作为使用语句的替代方案:

SqlConnection con = new SqlConnection(myConnectionString);

SqlCommand cmd = con.CreateCommand();
cmd.CommandText = @"SELECT [stuff] FROM [tableOfStuff]";

con.Open();

SqlDataReader dr = null;
try
{
    dr = cmd.ExecuteReader();

    while(dr.Read())
    {
        // Populate your business objects/data tables/whatever
    }
}
catch(SomeTypeOfException ex){ /* handle exception */ }

// Manually call Dispose()...
if(con != null) con.Dispose();
if(cmd != null) cmd.Dispose();
if(dr != null) dr.Dispose();

与使用语句的主要区别在于,这将允许您更清晰地处理异常。

谢谢回复,目前我还没有使用SqlDataReader,但是一旦完成这个任务,我会去了解它。谢谢提供示例! - QPTR
请注意,以这种方式执行脚本意味着如果出现任何错误,事情将不会像您期望的那样被处理。 - Shadow

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接