问题描述
有两张DataTable结构一样,其中的数据有差异!publicDataTableCompare(DataTableverNew,DataTableverOld)表有主键比较后的结果需要标记出是新增的,修改的,删除的!
解决方案
解决方案二:
一行行比较了,你不是有主键的啊1、遍历其中旧表,取出当前行主键,然后在另一张表中找,如果找到就再比较内容是不是一样的,如果没找到就说明删掉了2、然后用上面的方法遍历新表,每一行与旧表的比,如果发现找不到的,则说明是新增的,此时不用再比较内容了,因为前面已经比较过了!比较SB的办法,我也等等看有没有更好的办法!
解决方案三:
字段很多给出点具体的东西!最好是带注释的代码!//找出verNew的关键值到verOld中去匹配//找不到该条新增标记//找到并一致该条未做任何操作标记//找到不一致该条为修改标记//就版本有未标记的内容为被删除内容
解决方案四:
单就比较两个表的数据的话是没有太好算法不知道楼主是要处理什么样的业务?一般在比较或是同步数据的时候,我想应该有一个表作为参考,如果有更新的话做出标记,或是满足一定的条件,只比较更新的数据(更新:增删改)
解决方案五:
的确如此,如果真的是两个结构相同的表,只能逐行比较但是如果只是某个表(dtOld)的数据变化了而你想获得某些变化,那么请用GetChanges方法DataTabledtNew=dtOld.GetChanges(DataRowState.Added);DataTabledtNew=dtOld.GetChanges(DataRowState.Deleted);DataTabledtNew=dtOld.GetChanges(DataRowState.Detached);DataTabledtNew=dtOld.GetChanges(DataRowState.Modified);DataTabledtNew=dtOld.GetChanges(DataRowState.Unchanged);
解决方案六:
如果硬是要这么操作的话,那只能一行行遍历并进行比较了
解决方案七:
publicDataTableCompare(DataTableverNew,DataTableverOld){for(intiRows=0;iRwos<verOld.Rows.Count;iRows++){DataRow[]drs=verNew.Select("verOld.关键字="+verOld.Rows[iRows]["verNew.关键字"].ToString());if(drs!=null){//匹配关键字成功for(intiItems;iItems<drs.Length;iItems++){//TODO一个字段一个字段比较罗}}else{//匹配关键字失败//TODO:为新增标记}}//TODO:没有标识就删除}
解决方案八:
我用winform做了个小程序,希望对你有帮助DataTableoldTable=newDataTable();DataTablenewTable=newDataTable();privatevoidForm1_Load(objectsender,EventArgse){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));}privatestringdataTableCompare(DataTableoldTable,DataTablenewTable){oldTable.PrimaryKey=newDataColumn[]{oldTable.Columns["Id"],oldTable.Columns["Name"]};stringret=string.Empty;DataRowdr=oldTable.NewRow();for(inti=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=newDataColumn[]{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=newDataColumn[]{oldTable.Columns["Id"],oldTable.Columns["Name"]};}}catch{ret+=string.Format("新表中的第{0}行是没有修改过的n",i.ToString());}}returnret;}
解决方案九:
说明一下,上面代码中Id是主键列,我忘了设,这种方法效率较高,因为不是采用手工比较而是尝试将新行加入旧表中,从加入的结果进行判断
解决方案十:
有创意
解决方案十一:
不错参考!
解决方案十二:
还有删除哦!!
解决方案十三:
To:cpw999cn没细看但是for里套trytry里套try以catch获得结果等等,太耗费系统资源,如非必要(一般不需要),不要这样做
解决方案十四:
To:heboyi删除是判断不出来的,旧表中删除的,新表中有旧表中没有的,对于旧表来说就是新增的,无法判断旧表原来是否有该记录(我想你需要做这种比较就表明你不是直接对旧表的datatable进行操作,否则用不着这样做比较)
解决方案十五:
不好意思,非中文系统,拿写字板写的publicDataTableCompare(DataTabledtNew,DataTabledtOld){foreach(DataRowdrindtNew.Rows){DataRow[]drs=dtOld.Select("PrimaryKey="+dr["PrimaryKey"].ToString());if(drs!=null)//canmatch,andthereisonlyonerowindrs{//compareeverycolumnfor(inti=0;i<dtNew.columns.count;i++){drs[0]=dr[i]?}//ifallthecolumnsisthesamedr["Flag"]="Unchanged";drs[0]["Flag"]="Unchanged";//ifallthecolumnsisnotthesamedr["Flag"]="Modified";drs[0]["Flag"]="Modified";}else//can'tmatch{dr["Flag"]="Added";}}foreach(DataRowdrindtOld.Rows){if(dr["Flag"]=null)//not(ModifiedorAddedorUnchanged),thereisnoflag{dr["Flag"]="Delete";}}}以上,对drs[0]的标记,其实就是对dtOld的相应行的标记drs数组并没有开辟新内存,只是对原有数据行的引用
解决方案:
已经解决了!希望还有更好的方法!到期结贴!给出代码的都有分!///<summary>///比较两表///</summary>///<paramname="oldTable">老的版本</param>///<paramname="newTable">新的版本</param>///<paramname="primaryKeys">主键</param>///<returns>返回的结果中新增changed列标记结果</returns>privatestaticDataTableCompareDataTable(DataTableoldTable,DataTablenewTable,paramsDataColumn[]primaryKeys){DataTableresult=newTable.Copy();DataColumn[]tdc=newDataColumn[oldTable.Columns.Count];for(intx=0;x<oldTable.Columns.Count;x++){tdc[x]=oldTable.Columns[x];}result.Columns.Add("changed");oldTable.PrimaryKey=tdc;oldTable.Columns.Add("changed");DataRowdr=oldTable.NewRow();for(inti=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(DataRowrdinoldTable.Rows){if(rd["changed"]==DBNull.Value){rd["changed"]="被删除的";DataRownr=result.NewRow();nr.ItemArray=rd.ItemArray;result.Rows.Add(nr);}}returnresult;}
解决方案:
学习-----打倒小日本
解决方案:
给LZ说说我以前作的思想:首先在OLD和NEW表中分别增加TimeStamp字段,此字段内容由DB负责。比较两表时,以NEW表为外循环,依照ID查找OLD表记录,找到再比较TimeStamp字段是否相同同时BREAK此次循环,如果找不到则为新增。依次操作即可。
解决方案:
Toheboyi:你的这种方法请以后不要考虑,trycatch并非是用来做验证的比如你要判断一个字符串是否是数字,难道用trycatch来做转换转换成功就是数字吗?到其他地方搜索下trycatch的真正用途吧privatevoidCompareDataTable(DataTabledtOld,DataTabledtNew){DataRow[]drS;//存放指向旧表相应行的指针boolbAllTheSame;//存放某行数据是否有所变更的标志foreach(DataRowdrindtNew.Rows){drS=dtOld.Select("ID="+dr["ID"].ToString());//检索旧表,看是否有对应行if(drS.Length>0)//旧表有对应行{bAllTheSame=true;for(inti=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(DataRowdrindtOld.Rows){if(dr["Status"].ToString().Length==0)//旧表中此行数据未被标志{dr["Status"]="Delete";}}//至此,旧表删除行标志完毕}
/*再次解释:drS数组不开辟新内存,因为是主键检索,所以drS数组只能最多有一条数据并且修改drS[0]的某列的值,实质上就是修改了dtOld表中相应列的值*/