patterncsharpModerate
Verify which columns have changed in a datatable or datarow
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
This is the method I use to search for changes:
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
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
-
-
If you have .Net 4.0 then 6
-
-
-
LINQify it!
Original:
Result:
-
-
Why do you compare items by casting them to string? Why don't you compare them as objects?
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.