【问题标题】:update insert data from bounded datagridview from datatable从数据表中更新有界数据网格视图中的插入数据
【发布时间】:2018-09-21 12:55:55
【问题描述】:

我已将datagridviewdatatable 与sql server 数据库绑定

我需要知道如何制作更新按钮,点击更新此datagridview 中的已编辑数据

如果有新的直接添加行到datagridview将它们插入数据库 如果之前有界数据有更新,则更新它

我搜索了,但我真的不明白该怎么做

  1. 为什么我必须使用DataAdpterReader

  2. 为什么我必须使用Dataset,它是一组DataTable,而我已经有一个DataTable

谢谢

【问题讨论】:

  • Here is a full example of one way to do it。它使用SqlDataAdapter,它与数据表一起可以在您的数据库上跟踪和执行CRUD。在您看到SQLite... 的地方,您可以将其与Sql... 一起使用
  • @Crowcoder 它是用.net4.5.2 编写的,我正在处理.net4.0
  • 如果您删除对 SQLite 的引用并添加以前的版本,它可能仍然有效。除此之外,它应该可以一直工作到 .net 2.0 甚至更早。最坏的情况是您可以参考代码,它保持简单并带有注释。

标签: c# visual-studio-2013 datagridview .net-4.0


【解决方案1】:

如果您想让 DataGirdView 中的行反映在数据库中,您只需使用 DataAdapter 对象的方法即可。

简单地说,DataAdapterDataReader 对象为您提供了一种简单而有效的方式来读取和写入数据库。除此之外,他们还会在不影响实际数据库表的情况下执行所有这些操作,这意味着在您说之前,一切都不会受到影响。

对于这个例子,假设我们有一个名为 contacts 的 SQL 表,其中包含三列,即 fnamemnamelname em>。

首先,我们需要一个函数来从“联系人”表中获取数据。

    protected DataSet GetData()
    {
        // our select query to obtain all the rows from the contacts table
        string selectQuery = "SELECT * FROM contacts";

        // Where the data from the underlying table will be stored
        DataSet ds = new DataSet();

        // Connect to the database and get the data from the "contacts" table
        using (SqlConnection conn = new SqlConnection(connString))
        {
            using (SqlDataAdapter da = new SqlDataAdapter(selectQuery, conn))
            {
                da.Fill(ds, "contacts"); // Add the rows from the "contacts" table to our dataset
            }
        }

        return ds;
    }

然后,您可以通过执行将 DGV 绑定到存储在返回的数据集对象中的表

DGV_Items.DataSource = GetData();

在您的 form_load 事件中。

现在我们已经完成了从数据库中获取数据的方法的设置,我们现在设置了一个方法来操作我们现在拥有的所有数据。

    protected void UpdateTable(DataSet ds)
    {
        SqlConnection conn = new SqlConnection(connString);

        // Insert, update and delete queries
        string updateQuery = "UPDATE contacts SET fname=@first,mname=@middle,lname=@last WHERE ID=@id";
        string deleteQuery = "DELETE FROM contacts WHERE ID=@id";
        string insertQuery = "INSERT INTO contacts VALUES(@first,@middle,@last)";

        // Create the parameters for the queries above
        SqlParameter[] insertParams = new SqlParameter[]
        {
            // the first parameter (e.g. @first) has to match with the declaration in the query

            // the second parameter (e.g.SqlDbType.NVarChar) is the data type of the actual column in the source table

            // the third paramter (e.g. 100) is the length of the data in the database table's column

            // the last parameter (e.g. "fname") is the DataPropertyName of the source column which is
            // basically the name of the database table column that the DGV column represents

            new SqlParameter("@first", SqlDbType.NVarChar, 100, "fname"),
            new SqlParameter("@middle", SqlDbType.NVarChar, 100, "mname"),
            new SqlParameter("@last", SqlDbType.NVarChar, 100, "lname")
        };

        SqlParameter[] updateParams = new SqlParameter[]
        {
            new SqlParameter("@first", SqlDbType.NVarChar, 100, "fname"),
            new SqlParameter("@middle", SqlDbType.NVarChar, 100, "mname"),
            new SqlParameter("@last", SqlDbType.NVarChar, 100, "lname"),
            new SqlParameter("@id", SqlDbType.Int, 100, "id")
        };

        SqlParameter[] DeleteParams = new SqlParameter[]
        {
            new SqlParameter("@id", SqlDbType.Int, 100, "id")
        };

        // Create the SqlCommand objects that will be used by the DataAdapter to modify the source table
        SqlCommand insertComm = new SqlCommand(insertQuery, conn);
        SqlCommand updateComm = new SqlCommand(updateQuery, conn);
        SqlCommand deleteComm = new SqlCommand(deleteQuery, conn);

        // Associate the parameters with the proper SqlCommand object
        insertComm.Parameters.AddRange(insertParams);
        updateComm.Parameters.AddRange(updateParams);
        deleteComm.Parameters.AddRange(DeleteParams);

        // Give the DataAdapter the commands it needs to be able to properly update your database table
        SqlDataAdapter dataAdapter = new SqlDataAdapter()
        {
            InsertCommand = insertComm,
            UpdateCommand = updateComm,
            DeleteCommand = deleteComm
        };

        // A DataTable and a DataSet are basically the same. Except the DataSet is a collection of DataTables
        // Here, you can see that we've accessed a specific DataTable in the DataSet.

        // Calling the Update method executes the proper command based on the modifications to the specified
        // DataTable object then commits these changes to the database
        dataAdapter.Update(ds.Tables["contacts"]);
    }

上述方法将处理所有数据操作。它将根据对绑定到 DGV 的 DataTable 对象所做的更改进行操作。最后,您可以调用我们在 update 按钮的事件处理程序中创建的所有方法。

    private void Btn_Update_Click(object sender, EventArgs e)
    {
        // Grab the DGV's data source which contains the information shown in the DGV
        DataSet ds = (DataSet)dgv_items.DataSource;
        // Have any updates to the said dataset committed to the database
        UpdateTable(ds);
        // rebind the DGV
        dgv_items.DataSource = GetData();
    }

编辑

根据 Crowcoder 的建议,这里有一个更好的方法来编写我上面写的所有内容:

/// <summary>
/// A collection of methods for easy manipulation of the data in a given SQL table
/// </summary>
class DBOps
{
    // The connection string contains parameters that dictate how we connect to the database
    private string connString = ConfigurationManager.ConnectionStrings["contactsConnectionString"].ConnectionString;

    // The table the instance of the class will be interacting with
    private string srcTable;

    // The SqlConnection Object that we will be using to connect to the database
    SqlConnection conn;

    // The DataAdapter object that we will be using to interact with our database
    SqlDataAdapter da;

    // The DataSet that we will be storing the data retrieved from the database
    DataSet ds;

    // The queries we would be using to manipulate and interact with the data in the database
    private string selectQuery;
    private string updateQuery;
    private string deleteQuery;
    private string insertQuery;

    // The collection of parameters for the queries above
    private SqlParameter[] insertParams;
    private SqlParameter[] updateParams;
    private SqlParameter[] DeleteParams;

    // The command objects that will be used by our data adapter when
    // interacting with the database
    private SqlCommand insertComm;
    private SqlCommand updateComm;
    private SqlCommand deleteComm;

    /// <summary>
    /// Initialize a new instance of the DBOps class
    /// </summary>
    /// <param name="tableName">The name of the table that the object will be interacting with</param>
    public DBOps(string tableName)
    {
        // Initialize the SqlConnection object
        conn = new SqlConnection(connString);

        // Initialize our collection of DataTables
        ds = new DataSet();

        srcTable = tableName;

        // initialize the query strings
        selectQuery = string.Format("SELECT * FROM {0}", srcTable);
        insertQuery = string.Format("INSERT INTO {0}(fname, mname, lnmae) VALUES(@first, @middle, @last", srcTable);
        updateQuery = string.Format("UPDATE {0} SET fname=@first, mname=@middle, lname=@last WHERE ID=@id", srcTable);
        deleteQuery = string.Format("DELETE FROM {0} WHERE ID=@id", srcTable);

        // Initialize the collection of parameters for each query above
        insertParams = new SqlParameter[]
        {
            // new SqlParameter(@paramName, paramDataType, paramValueLength, DGVDataPropertyName);
            new SqlParameter("@first", SqlDbType.NVarChar, 100, "fname"),
            new SqlParameter("@middle", SqlDbType.NVarChar, 100, "mname"),
            new SqlParameter("@last", SqlDbType.NVarChar, 100, "lname")
        };

        updateParams = new SqlParameter[]
        {
            new SqlParameter("@first", SqlDbType.NVarChar, 100, "fname"),
            new SqlParameter("@middle", SqlDbType.NVarChar, 100, "mname"),
            new SqlParameter("@last", SqlDbType.NVarChar, 100, "lname"),
            new SqlParameter("@id", SqlDbType.Int, 100, "id")

        };

        DeleteParams = new SqlParameter[]
        {
            new SqlParameter("@id", SqlDbType.Int, 100, "id")
        };

        // Initialize the SqlCommand objects that will be used by the DataAdapter to modify the source table
        insertComm = new SqlCommand(insertQuery, conn);
        updateComm = new SqlCommand(updateQuery, conn);
        deleteComm = new SqlCommand(deleteQuery, conn);

        // Associate the parameters with the proper SqlCommand object
        insertComm.Parameters.AddRange(insertParams);
        updateComm.Parameters.AddRange(updateParams);
        deleteComm.Parameters.AddRange(DeleteParams);

        // Give the DataAdapter the commands it needs to be able to properly update your database table
        da = new SqlDataAdapter()
        {
            InsertCommand = insertComm,
            UpdateCommand = updateComm,
            DeleteCommand = deleteComm
        };
    }

    /// <summary>
    /// Retrieve the data from the SQl table
    /// </summary>
    /// <returns></returns>
    public DataSet GetData()
    {
        DataSet ds = new DataSet();

        // Connect to the database and get the data from the "contacts" table
        using (conn)
        {
            conn.Open();
            using (SqlDataAdapter da = new SqlDataAdapter(selectQuery, conn))
            {
                da.Fill(ds); // Add the rows from the "contacts" table to our dataset
            }
        }

        return ds;
    }

    /// <summary>
    /// Commit the changes present in the object's DataSet to the Database
    /// </summary>
    public void UpdateData(DataSet ds)
    {
        // Calling the Update method executes the proper command based on the modifications to the specified
        // DataTable object
        da.Update(ds.Tables[srcTable]);
    }

要使用这个类,只需编写它的一个实例:

DBOps ops = new DBOps("contacts");

更新按钮的点击事件处理程序中,您可以通过调用 UpdateData 方法提交对 DGV 底层数据源所做的所有更改。

private void Btn_Update_Click(object sender, EventArgs e)
{
    // Grab the DGV's data source which contains the information shown in the DGV
    DataSet ds = (DataSet)dgv_items.DataSource;
    // Have any updates to the said dataset committed to the database
    ops.UpdateData(ds);
    // rebind the DGV
    dgv_items.DataSource = ops.GetData();
}

总结一下:

  • DataAdapterDataReader 对象为您提供了允许您以安全、高效和简单的方式与数据库交互的方法。
  • DataTableDataSet 几乎相同。除了DataTable 只是一个表,DataSetDataTables 的集合。另一方面,它们中的每一个也具有其他没有的特定方法。

【讨论】:

  • 我不建议每次都更新适配器、数据集和命令/参数,当您 Update() 时已经调用了 AcceptChanges
  • 啊,正确。我完全忘记了这一点。另一方面,我过去常常分解这样的东西并将它们放在一个名为 DatabaseOps 的类中,我也建议 OP 也这样做。我应该编辑吗?感谢您的反馈@Crowcoder :)
  • @sam 我再次更新了代码。对于那个很抱歉。以 $ 为前缀的字符串值表示它是一个模板字符串,大括号之间的空格是放置变量的位置。而以 @ 符号为前缀的字符串表示将按原样解释 (Checkout verbatim string literals)。
  • 另一方面,如果你想向选择查询传递一个值,你必须这样做:string selectQuery = $"SELECT * FROM {tableName} WHERE ID=@id;SqlCommand selectCommand = new SqlCommand(selectQuery);selectCommand.Parameters.AddWithValue("id", 1);
  • 如果您想将值传递给 SqlCommand 对象而不必指定数据类型,则 SqlParameter 对象的构造函数有一个重载,其中只有参数“@name”的名称及其假定value 是必需的,用作 this 的第二个参数的值可以是任何东西,从变量到从文本框中获取的东西。
【解决方案2】:

如果我理解正确,您只需要执行将重新填充“刷新”网格的相同查询,即 OnClick - 执行上面的代码。我真的不明白你的 if 条款?如果有新的?新数据?您想将其添加到数据库中吗?您可以将该功能添加到此 OnClick 事件中,以将存在的任何内容写入数据库,无论是否更改,这实际上取决于您提供的数据量,因此解决方案可能会有所不同。

【讨论】:

    【解决方案3】:

    我想出了一个解决方案,我创建了一个方法来获取所有数据并将其添加到数据集中的 DataTable 中,如下例所示

    public DATEaSet GetDATEa()
    {
        string connStr = ConfigurationManager.ConnectionStrings["connstr"].ToString();
        string cmdStr = @"SELECT  SEQ,
                                           ID,
                                           DATE,
                                           Started,
                                           END,
                                           TYPE,
                                           ENTRANCE,
                                           OUTGOING
                                   FROM LOGING
                            WHERE SICK_ID=@ID;";
    
        SqlConnection conn = new SqlConnection(connStr);
        using (SqlCommand cmd = new SqlCommand(cmdStr, conn))
        {
            try
            {
                conn.Open();
                cmd.CommandText = cmdStr;
                cmd.CommandType = CommandType.Text;
    
                ds = new DATEaSet();
                cmd.Parameters.Add(new SqlParameter("@ID", SqlDbType.Int)).Value = Convert.ToInt32(TB_ID.Text);
                da = new SqlDATEaAdapter(cmd);
    
                da.Fill(ds, "DATEaTable1");
                MyDGV.Columns["MyDGV_RowNum"].DATEaPropertyName = ds.Tables["DATEaTable1"].Columns["SEQ"].ColumnName;
                MyDGV.Columns["MyDGV_SessionID"].DATEaPropertyName = ds.Tables["DATEaTable1"].Columns["ID"].ColumnName;
                MyDGV.Columns["MyDGV_DATEe"].DATEaPropertyName = ds.Tables["DATEaTable1"].Columns["DATE"].ColumnName;
                MyDGV.Columns["MyDGV_StartTime"].DATEaPropertyName = ds.Tables["DATEaTable1"].Columns["Started"].ColumnName;
                MyDGV.Columns["MyDGV_EndTime"].DATEaPropertyName = ds.Tables["DATEaTable1"].Columns["END"].ColumnName;
                MyDGV.Columns["MyDGV_Type"].DATEaPropertyName = ds.Tables["DATEaTable1"].Columns["TYPE"].ColumnName;
                MyDGV.Columns["MyDGV_CreatedBy"].DATEaPropertyName = ds.Tables["DATEaTable1"].Columns["ENTRANCE"].ColumnName;
                MyDGV.Columns["MyDGV_EntryDATEe"].DATEaPropertyName = ds.Tables["DATEaTable1"].Columns["OUTGOING"].ColumnName;
    
                return ds;
            }
            catch (Exception ex)
            {
                string ErrorMsg = ex.Message.Substring(0, Math.Min(ex.Message.Length, 1024));
                MessageBox.Show(ErrorMsg);
                return null;
            }
        }
    }
    

    Form_Load 事件中,我已将Datagridview 的DataSource 设置为上述方法返回的DS

    注意在某些情况下您必须明确设置DataMember

    MyDGV.DataSource = GetPatientSessions();
    MyDGV.DataMember = "DATEaTable1";
    

    现在当用户编辑或添加行到datagridview然后按下保存按钮时,下面的方法将更新编辑数据并插入新行输入

    private void BTN_Save_Click(object sender, EventArgs e)
    {
        using (SqlCommandBuilder cmdbuilder = new SqlCommandBuilder(da))
        {
            try
            {
                da.Update(ds, "DATEaTable1");
            }
            catch (Exception ex)
            {
                string ErrorMsg = ex.Message.Substring(0, Math.Min(ex.Message.Length, 1024));
                MessageBox.Show(ErrorMsg);
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多