比较两个不包括某些列的datarow
本文关键字:datarow 不包括 两个 比较 | 更新日期: 2023-09-27 18:02:44
我有两个数据表,例如OriginalEntity和Entity。接口应用程序修改实体数据表的行。在保存时,我想检查被修改或不同于originanlentity的DataRows。但是,我还需要排除几个字段,同时比较例如修改日期和其他审计字段。目前,我正在循环遍历数据表的每一行,如下所示:
List<string> auditFields = new List<string>(){"createdon","modifiedon"};
string IdentityKeyName = "id";
object ent,orgEnt;
foreach(string columnName in columnList) // ColumnList is List of columns available in datatable
{
foreach(DataRow dr in Entity.Rows)
{
ent = dr[columnName];
orgEnt = OriginalEntity.Select(IdentityKeyName + " = " + dr[IdentityKeyName].ToString())[0][columnName];
if(!ent.Equals(orgEnt) && !auditFields.Contains(columnName))
{
isModified = true;
break;
}
}
}
我只是想要一个有效的方法来实现以上。请建议。
感谢大家的建议,这是我的(因为我没有主键定义)
解决方案:
public bool isModified(DataTable dt1, DataTable dt2, string IdentityKeyName)
{
bool isModified = false;
List<string> auditFields = new List<string>() { "createdon", "modifiedon" };
isModified = isModified || (dt1.Rows.Count != dt2.Rows.Count);
if(!isModified)
{
//Approach takes 150 ms to compare two datatable of 10000 rows and 24 columns each
DataTable copyOriginalEntity = dt1.Copy();
DataTable copyEntity = dt2.Copy();
//Exclude field you don't want in your comparison -- It was my main task
foreach(string column in auditFields)
{
copyOriginalEntity.Columns.Remove(column);
copyEntity.Columns.Remove(column);
}
for(int i=0;i<copyOriginalEntity.Rows.Count;i++)
{
var origItems = copyOriginalEntity.Rows[i].ItemArray;
var entityItem = copyEntity.Select(IdentityKeyName + " = " + copyOriginalEntity.Rows[i][dentityKeyName].ToString())[0].ItemArray;
if(string.Concat(origItems) != string.Concat(entityItem)){ isModified = true; break; }
}
}
return isModified;
}
您必须遍历列以进行比较。代码中的compare ent.Equals(orgEnt)比较对象引用是否相同。这似乎不是你想要的,你想比较值。
public bool IsChanged(DataTable original, DataTable source, string idKeyName, params string[] ignoreColumns)
{
// make sure "key" column exist in both
if (!original.Columns.Contains(idKeyName) || !source.Columns.Contains(idKeyName))
{
throw new MissingPrimaryKeyException("Primary key column not found.");
}
// if source rows are not the same as original then something was deleted or added
if (source.Rows.Count != original.Rows.Count)
{
return false;
}
// Get a list of columns ignoring passed in and key (key will have to be equal to find)
var originalColumns =
original.Columns.Cast<DataColumn>()
.Select(c => c.ColumnName)
.Where(n => !ignoreColumns.Contains(n) && n != idKeyName)
.ToArray();
// check to make sure same column count otherwise just fail no need to check
var sourceColumnsCount =
source.Columns.Cast<DataColumn>()
.Select(c => c.ColumnName).Count(originalColumns.Contains);
if (originalColumns.Length != sourceColumnsCount)
{
return false;
}
//Switch to linq
var sourceRows = source.AsEnumerable();
return sourceRows.All(sourceRow =>
{
// use select since not real key
var originalCheck = original.Select(idKeyName + " = " + sourceRow[idKeyName]);
if (originalCheck.Length != 1)
{
// Couldn't find key or multiple matches
return false;
}
var originalRow = originalCheck.First();
//Since using same array we can use linq's SequenceEqual to compare for us
return
originalColumns.Select(oc => sourceRow[oc])
.SequenceEqual(originalColumns.Select(oc => originalRow[oc]));
});
}
可能会有一些微优化,但我认为无论如何你都必须检查每一列