需求:不能每加一条数据就操作数据库,要完成所有的数据加入界面,点击保存时才一次性保存。
加载数据时,数据源上可以有数据,并可以在界面上对数据进行增加、修改、删除。
所有操作,在点击保存时,准确地将所需要的操作结果反应到数据库中。
解决思路:先在程序中判断哪些数据要增加到数据库,哪些数据要对数据库中数据进行修改,哪些数据要进行删除。
再循环操作数据库。
#region 一次性判断并获取DataGridViewRow数据的操作情况 /// <summary> /// 一次性判断并获取DataGridViewRow数据的操作情况 /// </summary> /// <param name="dt">初始化DataGridView时绑定的数据源</param> /// <param name="DataGridViewRows">修改后的DataGridView.Rows</param> /// <param name="UniColumn">记录的唯一标识,可以是主键。能保证唯一的属性就行</param> /// <returns> 返回值为Dictionary《object, int》,value值: 1为新增,2为修改,3为删除,4 什么也不做</returns> public static IDictionary<object, int> GetCompareDataGridViewRows(DataTable dt, DataGridViewRowCollection DataGridViewRows, string UniColumn) { IDictionary<object, int> dictlist = new Dictionary<object, int>(); List<string> listOperated = new List<string>(); int OperateType = -1; if (DataGridViewRows.Count > 0) { for (int i = 0; i < DataGridViewRows.Count; i++) { OperateType=OperateModel(dt, DataGridViewRows[i], UniColumn); if (OperateType == 1 || OperateType == 2)//添加或修改的 { dictlist.Add(DataGridViewRows[i], OperateType); } listOperated.Add(DataGridViewRows[i].Cells[UniColumn].Value.ToString()); } } for (int j = 0; j < dt.Rows.Count; j++) { if (!listOperated.Contains(dt.Rows[j][UniColumn].ToString())) { dictlist.Add(dt.Rows[j][UniColumn], 3); //要删除的 } } return dictlist; /***************使用方法*********************** IDictionary<object, int> dictlist = CommonFunctions.GetCompareDataGridViewRows(list, dataGridView.Rows, "contct_cd"); foreach (var dt in dictlist) { //定义model类,从DataGridViewRow中读取数据 switch (dt.Value) { case 1: DataGridViewRow row = (DataGridViewRow)dt.Key; //增加到数据库代码 break; case 2: DataGridViewRow row = (DataGridViewRow )dt.Key; //修改到数据库的代码 break; case 3: string primarykey=(string)dt.Key; //从数据库删除的代码 break; } } ***********************************************/ } #endregion #region 判断需要操作的类型 OperateModel /// <summary> /// 判断需要操作的类型 1为新增,2为修改,4 什么也不做 /// </summary> /// <param name="modelcmp"></param> /// <returns></returns> private static int OperateModel(DataTable dt, DataGridViewRow row, string UniColumn) { if (dt.Rows.Count == 0) return 1; bool isExist = false; //是否存在 bool isModified = false; //是否修改过 for (int i = 0; i < dt.Rows.Count; i++) //遍历list数据,一个一个判断 { DataRow CurrentRow = dt.Rows[i]; //当前行 if (CurrentRow[UniColumn].ToString() == row.Cells[UniColumn].Value.ToString()) //如果唯一标识相同 { for (int j = 0; j < dt.Columns.Count; j++) { string columnName = dt.Columns[j].ColumnName; if (CurrentRow[columnName].ToString() != row.Cells[columnName].Value.ToString()) { isModified = true; break; } } isExist = true; break; } } if (isExist && isModified) { return 2; } else if (!isExist) { return 1; } else return 4; } #endregion
提示:使用对比的不能是数据源,只有另外定义一个DataTable dtCopy=dt.Copy(); 不去操作dtCopy,对dt操作才不能影响到副本dtCopy,直接等于是不可以的。
还有DataGridViewRow也是一样,因为这个问题,搞了半天,最后才知道,他们都是引用类型,即使把DataGridViewRow加入List,一旦改变DataGridView的行,List中的DataGridViewRow也会被修改。