问题 救 dataGridView data for the selected data records

安德鲁·马努亚

知名会员
已加入
五月30,2019
留言内容
75
编程经验
Beginner
大家好,
我正在开发一个具有dataGridView的小型应用程序,第一列有一个"CheckBox".
我的要求是,如果用户已选择/检查了dataGridView的记录,则在击中该记录时,这些记录应保存到数据库表中。"Save" button.
但是,我碰到过,按照我的代码,foreach命令和if条件(以检查用户是否选择了一个项目)不能一起工作。
请在下面找到相应的代码;

C#:
 SqlConnection con = new SqlConnection(@"Data Source=55504-CGHS\\SQLEXPRESS;Initial Catalog=Test_CheckBox;Integrated Security=True");
            SqlCommand cmd;

            using (con)
            {
                foreach (DataGridView row in dataGridViewProducts.Rows)
                {
                    if (Convert.ToBoolean(dataGridViewProducts.Rows[row].Cells["selectItem"].Value) == true)
                    {
                        cmd = new SqlCommand(@"INSERT INTO tbl_Product(productID,productName,quantity) VALUES (@aproductID,@aproductName,@aquantity)", con);
                        cmd.Parameters.AddWithValue("@aproductID", Convert.ToInt32(row.Cells["textProductID"].Value == DBNull.Value ? "0" : row.Cells["textProductID"].Value.ToString()));
                        cmd.Parameters.AddWithValue("@aproductName", row.Cells["textProductName"].Value == DBNull.Value ? "0" : row.Cells["textProductName"].Value.ToString());
                        cmd.Parameters.AddWithValue("@aquantity", Convert.ToInt32(row.Cells["textQuantity"].Value == DBNull.Value ? "0" : row.Cells["textQuantity"].Value.ToString()));

                        cmd.ExecuteNonQuery();
                    }
                }
            }

我的数据库表如下所示;

1580690640713.png


请告诉我如何解决上述问题。

先感谢您。
亲切的问候,
安德鲁
 

金西尼

C#论坛主持人
工作人员
已加入
2011年4月23日
留言内容
3,534
地点
悉尼,澳大利亚
编程经验
10+
不要那样做。我的建议是,您遍历网格,获取底层 数据行 并将其添加到新 数据表,然后使用数据适配器一次性保存很多。我会提供一个示例。
 

金西尼

C#论坛主持人
工作人员
已加入
2011年4月23日
留言内容
3,534
地点
悉尼,澳大利亚
编程经验
10+
实际上,我想到可能有更好的方法,具体取决于具体情况。首先如何准确地填充网格?这是我的构想:
C#:
private DataTable table = new DataTable();

private void button2_Click(object sender, EventArgs e)
{
    // Get data from source.
    using (var adapter = new SqlDataAdapter("SELECT * FROM SourceTable", "source connection string here"))
    {
        adapter.Fill(table);
    }

    // Add column for selection.
    table.Columns.Add("Flag", typeof(bool));

    // Bind to grid.
    dataGridView1.DataSource = table;
}

private void button1_Click(object sender, EventArgs e)
{
    // Mark selected rows ready for insert.
    foreach (DataRow row in table.Rows)
    {
        if ((bool)row["Flag"])
        {
            row.SetAdded();
        }
    }

    // Save data to destination.
    using (var connection = new SqlConnection("destination connection string here"))
    using (var command = new SqlCommand("INSERT INTO DestinationTable (Column1, Column2) VALUES (@Column1, @Column2)", connection))
    using (var adapter = new SqlDataAdapter { InsertCommand = command })
    {
        command.Parameters.Add("@Column1", SqlDbType.VarChar, 50, "Column1");
        command.Parameters.Add("@Column2", SqlDbType.Int, 0, "Column2");

        adapter.Update(table);
    }
}
该代码将复选框列放入 数据表,这不是必需的,但我认为更方便。尽管原理相同。填充一个 数据表,绑定它,进行选择,循环并标记添加,然后保存。
 

安德鲁·马努亚

知名会员
已加入
五月30,2019
留言内容
75
编程经验
Beginner
嗨Jmcilhinney,
我遵循了您的步骤,但是在加载数据并将数据保存到数据库表时仍然遇到问题。
检索数据时,我收到错误消息,"初始化字符串的格式不符合从索引0开始的规范。我在线检查了一下,它说这与连接字符串有关,但是,找不到与连接字符串有关的任何问题。
请在下面找到我的代码,
C#:
 SqlConnection source_con = new SqlConnection(@"Data Source=55504-CGHS\\SQLEXPRESS;Initial Catalog=Test_CheckBox;Integrated Security=True");

        private DataTable table = new DataTable();

        private void btnSave_Click(object sender, EventArgs e)
        {
            //Mark selected rows ready for insert
            foreach (DataRow row in table.Rows)
            {
                if((bool)row["selectItem"])
                {
                    row.SetAdded();
                }
            }
            //Save data to destinaion
            using (var connection = new SqlConnection(@"Data Source=55504-CGHS\SQLEXPRESS;Initial Catalog=Test_CheckBox;Integrated Security=True"))
            using (var command = new SqlCommand("INSERT INTO tbl_Product (productID,productName,quantity) VALUES (@aproductID,@aproductName,@aquantity)", connection))
            using (var adapter = new SqlDataAdapter { InsertCommand = command })
            {
                command.Parameters.Add("@aproductID", SqlDbType.Int, 0, "textProductID");
                command.Parameters.Add("@aproductName", SqlDbType.VarChar , 50, "textProductName");
                command.Parameters.Add("@aquantity", SqlDbType.Int, 0, "textQuantity");

                adapter.Update(table);              
            }            
        }

        private void btnGetData_Click(object sender, EventArgs e)
        {
            //Get data from source
            using (var adapter = new SqlDataAdapter("Select productID, productName, quantity from tbl_Product", "source_con"))
            {
                adapter.Fill(table);
            }

            //Add column for selection
            table.Columns.Add("selectItem", typeof(bool));

            //Bind to grid
            dataGridViewProducts.DataSource = table;
        }


该应用程序不会将dataGridView数据保存到数据库表中。

感谢您的宝贵反馈。
抱歉,如果我在这里犯了一个愚蠢的错误。
谢谢你。

亲切的问候,

安德鲁
 

金西尼

C#论坛主持人
工作人员
已加入
2011年4月23日
留言内容
3,534
地点
悉尼,澳大利亚
编程经验
10+
那里有两个错误。首先,您在这里做什么:
C#:
using (var adapter = new SqlDataAdapter("Select productID, productName, quantity from tbl_Product", "source_con"))
您正在使用的重载 SqlDataApapter constructor that expects a connection string as the second argument. Is "source_con" a valid connection string? No, it's not, any more than "Hello World" is a valid connection string. You do have a variable named source_con 指的是 SqlConnection 对象,所以也许您应该使用需要一个 SqlConnection object:
C#:
using (var adapter = new SqlDataAdapter("Select productID, productName, quantity from tbl_Product", source_con))
其次,您使用的是逐字字符串文字,但您仍在尝试转义反斜杠:
C#:
SqlConnection source_con = new SqlConnection(@"Data Source=55504-CGHS\\SQLEXPRESS;Initial Catalog=Test_CheckBox;Integrated Security=True");
字符串文字是双引号之间的任何文本。逐字字符串文字是指任何以字符串开头的字符串文字 @ 象征。使用逐字字符串文字的目的是您不必转义反斜杠。 C#使用C样式的转义序列,这些序列以反斜杠开头的字符,例如您可以使用适当的转义序列添加换行符:
C#:
var text = "First Line\r\nSecond Line";
由于反斜杠字符表示转义序列,因此文字反斜杠也必须转义。这在文件路径中尤其令人讨厌,例如
C#:
var filePath = "C:\\Folder\\File.ext";
两个避免了必须将此类文字中的所有反斜杠加倍,引入了逐字字符串文字。逐字字符串文字将所有反斜杠视为文字字符,因此无法进行转义序列。对于诸如文件路径之类的东西来说这不是问题。
C#:
var filePath = @"C:\Folder\File.ext";
在您的代码中,两个连接字符串都使用逐字字符串文字,但是第一个仍将反斜杠加倍,而第二个则不是。
 

安德鲁·马努亚

知名会员
已加入
五月30,2019
留言内容
75
编程经验
Beginner
你好,
感谢您的宝贵答复。
现在我可以检索数据了,但是得到一个错误"指定的演员表无效".
但是,我将尝试一下并重新返回。
谢谢你。
亲切的问候,
安德鲁
 

金西尼

C#论坛主持人
工作人员
已加入
2011年4月23日
留言内容
3,534
地点
悉尼,澳大利亚
编程经验
10+
您应该已经指定了,但是我猜这在这里发生:
C#:
if((bool)row["selectItem"])
我没有考虑到每一行实际上都会包含 DBNull.Value 默认情况下在该列中。解决方法有很多种,但是最简单的方法可能是将代码更改为此:
C#:
if(row["selectItem"] as bool? == true)
 

安德鲁·马努亚

知名会员
已加入
五月30,2019
留言内容
75
编程经验
Beginner
嗨Jmcilhinney,

感谢您提供上述有意义的反馈。

不得不对代码进行较小的更改,现在它可以正常工作。感谢您的指导。

需要您一点澄清。需要将添加的列(选择项)设置为第一列以显示在dataGridView上。
尝试使用"SetOrdinal"命令来完成它,但是没有用。我应该在数据绑定步骤中考虑顺序吗?有什么建议吗?

请在下面找到经过微调的代码,并感谢您对代码的评论。

C#:
SqlConnection source_con = new SqlConnection(@"Data Source=55504-CGHS\SQLEXPRESS;Initial Catalog=Test_CheckBox;Integrated Security=True");

private DataTable table = new DataTable();

private void btnSave_Click(object sender, EventArgs e)
{
    //"row.SetAdded()" was giving an error called"SetAdded and SetModified can only be called on DataRows with Unchanged DataRowState". Thus, after adding "table.AcceptChanges()", the issue was able to resolve
    table.AcceptChanges();
    //Mark selected rows ready for insert
    foreach (DataRow row in table.Rows)
    {
        if (row["Select Item"] as bool? == true)
        {
            row.SetAdded();
        }
    }
    //Save data to destinaion

    using (var command = new SqlCommand("INSERT INTO tbl_Product (productID,productName,quantity) VALUES (@aproductID,@aproductName,@aquantity)", source_con))
    using (var adapter = new SqlDataAdapter { InsertCommand = command })
    {
        command.Parameters.Add("@aproductID", SqlDbType.Int, 0, "productID");
        command.Parameters.Add("@aproductName", SqlDbType.VarChar, 50, "productName");
        command.Parameters.Add("@aquantity", SqlDbType.Int, 0, "quantity");

        try
        {
            adapter.Update(table);
            MessageBox.Show("Data Saved");
        }
        catch (Exception ee)
        {
            MessageBox.Show(ee.Message);
        }
    }
}

private void btnGetData_Click(object sender, EventArgs e)
{
    //Get data from source
    using (var adapter = new SqlDataAdapter("Select productID, productName, quantity from tbl_Product", source_con))
    {
        adapter.Fill(table);
    }

    //Add column for selection
    table.Columns.Add("Select Item", typeof(bool)).SetOrdinal(0);

    //Bind to grid
    dataGridViewProducts.DataSource = table;
}

非常感谢你。

亲切的问候,

安德鲁
 

金西尼

C#论坛主持人
工作人员
已加入
2011年4月23日
留言内容
3,534
地点
悉尼,澳大利亚
编程经验
10+
列在数据源中的位置和列在网格中的位置可以独立,尽管默认情况下它们是相同的。您可以将额外的列添加到 数据表 致电之前 充满,因此它将成为数据源中的第一列。或者,您可以设置 显示索引 绑定后网格列的属性。这 指数 网格列的位置是其在 同时收集 显示索引 是它在用户界面中的位置。
 
最佳 底部