DataGridView控件是微软预先写好的一个显示数据的控件,功能非常强大,可以显示来自数据库表的数据和XML等其他来源的数据。

方法一:基于DataAdapter对象创建一个CommandBulider,用来生成Sql命令,修改数据源,从而直接更改数据表的内容。

  前提是:

    1.这个表必须有主键,否则该对象无法生成Update和delete、insert的Sql命令,报异常:

     对于不返回任何键列信息的 SelectCommand,不支持 UpdateCommand 的动态 SQL 生成。

    2.实例化SqlCommandBuilder对象的数据适配器对象SqlDataAdapter必须预先设置好SelectCommand属性

    3.更新的表中不能包括image类型的字段(列)

  由于出错的情况有很多,程序员无法完全掌握,所以我们强烈建议将更新代码写在try catch里

 下面是此方法的实例:

  

     /// <summary>

/// 数据适配器

/// </summary>

SqlDataAdapter adapter = null;

/// <summary>

/// 数据集对象

/// </summary>

DataSet dSet = null;

/// <summary>

/// 连接字符串

/// </summary>

private static string strConn = "server=.\\sqlexpress;database=MySchool;uid=sa;pwd=123456";

/// <summary>

/// 窗体加载事件

/// </summary>

/// <param name="sender"></param>

/// <param name="e"></param>

private void Form3_Load(object sender, EventArgs e)

{

adapter = new SqlDataAdapter("select * from UserInfo", strConn);

dSet = new DataSet();

adapter.Fill(dSet);

DGVMain.DataSource = dSet.Tables[0];

}

/// <summary>

/// 更新按钮点击事件

/// </summary>

/// <param name="sender"></param>

/// <param name="e"></param>

private void button1_Click(object sender, EventArgs e)

{

//创建命令重建对象

SqlCommandBuilder scb = new SqlCommandBuilder(adapter);

//更新数据

try

{
         //这里是关键

adapter.Update(dSet);

}

catch (SqlException ex)

{

MessageBox.Show(ex.Message);

}

}

由于各种原因,性能问题,安全问题和其他复杂的因素。

主要缺点:

1、 基于单表,只能对一个数据源表进行更新,如果要更新数据库
中的已改变的表,则不能用它来更新了。

2、 要求数据库中必须设置好主键字段

3、 不能对存有图片的数据库进行增删改操作

4、 执行起来,速度相对于非自动化慢(当然,是在数据库的规模
很大的情况下)

需要注意的地方:

1、 必须与DataAdapter结合使用 
2、 实例化SqlCommandBuilder对象前,必须先指定好数据适配器
的填充命令(SelectCommand)。 
3、 填充命令(Select 语句)中返回的列要包括主键列,否则将无
法产生Update,和Delete语句。 
4、  使用命令构建器比手动编写SQL更好,但是它们只能处理一个
表,底层的数据库表必须有主键或唯一键。另外,数据适配器的SelectCommand属性必须有一个包含主键的查询。

这种方法在实际项目中根本不会用到,一些小项目和初学者可以尝试。

第二种方法:定位被修改的单元格,获取列名和id,构建SQL然后,然后执行更新操作。

  这种方法比第一张方法复杂多,效果却是一样的,一般也不太会去用。这里简单介绍一下。思路是:点击单元格触发DGV的CellBeginEdit事件,在此事件中保存原先的值到成员字段中,然后在DGV的CellEndEdit事件中修改数据,执行更新。

  具体的代码:

  

#region DGV直接编辑修改数据的功能

/// <summary>

/// 用来存放DGV单元格修改之前值

/// </summary>

Object cellTempValue = null;

/// <summary>

/// DGV单元格开始编辑时触发的事件

/// </summary>

/// <param name="sender"></param>

/// <param name="e"></param>

private void DGVMain_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)

{

cellTempValue = DGVMain.Rows[e.RowIndex].Cells[e.ColumnIndex].Value;

}

/// <summary>

/// DGV单元格结束编辑时触发的事件

/// </summary>

/// <param name="sender"></param>

/// <param name="e"></param>

private void DGVMain_CellEndEdit(object sender, DataGridViewCellEventArgs e)

{

//判断编辑前后的值是否一样(是否修改了内容)

if (Object.Equals(cellTempValue,
DGVMain.Rows[e.RowIndex].Cells[e.ColumnIndex].Value))

{

//如果没有修改,则返回

return;

}

//判断用户是否确定修改

if (MessageBox.Show("确定修改?", "提示", MessageBoxButtons.OKCancel,
MessageBoxIcon.None) != DialogResult.OK)

{

//如果不修改,恢复原来的值

DGVMain.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = cellTempValue;

return;

}

//修改数据库的数据

string sql = String.Format("update  set {1}='{2}' where 商品编号='{3}'",

DGVMain.Columns[0].DataPropertyName,            //所选单元格列名

DGVMain.Rows[e.RowIndex].Cells[e.ColumnIndex].Value,    //所选单元格修改后的值

DGVMain.Rows[e.RowIndex].Cells[0].Value                  //所选行的商品编号

);

try

{

OleDbHelper.ExecuteNonQuery(CommandType.Text, sql);

}

catch (OleDbException ex)

{

MessageBox.Show(ex.Message);

}

//刷新数据

LoadDGV();

}

#endregion

个人建议的解决方案:做一个ContextMenu菜单,绑定DGV,菜单中有修改数据和删除数据,当用户选择整行后,点击右键选择修改信息,立即弹出一个窗口,根据该行的id重新从数据库中取出该行记录的所有值,赋值到各个文本框中,然后点击更新,执行更新操作。这是最最纯洁的方法。

分类: C#.Net

DataGridView编辑后立即更新到数据库的两种方法的更多相关文章

  1. C++连接mysql数据库的两种方法

    本文主要介绍了C++连接mysql数据库的两种方法,希望通过本文,能对你有所帮助,一起来看. 现在正做一个接口,通过不同的连接字符串操作不同的数据库.要用到mysql数据库,以前没用过这个数据库,用a ...

  2. python学习--python 连接SQLServer数据库(两种方法)

    1. python 学习.安装教程参照: http://www.runoob.com/python/python-tutorial.html 2. 集成开发环境 JetBrains PyCharm C ...

  3. python更新数据库脚本两种方法

    最近项目的两次版本迭代中,根据业务需求的变化,需要对数据库进行更新,两次分别使用了不同的方式进行更新. 第一种:使用python的MySQLdb模块利用原生的sql语句进行更新 import MySQ ...

  4. 【Python】python更新数据库脚本两种方法

    最近项目的两次版本迭代中,根据业务需求的变化,需要对数据库进行更新,两次分别使用了不同的方式进行更新. 第一种:使用python的MySQLdb模块利用原生的sql语句进行更新   1 import ...

  5. MySQL 创建数据库的两种方法

    使用 mysqladmin 创建数据库 使用普通用户,你可能需要特定的权限来创建或者删除 MySQL 数据库. 所以我们这边使用root用户登录,root用户拥有最高权限,可以使用 mysql mys ...

  6. c#取数据库数据 ---两种方法

    通常有以下两种方式 SqlDataReader 和SqlDataAdapter|DataSet方式 SqlDataReader 方式使用方式如下: using System; using System ...

  7. MySQL 删除数据库的两种方法

    使用 mysqladmin 删除数据库 使用普通用户登陆mysql服务器,你可能需要特定的权限来创建或者删除 MySQL 数据库. 所以我们这边使用root用户登录,root用户拥有最高权限,可以使用 ...

  8. c#访问数据库的两种方法以及事务的两种方法

    //2015/07/03 using System; using System.Collections.Generic; using System.Linq; using System.Text; u ...

  9. C#将Excel数据表导入SQL数据库的两种方法(转)

    最近用写个winform程序想用excel 文件导入数据库中,网上寻求办法,找到了这个经过尝试可以使用. 方法一: 实现在c#中可高效的将excel数据导入到sqlserver数据库中,很多人通过循环 ...

随机推荐

  1. C++-POJ3070-Fibonacci-[矩阵乘法][快速幂]

    #include <cstdio> ][];}; ,MOD=1e4; Matrix A,B,O,I; Matrix Mul(Matrix A,Matrix B){ Matrix C=O; ...

  2. C++-POJ3735-Training little cats[矩阵乘法][快速幂]

    矩阵快速幂,主要是考构造.另外,swap总是写龊? 为什么?干脆放弃了.唉,我太难了. 思路:操作e和s都很好想,主要是g操作 我们可以额外空出一位,记为1,每次要加1,就对这个额外的1进行计算即可 ...

  3. 辣些数据结构的思维题(思维题好难一个都不会TAT)

    洛谷P1268 树的重量 我觉得难点在于把每个叶子节点想象成分出来的叉 然后如果c是a--b这条边上分出来的,可以通过Dab,Dca,Dcb算出分叉边的长度, 长度=(Dac+Dbc-Dab)/2 怎 ...

  4. 分类问题(三)混淆矩阵,Precision与Recall

    混淆矩阵 衡量一个分类器性能的更好的办法是混淆矩阵.它基于的思想是:计算类别A被分类为类别B的次数.例如在查看分类器将图片5分类成图片3时,我们会看混淆矩阵的第5行以及第3列. 为了计算一个混淆矩阵, ...

  5. PIE-SDK For C++栅格数据集的读取

    1.功能简介 栅格数据包含很多信息,在数据的运用中需要对数据的信息进行读取,目前PIE SDK支持多种数据格式的数据读取,下面对栅格数据格式的数据读取功能进行介绍. 2.功能实现说明 2.1 实现思路 ...

  6. 题解 CF1064A 【Make a triangle!】

    题目传送门 反正数学方法我是不会 那只能模拟了一只连模拟题解都看不懂的哀怨 我的思路大体如下 1.定义3个变量a,b,c并输入 int a,b,c; cin>>a>>b> ...

  7. BindingException: Invalid bound statement (not found)问题

  8. Docker学习(六)Dockerfile构建自定义镜像

    Docker学习(六)Dockerfile构建自定义镜像 前言 通过前面一篇文章可以知道怎么去使用一个镜像搭建服务,但是,如何构造自己的一个镜像呢,docker提供了dockerfile可以让我们自己 ...

  9. Mysql多实例数据库安装应用

    第1章 MySQL多实例数据库企业级应用实践 1.1 MySQL多实例介绍 前文已经讲了为什么选择MySQL数据库,以及MySQL数据库在Linux系统下的多种安装方式,同时以单实例讲解了编译方式安装 ...

  10. JS的冒泡事件

      在一个对象上触发某类事件(比如单击onclick事件),如果此对象定义了此事件的处理程序,那么此事件就会调用这个处理程序,如果没有定义此事件处理程序或者事件返回true,那么这个事件会向这个对象的 ...