HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpModerate

Verify which columns have changed in a datatable or datarow

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
columnsdatatabledatarowverifywhichchangedhave

Problem

I was asked to update a business rule to allow a specific column to be added. Because our datalayer uses only DataSets as an interface to the database that is what we work with in the business layer.

Here I have created a couple of DataTable and DataRow extensions to use for this businessrule and I would like your opinion on things I might have missed.
This is the method I use to search for changes:

private static bool hasColumnChanged(StringComparison stringComparison, bool ignoreWhitespace, DataRow row, DataColumn col)
{
    bool isEqual = true;
    if (row[col, DataRowVersion.Original] != DBNull.Value && row[col, DataRowVersion.Current] != DBNull.Value)
    {
        if (ignoreWhitespace)
            isEqual = row[col, DataRowVersion.Original].ToString().Trim().Equals(row[col, DataRowVersion.Current].ToString().Trim(), stringComparison);
        else
            isEqual = row[col, DataRowVersion.Original].ToString().Equals(row[col, DataRowVersion.Current].ToString(), stringComparison);
    }
    else
        isEqual = row[col, DataRowVersion.Original].Equals(row[col, DataRowVersion.Current]);

    return !isEqual;
}


And these are simply the extensions using the code:

```
public static List GetChangedColumns(this DataTable table)
{
return table.GetChangedColumns(StringComparison.InvariantCultureIgnoreCase, false);
}
public static List GetChangedColumns(this DataTable table, bool ignoreWhitespace)
{
return table.GetChangedColumns(StringComparison.InvariantCultureIgnoreCase, ignoreWhitespace);
}
public static List GetChangedColumns(this DataTable table, StringComparison stringComparison, bool ignoreWhitespace)
{
if (table == null) throw new ArgumentNullException("table");

List columnsChanged = new List();
foreach (DataRow row in table.GetChanges().Rows)
{
foreach (DataColumn col in row.Table.Columns)
{
if (!columnsChanged.Contains(col) && hasColumnChanged(stringComparison, ignoreWhitespace, row, c

Solution

-
hasColumnChanged method. Inside first if you have two almost same lines. Duplicated code should be extracted:

if (row[col, DataRowVersion.Original] != DBNull.Value && row[col, DataRowVersion.Current] != DBNull.Value)  
{  
    string originalVersionToCompare = row[col, DataRowVersion.Original].ToString();
    string currentVersionToCompare = row[col, DataRowVersion.Current].ToString();
    if (ignoreWhitespace)
    {
        originalVersionToCompare = originalVersionToCompare.Trim();
        currentVersionToCompare = currentVersionToCompare.Trim();
    }
    isEqual = originalVersionToCompare.Equals(currentVersionToCompare, stringComparison);
}


-
If you have .Net 4.0 then 6 GetChangedColumns methods I would refactor into 2 with optional parameters.

-
foreach inside GetChangedColumns for DataRow looks like a copypaste. I cannot imagine a situation when columnsChanged.Contains(col) will be true in this method.

-
hasColumnChanged seems to be named incorrectly. It should be hasCellChanged since it checks for intersection of row and column. Maybe also PascalCase?

-
LINQify it!

Original:

List columnsChanged = new List();
foreach (DataRow row in table.GetChanges().Rows)
{
    foreach (DataColumn col in row.Table.Columns)
    {
        if (!columnsChanged.Contains(col) && hasColumnChanged(stringComparison, ignoreWhitespace, row, col))
            columnsChanged.Add(col);
    }
}
return columnsChanged;


Result:

return table.GetChanges().Rows.Cast()
    .SelectMany(dr => table.Columns.Cast(), (row, column) => new {row, column})
    .Where(c => hasColumnChanged(stringComparison, ignoreWhitespace, c.row, c.column))
    .Select(c => c.column)
    .Distinct()
    .ToList();


-
DateUntill - double l?

-
Why do you compare items by casting them to string? Why don't you compare them as objects?

Code Snippets

if (row[col, DataRowVersion.Original] != DBNull.Value && row[col, DataRowVersion.Current] != DBNull.Value)  
{  
    string originalVersionToCompare = row[col, DataRowVersion.Original].ToString();
    string currentVersionToCompare = row[col, DataRowVersion.Current].ToString();
    if (ignoreWhitespace)
    {
        originalVersionToCompare = originalVersionToCompare.Trim();
        currentVersionToCompare = currentVersionToCompare.Trim();
    }
    isEqual = originalVersionToCompare.Equals(currentVersionToCompare, stringComparison);
}
List<DataColumn> columnsChanged = new List<DataColumn>();
foreach (DataRow row in table.GetChanges().Rows)
{
    foreach (DataColumn col in row.Table.Columns)
    {
        if (!columnsChanged.Contains(col) && hasColumnChanged(stringComparison, ignoreWhitespace, row, col))
            columnsChanged.Add(col);
    }
}
return columnsChanged;
return table.GetChanges().Rows.Cast<DataRow>()
    .SelectMany(dr => table.Columns.Cast<DataColumn>(), (row, column) => new {row, column})
    .Where(c => hasColumnChanged(stringComparison, ignoreWhitespace, c.row, c.column))
    .Select(c => c.column)
    .Distinct()
    .ToList();

Context

StackExchange Code Review Q#1319, answer score: 13

Revisions (0)

No revisions yet.