Thursday, December 18, 2008

ADO.Net to create unique DataTable values

The application I'm building uses a .NET BLL referenced by Flex to build views. I've come upon a situation where a series of table queries creates a duplicate list of what are unique values. This throws an error from .NET. The layer queries generate column values that begin as non-unique and become unique upon subsequent table queries.

I have been looking into solutions to update my BLL to remove duplicates of the offending column before the subsequent queries. Initially, as late as 2005, developers suggested writing a custom routine to do this. Here is one written in VB from Julie Lerman:

(note - the int32_key is in there as a reminder in case I need to create another one for non-int keys)

Public Function DistinctRows_Int32_Key(ByVal dt As DataTable, ByVal keyfield As String) As DataTable
Dim newTable As DataTable = dt.Clone
Dim keyval As Int32 = 0
Dim dv As DataView = dt.DefaultView
dv.Sort = keyfield
If dt.Rows.Count > 0 Then
For Each dr As DataRow In dt.Rows
If Not dr.Item(keyfield) = keyval Then
newTable.ImportRow(dr)
keyval = dr.Item(keyfield)
End If
Next
Else
newTable = dt.Clone
End If
Return newTable
End Function


It has since been shoehorned into an ADO.NET 2.0 method called ToTable that works thus:


ADO.Net 2.0 prevents this difficulty by exposing method called DataView.ToTable() with 4 overloads.

DataView.ToTable ()
Creates and returns a new DataTable based on rows in an existing DataView.

DataView.ToTable (String)
Creates and returns a new DataTable based on rows in an existing DataView.

DataView.ToTable (Boolean, String[])
Creates and returns a new DataTable based on rows in an existing DataView.

DataView.ToTable (String, Boolean, String[])
Creates and returns a new DataTable based on rows in an existing DataView.


This is an improvement over writing a custom routine. The hitch is getting the resultant table back to the correct datatype in order to call the row values by name. Here's my solution:

DataView tempView = stronglyTypedTableInstance.DefaultView;

stronglyTypedTableInstance = (StronglyTypedDataTable)(StronglyTypedTableInstance.DefaultView.ToTable(true, "name"));

foreach (StronglyTypedRow stronglyTypedRowInstance in stronglyTypedTableInstance)
{
runLogic...
}
return newlyBuiltTable;


And so on and so forth.

No comments: