字段很多
给出点具体的东西!最好是带注释的代码!
//找出verNew的关键值到verOld中去匹配
//找不到 该条新增 标记
//找到并一致 该条未做任何操作 标记
//找到不一致 该条为修改 标记
//就版本有未标记的内容 为被删除内容
给出点具体的东西!最好是带注释的代码!
//找出verNew的关键值到verOld中去匹配
//找不到 该条新增 标记
//找到并一致 该条未做任何操作 标记
//找到不一致 该条为修改 标记
//就版本有未标记的内容 为被删除内容
调试欢乐多
但是如果只是某个表(dtOld)的数据变化了
而你想获得某些变化,那么请用GetChanges 方法DataTable dtNew = dtOld.GetChanges(DataRowState.Added);
DataTable dtNew = dtOld.GetChanges(DataRowState.Deleted);
DataTable dtNew = dtOld.GetChanges(DataRowState.Detached);
DataTable dtNew = dtOld.GetChanges(DataRowState.Modified);
DataTable dtNew = dtOld.GetChanges(DataRowState.Unchanged);
{
for (int iRows = 0; iRwos < verOld.Rows.Count; iRows++)
{
DataRow[] drs = verNew.Select("verOld.关键字 = " + verOld.Rows[iRows]["verNew.关键字"].ToString());
if (drs != null)
{
//匹配关键字成功
for (int iItems; iItems < drs.Length; iItems++)
{
//TODO 一个字段一个字段比较罗 }
}
else
{
//匹配关键字失败
//TODO:为新增标记
}
} //TODO:没有标识就删除
}
DataTable newTable = new DataTable();
private void Form1_Load(object sender, EventArgs e)
{
oldTable.Columns.Add("Id", typeof(int));
oldTable.Columns.Add("Name");
oldTable.Rows.Add("1", "一");
oldTable.Rows.Add("2", "二");
newTable.Columns.Add("Id", typeof(int));
newTable.Columns.Add("Name");
newTable.Rows.Add("1", "一");
newTable.Rows.Add("2", "三");
newTable.Rows.Add("3", "二"); MessageBox.Show(dataTableCompare(oldTable, newTable));
} private string dataTableCompare(DataTable oldTable, DataTable newTable)
{
oldTable.PrimaryKey = new DataColumn[] { oldTable.Columns["Id"], oldTable.Columns["Name"] };
string ret = string.Empty;
DataRow dr = oldTable.NewRow();
for (int i = 0; i < newTable.Rows.Count; i++)
{
dr.ItemArray = newTable.Rows[i].ItemArray;
try
{
oldTable.Rows.Add(dr);
//注意:这里Remove以后dr的指针会跑没
oldTable.Rows.Remove(dr);
//因为前面的Remove使dr的指针跑掉了,所以要重新赋一次值
dr.ItemArray = newTable.Rows[i].ItemArray;
oldTable.PrimaryKey = new DataColumn[] { oldTable.Columns["Id"] };
try
{
oldTable.Rows.Add(dr); ret += string.Format("新表中的第{0}行是新增的\n", i.ToString());
}
catch
{
ret += string.Format("新表中的第{0}行是修改过的\n", i.ToString());
}
finally
{
oldTable.PrimaryKey = new DataColumn[] { oldTable.Columns["Id"], oldTable.Columns["Name"] };
}
}
catch
{
ret += string.Format("新表中的第{0}行是没有修改过的\n", i.ToString());
}
}
return ret;
}
但是 for 里 套try
try 里套 try
以catch 获得结果
等等,太耗费系统资源,如非必要(一般不需要),不要这样做
删除是判断不出来的,旧表中删除的,新表中有旧表中没有的,对于旧表来说就是新增的,无法判断旧表原来是否有该记录(我想你需要做这种比较就表明你不是直接对旧表的datatable进行操作,否则用不着这样做比较)
{
foreach(DataRow dr in dtNew.Rows)
{
DataRow[] drs = dtOld.Select("PrimaryKey = " + dr["PrimaryKey"].ToString());
if (drs != null) // can match, and there is only one row in drs
{
// compare every column
for(int i=0; i<dtNew.columns.count; i++)
{
drs[0] = dr[i]?
}
// if all the columns is the same
dr["Flag"] = "Unchanged";
drs[0]["Flag"] = "Unchanged";
// if all the columns is not the same
dr["Flag"] = "Modified";
drs[0]["Flag"] = "Modified";
}
else // can't match
{
dr["Flag"] = "Added";
}
}
foreach(DataRow dr in dtOld.Rows)
{
if (dr["Flag"] = null) // not (Modified or Added or Unchanged), there is no flag
{
dr["Flag"] = "Delete";
}
}
}以上, 对drs[0]的标记,其实就是对dtOld的相应行的标记
drs数组并没有开辟新内存,只是对原有数据行的引用
希望还有更好的方法!到期结贴!给出代码的都有分!
/// <summary>
/// 比较两表
/// </summary>
/// <param name="oldTable">老的版本</param>
/// <param name="newTable">新的版本</param>
/// <param name="primaryKeys">主键</param>
/// <returns>返回的结果中新增changed列标记结果</returns>
private static DataTable CompareDataTable(DataTable oldTable, DataTable newTable, params DataColumn[] primaryKeys)
{
DataTable result = newTable.Copy();
DataColumn[] tdc = new DataColumn[oldTable.Columns.Count];
for (int x = 0; x < oldTable.Columns.Count; x++)
{
tdc[x] = oldTable.Columns[x];
}
result.Columns.Add("changed"); oldTable.PrimaryKey = tdc;
oldTable.Columns.Add("changed");
DataRow dr = oldTable.NewRow();
for (int i = 0; i < newTable.Rows.Count; i++)
{
dr.ItemArray = newTable.Rows[i].ItemArray;
try
{
oldTable.Rows.Add(dr);
//注意:这里Remove以后dr的指针会跑没
oldTable.Rows.Remove(dr);
//因为前面的Remove使dr的指针跑掉了,所以要重新赋一次值
dr.ItemArray = newTable.Rows[i].ItemArray;
oldTable.PrimaryKey = primaryKeys;
try
{
oldTable.Rows.Add(dr);
result.Rows[i]["changed"] = "新增";
}
catch (ConstraintException)
{
result.Rows[i]["changed"] = "修改";
oldTable.Rows[i]["changed"] = "修改"; }
finally
{
oldTable.PrimaryKey = tdc;
}
}
catch (ConstraintException)
{ result.Rows[i]["changed"] = "没有改变";
oldTable.Rows[i]["changed"] = "没有改变";
}
}
foreach (DataRow rd in oldTable.Rows)
{
if (rd["changed"] == DBNull.Value)
{
rd["changed"] = "被删除的";
DataRow nr = result.NewRow();
nr.ItemArray = rd.ItemArray;
result.Rows.Add(nr);
}
}
return result;
}
首先在OLD和NEW表中分别增加TimeStamp字段,此字段内容由DB负责。
比较两表时,以NEW表为外循环,依照ID查找OLD表记录,找到再比较TimeStamp字段是否相同同时BREAK此次循环,
如果找不到则为新增。依次操作即可。
你的这种方法请以后不要考虑,try catch 并非是用来做验证的
比如你要判断一个字符串是否是数字,难道用try catch 来做转换
转换成功就是数字吗?
到其他地方搜索下try catch 的真正用途吧
private void CompareDataTable(DataTable dtOld, DataTable dtNew)
{
DataRow[] drS; //存放指向旧表相应行的指针
bool bAllTheSame; //存放某行数据是否有所变更的标志
foreach(DataRow dr in dtNew.Rows)
{
drS = dtOld.Select("ID =" + dr["ID"].ToString()); //检索旧表,看是否有对应行
if (drS.Length > 0) //旧表有对应行
{
bAllTheSame = true;
for (int i = 0; i < dtOld.Columns.Count; i++) //看是否某列的值被变更
{
if (dr[i].ToString().CompareTo(drS[0][i].ToString()) != 0) //有变更
{
bAllTheSame = false;
break;
}
}
if (bAllTheSame) //所有列未被变更
{
dr["Status"] = "UnChanged";
drS[0]["Status"] = "UnChanged";
}
else //有些列被变更
{
dr["Status"] = "Modified";
drS[0]["Status"] = "Modified";
}
}
else //旧表中无对应行
{
dr["Status"] = "Added";
}
}//至此,新表标志完毕,旧表只剩删除行未被标志 foreach (DataRow dr in dtOld.Rows)
{
if (dr["Status"].ToString().Length == 0) //旧表中此行数据未被标志
{
dr["Status"] = "Delete";
}
}//至此,旧表删除行标志完毕
}
/*再次解释:drS 数组不开辟新内存,因为是主键检索,所以drS数组只能最多有一条数据
并且修改drS[0]的某列的值,实质上就是修改了dtOld表中相应列的值 */