1

注意:我的办公室不允许我查看 YouTube 和其他几个可能有此问题答案的网站(它们已被屏蔽),这就是谷歌搜索答案没有产生结果的原因。

ComboBox 代码参考:在此处找到

在我的 上C# Form,我用数据库中的表填充了一个 ComboBox(参见下面的代码),它正确返回了适当的值和函数:

public Form1()
        {
        InitializeComponent();

        // Connection
        SqlConnection conn = new SqlConnection();
        conn.ConnectionString = "CONNECTION STRING" // shortened for security and convenience

        // Fill ComboBox with SQL Values
        conn.Open();
        SqlCommand cmbTables = new SqlCommand("SELECT name FROM sys.tables", conn);
        SqlDataReader read = cmbTables.ExecuteReader();
        DataTable cmbData = new DataTable();
        cmbData.Columns.Add("name", typeof(string));
        cmbData.Load(read);
        cmb1.DisplayMember = "name";
        cmb1.DataSource = cmbData;
        conn.Close();
    }

ComboBox加载表(有效)之后,应用程序然后选择一个表并单击一个加载该表的按钮,该表被选中。这是代码错误的地方:

private void button1_Click(object sender, EventArgs e)
        {
            using (var connection = Utilities.GetConnection())
            { 

                string table = Convert.ToString(txt1.Text);
                string cmb1Value = Convert.ToString(cmb1.SelectedItem);

                // Stored Procedure
                SqlCommand select = new SqlCommand("EXECUTE STOREDPROCEDURE" + cmb1Value, connection); // shortened for security and convenience
                select.Parameters.Add(new SqlParameter(cmb1Value, table));

                // Data View
                SqlDataAdapter ad= new SqlDataAdapter(select);
                ad.SelectCommand = select;
                DataTable dt = new DataTable();
                ad.Fill(dt); // this generates the error "Incorrect Syntax Near '.'"
                BindingSource b = new BindingSource();
                b.DataSource = dt;
                dGrid.DataSource = b;
                ad.Update(dt);
                connection.Close();
            }
        }

即使 ComboBox 加载了适当的值,从上面的代码中,我可能会丢失将这些值附加到存储过程的东西(它所做的只是通过传递给它的变量SELECT调用语句)。SELECT该错误"Incorrect Syntax Near '.'"看起来像是SQL Server我见过的错误,但不记得我是如何生成它的(这是我通常如何排查TSQL代码出错的地方)。\

存储过程相关代码:

C#:    
SqlCommand select = new SqlCommand("EXECUTE STOREDPROCEDURE " + cmb1Value, connection);

TSQL:    

CREATE PROCEDURE [STOREDPROCEDURE]
    @TableName VARCHAR(250)
AS
BEGIN

    DECLARE @sql NVARCHAR(MAX)
    SET @sql = N'SELECT TOP 100 *
        FROM ' + @TableName

    EXECUTE(@sql)

END

-- Note this works in SSMS without a problem.

上面的代码不正确,当我调整TSQL代码时,我会产生类似的错误,告诉我在某处我缺少转换或另一个变量,因为SQL Server没有看到(第一个代码块)返回的这些表值SELECT。我可以确定这一点,因为我有第二个组合框,它使用类似的代码,除了我用手动值填充组合框,它连接到数据库中的表而没有错误。因此,您在上面看到的从数据库中获取值的 ComboBox 无法正常工作。

例如,如果我只将以下代码行添加到代码中,我会收到一个错误,它找不到数据库“EXECUTE STOREDPROCEDURE System”

select.CommandType = CommandType.StoredProcedure;

但是,System不是任何事物的一部分,那么它是从哪里来的呢?它在手动 ComboBox 上的代码从未出错,因为它可以轻松找到数据库(使用相同的连接字符串、服务器和数据库!)。

如果我尝试使用 TSQL 参数,例如:

SqlCommand select = new SqlCommand("EXECUTE stp_ReturnTable @p", scon);
select.Parameters.Add(new SqlParameter("@p", cmb1Value));

突然,它找不到存储过程。同样,手动 ComboBox 和动态 ComboBox 的连接字符串是相同的。

我认为动态 ComboBox 背后的代码是错误的。当我不在办公室时,我将查看一些视频,其中包含有关如何从数据库创建动态 ComboBox 的详细演示,并且我预感到系统对象在路上(基于系统错误,它存在我的代码中没有任何地方,以及它突然无法找到数据库或过程)。

4

1 回答 1

8

The missing key point in your code is the CommandType.
Without the proper set of this property the default is CommandText and thus the Framework expects a statement that starts with SELECT/INSERT/UPDATE/DELETE etc....

using (var connection = Utilities.GetConnection())
{ 
    string table = Convert.ToString(txt1.Text);
    string cmb1Value = Convert.ToString(cmb1.SelectedItem);

    // Stored Procedure
    SqlCommand select = new SqlCommand("STOREDPROCEDURE", connection);
    select.Parameters.Add(new SqlParameter("@TableName", cmb1Value));


    // That's the key to let ADO.NET accept the previous CommandText as valid.
    // If you omit this the CommandText is assumed to be a SELECT/UPDATE/DELETE etc..
    select.CommandType = CommandType.StoredProcedure;  


    // Data View
    SqlDataAdapter ad= new SqlDataAdapter(select);
    DataTable dt = new DataTable();
    ad.Fill(dt); 
    BindingSource b = new BindingSource();
    b.DataSource = dt;
    dGrid.DataSource = b;
}

EDIT Having seen the code of the SP then you could simply set the SqlParameter name to the constant @TableName and pass the value extracted from the combobox as the value to be used inside the SP

EDIT I have looked again at your code and I suspect that the culprit is the line

 string cmb1Value = Convert.ToString(cmb1.SelectedItem);

Looking at how you have filled your combo, this line, doesn't return the tablename as you expect, but the generic string System.Data.DataRowView because the DataSource of the combo is a DataTable and not a string collection. You should try to change that line in this way

DataRowView rw = cmb1.SelectedItem as DataRowView;
if(rw != null)
{
     string cmbValue1 = rw["name"].ToString();
     ....

And yes, your code should work also without the CommandType.StoredProcedure line because the text EXECUTE sp param is recognized as a valid sql commandtext (but why do you use it when a direct call to the storedprocedure could be optimized for reuse?)

于 2013-06-10T17:13:48.747 回答