Monday, March 30, 2009

DataView sorting issue on new record inserted

1. Scenario:
I was working on a project of feeding live data to a datagrid view (dgv) with just-in-time data loading. The dgv is populated from a datatable.DefaultView and should sort by the latest updates.

The screen data is cached and loaded from the underlying datatable when the user scrolls down the dgv. The gridview doesn't have to load 500,000 records when it initialise. Thus, greatly reducing the memory footprint and waiting time.

MSDN: Just-In-Time Data Loading in DataGridView Control

The gridview refreshes itself when new data arrives. The user sees the latest record appearing on top of the gridview.

## Code snippet (Starts)-----------------------------------------------------

DataView _latestPriceView = _dtPrices.DefaultView;
_latestPriceView.Sort = "PriceUID DESC"

// obtain the latest price unique-id and perform further processing
uid = (_latestPriceView.Table.Rows(0).Item(0))

## Code snippet (Ends)-----------------------------------------------------



2. What is the problem:

The issue happens new price arrives. It has been added to the bottom of dtPrices datatable. The dataview that build from the datatable should have sorted the latest record to the top. However, it hasn't and the row is at the bottom of the dataview rows.

What is going on here?

3. Mitigation:

The reason is dataTable is not sorted but DataView is. Finding the top element from dataview gives you the latest uid. Performing that on the unsorted datatable give you latest uid since it was retreive from data source. The latest record is at the bottom of the datatable.

Do not use the DataView.Table. Rows[0]. Reference the dataview item directly without using the table properties.

e.g.
DataView[i].Item[0]


## Code snippet (Starts)-----------------------------------------------------

DataView _latestPriceView = _dtPrices.DefaultView;
_latestPriceView.Sort = "[PriceUID] DESC"

// obtain the latest price unique-id (normally the first row from the dataview rows)
// Perform further processing
...
int32 uid = _latestPriceView(0).Item(0) // direct referencing to the view item does the trick.

If you try to use
int32 uid2 = _lastestPriceView.Table.Rows[0].Item[0] // This correspong to the datatable first row [
_dtPrices(0)] rather than the last update which is inserted at the bottom of the datatable -> _dtPrices.Rows[_dtPrices.Rows.Count-1].Item[0]


## Code snippet (Ends)-----------------------------------------------------

No comments: