条件:若每个表的数据都按主键排序则可:双重循环遍历比对,比对时有个算法优化,即第二个表的循环开始条件并非每次都从0开始,而是从上次已走到的地方继续往下走我写过这样的方法,贴出来给你看看吧 /// <summary> /// 此方法比对数据提供方的源数据表与数据申请方的关键数据表,并将三种结果(insert,update,delete)序列化为字节流返回 /// </summary> /// <param name="dtSource">源数据表</param> /// <param name="dtClientKey">关键数据表</param> /// <param name="crType">比对的类型</param> /// <returns>比对结果的字节流</returns> public MemoryStream GetSYNCCompareResultStream(DataTable dtSource, DataTable dtClientKey, CompareResultType crType) { //if (dtSource.TableName != dtClientKey.TableName) { throw new Exception("不同的表请不要拿来比对!"); } //表结构信息以本地表名为准 ColumnsInfoTable cit = GetSYNCDataTableInfo(dtSource.TableName); MemoryStream ms = new MemoryStream(); RawSerializer rs = new RawSerializer(ms); //返回的表名以客户表名为准 rs.Serialize(dtClientKey.TableName); //记录需要Insert的新数据 List<int> listInsert = new List<int>(); //记录需要Update的新数据及哪些列需要Update DataTable dtUpdate = InitDataTableForUpdate(cit); //记录需要Delete的行的PrimaryKey值项 bool[] isNeedDeleteRows = null; if (dtSource.Rows.Count > 0 && dtClientKey.Rows.Count > 0) { int nNeedDeleteCount = dtClientKey.Rows.Count; isNeedDeleteRows = new bool[dtClientKey.Rows.Count]; for (int i = 0; i < isNeedDeleteRows.Length; i++) { isNeedDeleteRows[i] = true; } #region 比对两个表的一般逻辑 //比对两个表的逻辑开始 bool bFound = false; bool bFit = false; int nFitIndex = -1; DataRow drUpdate = null; for (int i = 0; i < dtSource.Rows.Count; i++) { bFound = false; //注意:因为两个表都是按照Key项递增查询的,此循环才可以优化 for (int j = nFitIndex + 1; j < dtClientKey.Rows.Count; j++) { //判断Key列的值是否相等 bFit = true; foreach (int n in cit.KeyColumns) { if (dtSource.Rows[i][n].Equals(dtClientKey.Rows[j][n]) == false) { bFit = false; break; } } if (bFit == true) { nFitIndex = j; bFound = true; //如果dt2中的数据能与dt1中的匹配上,则不须删除 isNeedDeleteRows[j] = false; nNeedDeleteCount--; //判断是否需要Update,如果需要,则把相应的值填入dtUpdate中 int nColumns = cit.Rows.Count; bool isRowNeedUpdate = false; if (drUpdate == null) { drUpdate = dtUpdate.NewRow(); } int n; for (int k = 0; k < cit.SmallItemColumns.Length; k++) { n = cit.SmallItemColumns[k]; if (dtSource.Rows[i][n].Equals(dtClientKey.Rows[j][n]) == true) { drUpdate[n] = DBNull.Value; drUpdate[nColumns + n] = false; } else { isRowNeedUpdate = true; drUpdate[n] = dtSource.Rows[i][n]; drUpdate[nColumns + n] = true; } } if (cit.BLOBColumns != null && cit.BLOBColumns.Length > 0) { for (int k = 0; k < cit.BLOBColumns.Length; k++) { n = cit.BLOBColumns[k]; //比对的是BLOB的MD5列 if (dtSource.Rows[i][nColumns + k].Equals(dtClientKey.Rows[j][nColumns + k]) == true) { drUpdate[n] = DBNull.Value; drUpdate[nColumns + n] = false; } else { isRowNeedUpdate = true; drUpdate[n] = dtSource.Rows[i][n]; drUpdate[nColumns + n] = true; } } } if (isRowNeedUpdate == true) { foreach (int row in cit.KeyColumns) { drUpdate[row] = dtClientKey.Rows[j][row]; drUpdate[row + nColumns] = false; } dtUpdate.Rows.Add(drUpdate); drUpdate = null; } break; } } //未找到匹配项,说明此值需要新增 if (bFound == false) { listInsert.Add(i); } } #endregion //比对的一般逻辑结束,开始序列化 #region 将比对结果序列化为字节流 //省略 #endregion } #region 特殊情况的处理,全空,全删,全增 else if (dtSource.Rows.Count == 0 && dtClientKey.Rows.Count == 0) { //无需任何改变,两个都是空表 } else if (dtSource.Rows.Count == 0) { //全部需要删除,其他两项无需更改 } else { //全部需要新增,其他两项无需更改 } #endregion return ms; }
有两个结构完全一样的datatable,怎么才能比较出来哪些行的数据不一样 你的问题还需要你给解释一下:怎么才算是"数据不一样",是任何A记录!=B记录的都算?还是主键相同而其它列不同的算数据不一样呢? (列a为主键) A a, b, c B a, b, c 如果是前者 只能循环遍历了如果是后者 select A.a, A.b, A.c from A,B where (A.a = B.a) and (A.b != B.b or A.c != b.c) B表的查询也一样
DataTable A, B; int rows = A.Rows.Count; int cols = A.Columns.Count; for(int i=0; i< rows; i++) { for (int j=0; j< cols; j++) { if (A.Rows[i][j].ToString() != B.Rows[i][j]) { // break; } } }
如果设定了,先按照关键字排序,然后再依次比较。
1。merge.然后再根据datarow的状态,取得变化。
2。两个datatable分别遍历还有人说两个datatable建立关联。
第二个办法虽然很保险,但是有点迟钝。
第一个办法不知道保险不保险
第三个办法不会用。
正规的办法是哪个?
merge只能是DATASET吧,DATATABLE可以merge?
不过merge倒是个方法,但是表必须要有关键字。。要不没发判断数据是否一样。。
没有关键字,merge的话之是在把2个表叠加而已
/// <summary>
/// 此方法比对数据提供方的源数据表与数据申请方的关键数据表,并将三种结果(insert,update,delete)序列化为字节流返回
/// </summary>
/// <param name="dtSource">源数据表</param>
/// <param name="dtClientKey">关键数据表</param>
/// <param name="crType">比对的类型</param>
/// <returns>比对结果的字节流</returns>
public MemoryStream GetSYNCCompareResultStream(DataTable dtSource, DataTable dtClientKey, CompareResultType crType)
{
//if (dtSource.TableName != dtClientKey.TableName) { throw new Exception("不同的表请不要拿来比对!"); }
//表结构信息以本地表名为准
ColumnsInfoTable cit = GetSYNCDataTableInfo(dtSource.TableName); MemoryStream ms = new MemoryStream();
RawSerializer rs = new RawSerializer(ms);
//返回的表名以客户表名为准
rs.Serialize(dtClientKey.TableName);
//记录需要Insert的新数据
List<int> listInsert = new List<int>();
//记录需要Update的新数据及哪些列需要Update
DataTable dtUpdate = InitDataTableForUpdate(cit);
//记录需要Delete的行的PrimaryKey值项
bool[] isNeedDeleteRows = null; if (dtSource.Rows.Count > 0 && dtClientKey.Rows.Count > 0)
{
int nNeedDeleteCount = dtClientKey.Rows.Count;
isNeedDeleteRows = new bool[dtClientKey.Rows.Count];
for (int i = 0; i < isNeedDeleteRows.Length; i++)
{
isNeedDeleteRows[i] = true;
} #region 比对两个表的一般逻辑 //比对两个表的逻辑开始
bool bFound = false;
bool bFit = false;
int nFitIndex = -1;
DataRow drUpdate = null;
for (int i = 0; i < dtSource.Rows.Count; i++)
{
bFound = false;
//注意:因为两个表都是按照Key项递增查询的,此循环才可以优化
for (int j = nFitIndex + 1; j < dtClientKey.Rows.Count; j++)
{
//判断Key列的值是否相等
bFit = true;
foreach (int n in cit.KeyColumns)
{
if (dtSource.Rows[i][n].Equals(dtClientKey.Rows[j][n]) == false)
{
bFit = false;
break;
}
} if (bFit == true)
{
nFitIndex = j;
bFound = true;
//如果dt2中的数据能与dt1中的匹配上,则不须删除
isNeedDeleteRows[j] = false;
nNeedDeleteCount--;
//判断是否需要Update,如果需要,则把相应的值填入dtUpdate中
int nColumns = cit.Rows.Count;
bool isRowNeedUpdate = false;
if (drUpdate == null) { drUpdate = dtUpdate.NewRow(); } int n;
for (int k = 0; k < cit.SmallItemColumns.Length; k++)
{
n = cit.SmallItemColumns[k];
if (dtSource.Rows[i][n].Equals(dtClientKey.Rows[j][n]) == true)
{
drUpdate[n] = DBNull.Value;
drUpdate[nColumns + n] = false;
}
else
{
isRowNeedUpdate = true;
drUpdate[n] = dtSource.Rows[i][n];
drUpdate[nColumns + n] = true;
}
} if (cit.BLOBColumns != null && cit.BLOBColumns.Length > 0)
{
for (int k = 0; k < cit.BLOBColumns.Length; k++)
{
n = cit.BLOBColumns[k]; //比对的是BLOB的MD5列
if (dtSource.Rows[i][nColumns + k].Equals(dtClientKey.Rows[j][nColumns + k]) == true)
{
drUpdate[n] = DBNull.Value;
drUpdate[nColumns + n] = false;
}
else
{
isRowNeedUpdate = true;
drUpdate[n] = dtSource.Rows[i][n];
drUpdate[nColumns + n] = true;
}
}
} if (isRowNeedUpdate == true)
{
foreach (int row in cit.KeyColumns)
{
drUpdate[row] = dtClientKey.Rows[j][row];
drUpdate[row + nColumns] = false;
}
dtUpdate.Rows.Add(drUpdate);
drUpdate = null;
}
break;
}
}
//未找到匹配项,说明此值需要新增
if (bFound == false)
{
listInsert.Add(i);
}
}
#endregion //比对的一般逻辑结束,开始序列化 #region 将比对结果序列化为字节流
//省略
#endregion
}
#region 特殊情况的处理,全空,全删,全增
else if (dtSource.Rows.Count == 0 && dtClientKey.Rows.Count == 0)
{
//无需任何改变,两个都是空表
}
else if (dtSource.Rows.Count == 0)
{
//全部需要删除,其他两项无需更改
}
else
{
//全部需要新增,其他两项无需更改
}
#endregion return ms;
}
你的问题还需要你给解释一下:怎么才算是"数据不一样",是任何A记录!=B记录的都算?还是主键相同而其它列不同的算数据不一样呢?
(列a为主键)
A
a, b, c
B
a, b, c
如果是前者
只能循环遍历了如果是后者
select A.a, A.b, A.c
from A,B
where (A.a = B.a) and (A.b != B.b or A.c != b.c)
B表的查询也一样
int rows = A.Rows.Count;
int cols = A.Columns.Count;
for(int i=0; i< rows; i++)
{
for (int j=0; j< cols; j++)
{
if (A.Rows[i][j].ToString() != B.Rows[i][j])
{
//
break;
}
}
}