 Language: VB.NET Version 1.11 Task:Create a tool like SQL-Query analyzer that returns result in a grid. Problem: The data grid does not always display data! ds.tables("searchResults").clear() 'Custom function that uses a SQLDataAdapter to fill the datatable with results of the query fillBrowseSet(Me.query.Text.Trim, searchDT) datagrid1.datasource = ds.tables("searchResults") This works fine the first time. DataTable is filled and datagrid1 displays the result. The following request display a blank grid with no data, but correct column
Solution 1 Replace, ds.tables("searchResults").clear() with ds.tables("searchResults").reset() Then, bind the datagrid with the DataTable.
Problem with solution 1: If underlying schema of the datatable keeps changing, the data may appear, but all column may not appear correctly. This is usually due to the underlying contraint collection and the primary key collection bindings.
Explaination: datagrid1.datasource = ds.tables("searchResults") AND datagrid1.datasource = ds.tables("searchResults").DefaulView
Both are effectively the same statements. datagrid1.datasource = ds.tables("searchResults") implicitly uses the dataview generated for the datatable, and datagrid1.datasource = ds.tables("searchResults").DefaulView explicitly points to the dataview to bind. The point is, DataSource property of the datagrid uses a DataView object to establish mapping on the datagrid column(s) with columns and data stored in the DataTable object.
The DefaultView property of the DataTable is a ReadOnly property that points to an immutable object. Every DataTable object has exactly one DataView object created for it. This DataView object is created during the construction of the DataTable object. This DataView object is therefore based on the underlying schema of the DataTable object at that time. The problem is, when the underlying schema of the DataTable changes, the associated DataView object is not automatically notified of the change, and is not re-Synchronized. So, the result is a disconnected DataView that is unable to provide a current binding to the DataGrid object.
You can test these findings using the debugger and checking the TableName and Count properties of both the DataView and DataTable. You will notice, the two will contain the same values initially. The defaul DataView object will be reset upon disconnect and display a Count of 0 (zero).
My Solution 'Eliminate the use of a large and bulky DataSet object. Private searchDT As DataTable Private searchView As New DataView
searchDT = New DataTable("searchResult") searchView.AllowDelete = False searchView.AllowEdit = False searchView.AllowNew = False
searchDT.Reset() 'The DataView object being used is no longer immutable, and can be manipulated If Not searchView.Table Is Nothing Then searchView.Table = Nothing End If fillBrowseSet(Me.query.Text.Trim, searchDT, False) 'Attach the dataview to refreshed DataTable object. 'This refreshes the DataView searchView.Table = searchDT Me.resultGrid.SetDataBinding(searchView, "")
Advantages to this Technique: 1) We do not find the need to create a new DataView object for every new schema of DataTable 2) We avoid the use of a bulky DataSet object, and minimize cost associate with processing and boxing/un-boxing DataSet object. An independant DataTable object is enough for our purposes 3) We have control of the DataView object contained by the DataTable. searchView.Table = searchDT sets the new dataview object accessible by DefaultView property of DataTable |
Comments on "ReUsing DataTable with DataGrid"
post a comment