CommandText属性未初始化。

4

我发现只有在将我的工作代码更改为使用数据视图来显示单行数据而不是文本框后,才会出现这个问题。

我有以下内容:

static SqlConnection dbConnection = new SqlConnection
                       (DBConnection.DBConnection.connectionString);        
    SqlDataAdapter holdone = new SqlDataAdapter(getCommand, dbConnection);      

    DataSet holdall = new DataSet();
    DataSet updateall = new DataSet();
    DataTable invoiceTable = new DataTable();

    DataView invoiceView = new DataView();

这是由IT技术所使用的。

public void GetOne(/* connectionString, string invref, string tableref*/)
    {

getCommand = "select *redacted* from " + tableref +  
                                      "where *redacted* = " + invref;

        using (SqlConnection dbConnection = new SqlConnection
                               (DBConnection.DBConnection.connectionString))
        {
                dbConnection.Open();

            holdone.Fill(holdall);

            invoiceTable = holdall.Tables[0];

            dbConnection.Close();


        }

        DataRowView rowView = invoiceView.AddNew();

            rowView["*redacted*"] = invoiceTable;

            rowView.EndEdit();
    }

错误报告指出 holdone.fill(holdall) 这一行存在问题,但我不确定原因,因为我没有将 SQLCommand 作为参数使用,而是使用了 SQLDataAdapter 的参数。
我不太清楚自己哪里出错了。

1
@Jonny ExecuteReader:CommandText 属性未初始化。 - Wolfish
1
@Jonny Ah。这是一个“InvalidOperationException”。 - Wolfish
1
@AlexBell,命令文本未初始化和无效的命令语法之间存在差异。如果他只将 “一些” 文本分配给命令,他将不会得到他现在所遇到的错误。 - Thorsten Dittmar
1
@AlexBell 抱歉,我的意思是那段文字已被我从帖子中删除,而不是我实际在使用 *。对于任何困惑感到抱歉。 - Wolfish
1
@AlexBell 这里有一个误解 - 我试图指出你的评论没有帮助到提到的问题 :-) - Thorsten Dittmar
显示剩余8条评论
3个回答

4
问题在于,您在此行代码中将SqlDataAdapter的选择命令字符串设置为getCommand当前值:


SqlDataAdapter holdone = new SqlDataAdapter(getCommand, dbConnection); 

然而,由于字符串不是真正的指针,改变getCommand后将不会更改SqlDataAdapter的选择命令。

你需要做的是:

public void GetOne(/* connectionString, string invref, string tableref*/)
{

    getCommand = "select *redacted* from " + tableref + "where *redacted* = " + invref;
    using (SqlConnection dbConnection = new SqlConnection(DBConnection.DBConnection.connectionString))
    {
        dbConnection.Open();

        holdone.SelectCommand = new SqlCommand(getCommand, dbConnection);
        holdone.Fill(holdall);

        invoiceTable = holdall.Tables[0];
        //dbConnection.Close(); // This line is unnecessary, as the connection will be closed by `using`
    }

    DataRowView rowView = invoiceView.AddNew();
    rowView["*redacted*"] = invoiceTable;
    rowView.EndEdit();
}

1
如果我使用这个,我可以摆脱在 holdone 声明中的现有重载吗?也就是说:...ldone = new SqlDataAdapter(removethis) - Wolfish
1
实际上,在你的GetOne方法之外声明SqlDataAdapter没有任何意义,因为它应该是无状态的。你可以在Fill之前创建它,之后销毁它(使用using)。 - Thorsten Dittmar
1
如果是这种情况,我认为使用相同的适配器执行update()是不好的形式?这是我在类的根部声明适配器的初衷。 - Wolfish
1
这并不是不好的形式 - 当然,您可以将适配器“全局”声明,并在需要时重复使用它。但是,反复更改命令文本是不好的风格,因为这可能会让人感到困惑,不知道正在使用哪个命令文本。 - Thorsten Dittmar
1
好的。在这种情况下,我将把我的声明留在处理程序类的根部。你真是太棒了,非常感谢。 - Wolfish
显示剩余2条评论

1

看起来你在将getCommand传递给SqlDataAdapter构造函数之前,还没有为其分配实际的SQL命令。首先初始化getCommand字符串,然后再构造SqlDataAdapter对象。


1
我需要将命令与其他内容隔离开来,因为我可能会重新使用适配器。此外,我刚刚尝试过同样的操作,结果也是一样的。 - Wolfish
1
@Wolfish 那你做错了。在 GetOne 方法中,确实设置了 getCommand,但是你没有将其赋值给 holdone SQL 适配器的 CommandText。请记住,您不是设置对 getCommand 的引用,而是在这一行中将内部命令文本设置为 getCommand 的当前值:SqlDataAdapter holdone = new SqlDataAdapter(getCommand, dbConnection);。改变 getCommand 不会 更改 SqlDataAdapter 的命令文本! - Thorsten Dittmar

0

您的CommandText是按值传递给SqlDataAdapter的,而不是按引用传递,因此在创建适配器后更改变量getCommand将不会影响数据适配器。一个非常简单的演示是:

static void Main(string[] args)
{
    string r = "Test";
    using (var adapter = new SqlDataAdapter(r, new SqlConnection("")))
    {
        r = "Test2";
        Console.WriteLine(adapter.SelectCommand.CommandText);
    }

}

输出

测试

不是

测试2

您需要显式更改适配器的SelectCommand.CommandText:

holdone.SelectCommand.CommandText = getCommand;

就算这样重复使用对象也没有什么用,它几乎不会节省代码。.NET 使用连接池,因此使用多个 SQL 连接/适配器并不一定意味着对数据库有多个管道。您还应该使用参数化查询

string sql = "select *redacted* from " + tableref + " where *redacted* = @InvoiceParam";
using (var adapter = new SqlDataAdapter(sql, DBConnection.DBConnection.connectionString))
{
    adapter.SelectCommand.Parameters.AddWithValue("@InvoiceParam", invRef);
    adapter.Fill(holdall);
    invoiceTable = holdall.Tables[0];
}

1
我感谢有关参数化查询的建议,我会进一步研究。至于SelectCommand,@ThorstenDittmar上面的答案似乎有效。 - Wolfish

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