比较两个不包括某些列的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;
}

比较两个不包括某些列的datarow

您必须遍历列以进行比较。代码中的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]));
        });
}

可能会有一些微优化,但我认为无论如何你都必须检查每一列