Robinson
Robinson

Reputation: 10122

Finding the difference between two DataTables

So, I have a tree view, some rows of which come from a DataTable. When I fetch the data table, I want to update the tree with the following basic rules:

To that end I have a dictionary, hashing a Guid (primary key in the DataTable) to a tree node:

Dictionary<Guid, NoteNode> MyHashNoteToNode;

, where NoteNode is derived from TreeNode, with the addition of a LastEdit DateTime field. So far, so banal.

In order to find the 3 sets representing the difference between the tree and the DataTable, I wrote the code below. I would love to hear there's a really simple Linq query that will return the 3 sets (Insert, Edit, Delete), or something concise that will do it for me, perhaps a method I'm missing somewhere. Or is this pretty much optimal?

// Find all items that need inserting.
List<DataRow> toInsert = new List<DataRow>();
foreach (DataRow row in MyNotes.Rows)
{
    NoteNode node = null;
    MyHashNoteToNode.TryGetValue((Guid)row["ID"], out node);
    if(node == null)
    {
        toInsert.Add(row);
    }
}

// Find all items that need editing/changing.
List<DataRow> toEdit = new List<DataRow>();
foreach (DataRow row in MyNotes.Rows)
{
    NoteNode node = null;
    MyHashNoteToNode.TryGetValue((Guid)row["ID"], out node);
    if(node != null)
    {                
        if((DateTime)row["Edited"] != node.LastEdit)
        {
            toEdit.Add(row);
        }
    }
}

// Find all items that need deleting.
List<NoteNode> toDelete = new List<NoteNode>();
foreach (NoteNode node in MyHashNoteToNode.Values)
{
    if (!MyNotes.Rows.Contains(node.Key))
    {
        toDelete.Add(node);
    }
}

}

Upvotes: 1

Views: 1049

Answers (1)

Jodrell
Jodrell

Reputation: 35716

A simple way to make your dictionary from a DataTable is,

DataSet newData;
DataSet existingData;

var before = existingData.AsEnumerable().ToDictionary(
    n => Guid.Parse(n.Field<string>("ID")),
    n => n);

var after = newData.AsEnumerable().ToDictionary(
    n => Guid.Parse(n.Field<string>("ID")),
    n => n);

To find the keys that need work,

var keysToInsert = after.Select(p => p.Key).Except(before.Select(p => p.Key));
var keysToDelete = before.Select(p => p.Key).Except(after.Select(p => p.Key));
var keysTheSame = before.Select(p => p.Key).Intersect(after.Select(p => p.Key));

To find the rows that need work,

var nodesToInsert = keysToInsert.Select(k => after[k]);

var nodesToDelete = keysToDelete.Select(k => before[k]);

var nodesThatNeedUpdates = keysTheSame
    .Where(k => 
        before[k].Field<DateTime>("Edited") !=
        after[k].Field<DateTime>("Edited"))
    .Select(k => after[k]);

Upvotes: 1

Related Questions