Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/292.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 我的SqlCommand变量是否工作过度?它累了吗?_C#_.net 3.5_Sqlcommand - Fatal编程技术网

C# 我的SqlCommand变量是否工作过度?它累了吗?

C# 我的SqlCommand变量是否工作过度?它累了吗?,c#,.net-3.5,sqlcommand,C#,.net 3.5,Sqlcommand,在我的测试项目中,我有一个名为FixtureSetup的静态类,用于设置集成测试数据以进行验证 我在该类中使用相同的SqlCommand和SqlParameter变量(而不是对象本身),反复使用相同的变量引用,每次都分配新的SqlCommand和SqlParameter对象。我的连接本身只创建一次,并传递到执行设置的方法中,因此每个设置都使用它自己的不同连接引用,虽然同一个连接被多次使用,但它始终是线性序列 在一个这样的方法中,我遇到了一个非常奇怪的情况,我的SqlCommand变量似乎已经厌倦

在我的测试项目中,我有一个名为FixtureSetup的静态类,用于设置集成测试数据以进行验证

我在该类中使用相同的SqlCommand和SqlParameter变量(而不是对象本身),反复使用相同的变量引用,每次都分配新的SqlCommand和SqlParameter对象。我的连接本身只创建一次,并传递到执行设置的方法中,因此每个设置都使用它自己的不同连接引用,虽然同一个连接被多次使用,但它始终是线性序列

在一个这样的方法中,我遇到了一个非常奇怪的情况,我的SqlCommand变量似乎已经厌倦了

        cmd = new SqlCommand("INSERT INTO Subscription (User_ID, Name, Active) VALUES (@User_ID, @Name, @Active)", conn);
        parameter = new SqlParameter("@User_ID", TestUserID); cmd.Parameters.Add(parameter);
        parameter = new SqlParameter("@Name", "TestSubscription"); cmd.Parameters.Add(parameter);
        parameter = new SqlParameter("@Active", true); cmd.Parameters.Add(parameter);
        cmd.ExecuteNonQuery();

        cmd = new SqlCommand("SELECT Subscription_ID FROM [Subscription] WHERE Name = 'TestSubscription'", conn);
        parameter = new SqlParameter("@User_ID", TestUserID);
        cmd.Parameters.Add(parameter);
        using (dr = cmd.ExecuteReader())
        {
            while (dr.Read())
            {
                TestSubscriptionID = dr.GetInt32(dr.GetOrdinal("Subscription_ID"));
            }
        }

        cmd = new SqlCommand("INSERT INTO SubscriptionCompany (Subscription_ID, Company_ID) VALUES (@Subscription_ID, @Company_ID)", conn);
        parameter = new SqlParameter("@Subscription_ID", TestSubscriptionID); cmd.Parameters.Add(parameter);
        parameter = new SqlParameter("@Company_ID", KnownCompanyId); cmd.Parameters.Add(parameter);
        cmd.ExecuteNonQuery();
在上面显示的最后一行,我在其他几十个地方做了同样的事情(插入数据、读取ID列并捕获它),我得到了以下结果:

安装程序:System.InvalidOperationException:ExecuteOnQuery需要 打开可用的连接。连接的当前状态为 关闭在 System.Data.SqlClient.SqlConnection.GetOpenConnection(字符串方法)

但是-用新变量myCmd替换cmd,一切都很顺利

        SqlCommand myCmd;
        myCmd = new SqlCommand("INSERT INTO Subscription (User_ID, Name, Active) VALUES (@User_ID, @Name, @Active)", conn);
        parameter = new SqlParameter("@User_ID", TestUserID); myCmd.Parameters.Add(parameter);
        parameter = new SqlParameter("@Name", "TestSubscription"); myCmd.Parameters.Add(parameter);
        parameter = new SqlParameter("@Active", true); myCmd.Parameters.Add(parameter);
        myCmd.ExecuteNonQuery();

        myCmd = new SqlCommand("SELECT Subscription_ID FROM [Subscription] WHERE Name = 'TestSubscription'", conn);
        parameter = new SqlParameter("@User_ID", TestUserID);
        myCmd.Parameters.Add(parameter);
        using (dr = myCmd.ExecuteReader())
        {
            while (dr.Read())
            {
                TestSubscriptionID = dr.GetInt32(dr.GetOrdinal("Subscription_ID"));
            }
        }

        myCmd = new SqlCommand("INSERT INTO SubscriptionCompany (Subscription_ID, Company_ID) VALUES (@Subscription_ID, @Company_ID)", conn);
        parameter = new SqlParameter("@Subscription_ID", TestSubscriptionID); myCmd.Parameters.Add(parameter);
        parameter = new SqlParameter("@Company_ID", KnownCompanyId); myCmd.Parameters.Add(parameter);
        myCmd.ExecuteNonQuery();
这到底是怎么回事?我的命令只是累了吗

我在跟踪中注意到,在我的“读取id”块中,cmd.Parameters块中只有一个参数,添加了第二个参数,当我强制再次执行第一个cmd.Parameters.Add行时,列表中的参数数降为0。这就是促使我尝试方法级SqlCommand的原因…因为我有一个疯狂的想法,我的cmd太累了。。。想象一下,当我显然是对的时候,我的震惊


编辑:这里我没有循环使用任何对象——只是变量引用本身(类级别的静态SqlCommand)。很抱歉,我之前对这个问题的措辞有点混乱。

每个查询使用一个命令,然后调用dispose(或者更好的是,用using语句包装)。您不想“重用”ado.net组件。

大编辑:

发件人:

使用完后,必须显式调用Close方法 SqlDataReader将关联的SqlConnection用于任何其他 目的

Close方法填充输出参数的值,return 值和记录受影响,增加了关闭所需的时间 用于处理大型或复杂查询的SqlDataReader。 当返回值和受查询影响的记录数 不重要,关闭SqlDataReader所需的时间 可以通过调用关联的 在调用Close方法之前,先调用SqlCommand对象

因此,请尝试:

using (dr = cmd.ExecuteReader())
{
    while (dr.Read())
    {
        TestSubscriptionID = dr.GetInt32(dr.GetOrdinal("Subscription_ID"));
    }
    dr.Close();
}

检查您是否未将
DataReader
设置为,因为您提到您正在使用连接进行测试初始化


另外,
DataReader
确实占用了资源,因此利用Dispose

每次尝试后是否确实需要创建一个新的连接对象

myCmd = new SqlCommand(...)
//your code
myCmd = new SqlCommand(...)
//etc
你可以说:

myCmd.CommandText = "INSERT INTO SubscriptionCompany (Subscription_ID, Company_ID) VALUES (@Subscription_ID, @Company_ID)";
以便可以重复使用命令对象。此外,您还可以在每次调用后重置参数。只需调用
myCmd.Parameters.Clear()

另外,请确保使用语句将
SqlCommand
包装在
中,以便正确清理它们

using (SqlCommand cmd = new SqlCommand())
{
    cmd.CommandText = "some proc"
    cmd.Connection = conn;
    //set params, get data, etc
    cmd.CommandText = "another proc"
    cmd.Parameters.Clear();
    //set params, get date, etc.
}


是的,我自己也注意到了。正在修复。@marc_s:它们只是缩小了尺寸。做一个“查看图像”右键点击它们,它们是可读的。为时已晚-已经被代码片段替换。没有一天不在这里发布我最近的答案:(问题:“ExecuteReader需要一个开放的可用连接。连接的当前状态是连接”)@TimSchmelter+1对于这个答案,为什么不?cmd只不过是一个静态变量引用。在每一次“重用”中,我都明确地声明:cmd=new-SqlCommand——我在同一个类中的几十次重用中也使用了它。问题不在于命令,而在于连接。阅读错误信息(和我的答案)。我确实阅读了你的答案,也确实阅读了错误。我还检查了出现问题时的错误和连接。连接报告自己处于有效、打开状态,并且从使用静态cmd更改为使用相同连接的方法local myCmd修复了问题,因此我仍然不知道连接是如何造成问题的?我正在传递连接。我正在回收的是SqlCommand对象引用。我不明白你的答案是什么…啊哈!现在,这种联系有助于明确问题。我想我对测试项目中的ADO对象懒惰是对的。不。。。它仍然没有点击——因为正如Paul在问题的评论中指出的那样,我只是重用变量,而不是对象本身。这是一个很好的观点。我认为将SqlDataReader放在使用块中会自动关闭读卡器是错误的吗?它会自动处理读卡器,我本以为它也会关闭读卡器,但根据文档,情况似乎并非如此!嗯,是的,我可以这样做,但这并不能真正回答为什么正在反复重置的现有SqlCommand cmd变量在几十次成功使用后停止工作。@Theevillebo:尝试一下,看看它是否仍然存在。没有必要,我已经证明我已经让它工作了。问题不是“我如何修复它?”而是“为什么它不能按原样工作?”它通常会导致连接出现问题。为了回应其他人在这里所说的话,请确保在SqlConnection块的范围内完成所有工作。只要连接是打开的,您就可以让ADO.NET来完成它的工作。让我澄清一下,我上面所说的“重复使用”是指当您使用
处理连接时,ADO.NET不一定关闭