首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在同一代码中使用同一个SQLCommand实例不止一次,用于多个查询?

在同一代码中使用同一个SQLCommand实例不止一次,用于多个查询?
EN

Stack Overflow用户
提问于 2013-11-14 18:23:49
回答 3查看 1.6K关注 0票数 2

我想知道为什么不能在相同的代码中多次使用同一个SQLCommand实例?

我在这里尝试了下面的代码,它对网格视图运行良好,但是当我使用cmd.CommandText()方法更改查询时,它一直在说:

已经有一个与此命令关联的开放DataReader,必须先关闭该命令。

这是代码:

代码语言:javascript
复制
string cs = ConfigurationManager.ConnectionStrings["MyDB"].ConnectionString;
SqlConnection con = new SqlConnection(cs);

try
{
    SqlCommand cmd = new SqlCommand();
    cmd.Connection = con;
    con.Open();
    cmd.CommandText = "Select top 10 FirstName, LastName, Address, City, State from Customers";

    GridView1.DataSource = cmd.ExecuteReader(); 
    GridView1.DataBind();


    cmd.CommandText = "SELECT TOP 10 COUNT(CreditLimit) FROM Customers";
    int total = (int)cmd.ExecuteScalar();
    TotalCreditLble.Text = "The total Credit :" + total.ToString();

}
catch(Exception exp)
{
    Response.Write(exp.Message);
}
finally
{
    con.Close();
}
EN

回答 3

Stack Overflow用户

发布于 2013-11-14 18:32:01

问题是,您正在使用SqlCommand对象通过command.ExecuteReader()命令生成DataReader。虽然这是打开的,但不能重复使用该命令。

这应该是可行的:

代码语言:javascript
复制
using (var reader = cmd.ExecuteReader())
{
    GridView1.DataSource = reader;
    GridView1.DataBind();
}
//now the DataReader is closed/disposed and can re-use command
cmd.CommandText = "SELECT TOP 10 COUNT(CreditLimit) FROM Customers";
int total = (int)cmd.ExecuteScalar();
TotalCreditLble.Text = "The total Credit :" + total.ToString();
票数 5
EN

Stack Overflow用户

发布于 2013-11-14 18:32:07

已经有一个与此命令关联的开放DataReader,必须先关闭该命令。

这就是你不共享命令的原因。在您的代码中,您做了以下操作:

代码语言:javascript
复制
cmd.ExecuteReader();

但是,您没有利用using语句绕过命令,因为您想要共享它。你不能这么做。请看,当您每次读取一行时,ExecuteReader会打开到服务器的连接;但是,该命令现在被锁定,因为此时它是有状态的。正确的方法, The ,是这样的:

代码语言:javascript
复制
using (SqlConnection c = new SqlConnection(cString))
{
    using (SqlCommand cmd = new SqlCommand(sql, c))
    {
        // inside of here you can use ExecuteReader
        using (SqlDataReader rdr = cmd.ExecuteReader())
        {
            // use the reader
        }
    }
}

这些都是非管理资源,需要小心处理。这就是为什么用using包装它们是必要的。

不共享这些对象。构建它们、打开它们、使用它们并将它们释放。

通过利用using,您将不必担心关闭和释放这些对象。

你的代码,写得有点不同:

代码语言:javascript
复制
var cs = ConfigurationManager.ConnectionStrings["MyDB"].ConnectionString;
var gridSql = "Select top 10 FirstName, LastName, Address, City, State from Customers";
var cntSql = "SELECT TOP 10 COUNT(CreditLimit) FROM Customers";

using (SqlConnection con = new SqlConnection(cs))
{
    con.Open();

    try
    {
        using (SqlCommand cmd = new SqlCommand(gridSql, con))
        {
            GridView1.DataSource = cmd.ExecuteReader(); 
            GridView1.DataBind();
        }

        using (SqlCommand cmd = new SqlCommand(cntSql, con))
        {
            int total = (int)cmd.ExecuteScalar();
            TotalCreditLble.Text = "The total Credit :" + total.ToString();
        }
    }
    catch(Exception exp)
    {
        Response.Write(exp.Message);
    }
}
票数 5
EN

Stack Overflow用户

发布于 2013-11-14 20:02:00

谢谢大家,但对于那些谈论使用拦截器的人来说!为什么这个代码工作的很好,我在一个视频上看到的例子!使用相同的SqlCommand实例和通过使用CommanText方法传递不同的查询和使用相同的SqlCommand实例传递不同的查询是一样的,并且执行得很好,这是代码:

代码语言:javascript
复制
using (SqlConnection con = new SqlConnection(cs))
{
   SqlCommand cmd = new SqlCommand();
   cmd.Connection = con;
   con.Open();

   cmd.CommandText = "Delete from tbleProduct where ProductID= 4";
   int TotalRowsAffected = cmd.ExecuteNonQuery();
   Response.Write("Total rows affected :" + TotalRowsAffected );

   cmd.CommandText = "Insert into tbleProduct values (4, 'Calculator', 100, 230)";
   TotalRowsAffected = cmd.ExecuteNonQuery();
   Response.Write("Total rows affected :" + TotalRowsAffected );


   cmd.CommandText = "ypdate tbleProduct set QtyAvailbe = 234 where ProductID = 2";
   TotalRowsAffected = cmd.ExecuteNonQuery();
   Response.Write("Total rows affected :" + TotalRowsAffected );

 }
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19985385

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档