1

I have a windows form app with a DataGridView populated by a TableAdapter. I'm using the Fill method to update the data for the UI in a looping Async sub like so.

Private Async Sub updateUI()
    Dim sw As New Stopwatch
    While True
        Await Task.Delay(3000)
        sw.Restart()
        myTableAdapter.Fill(getDataWithMySQL())
        'myTableAdapter.Fill(myDataSet.myTable)
        logger.Debug(sw.ElapsedMilliseconds)
    End While
End Sub

The getDataWithMySQL function is as follows:

Private Function getDataWithMySQL() As myDataSet.myDataTable
    Dim connStr As String = My.Settings.myConnectionString
    Dim sql As String = "SELECT ... LEFT JOIN ..."
    Dim dt As New myDataSet.myDataTable
    Using conn As New MySqlConnection(connStr)
        Using cmd As New MySqlCommand()
            With cmd
                .CommandText = sql
                .Connection = conn
            End With
            Try
                conn.Open()
                Dim sqladapter As New MySqlDataAdapter(cmd)
                sqladapter.Fill(dt)

            Catch ex As MySqlException
                MsgBox(ex.Message)
            End Try
        End Using
    End Using
    Return dt
End Function

myTableAdapter.Fill(myDataSet.myTable) works fine but performs poorly whereas myTableAdapter.Fill(getDataWithMySQL()) performs better as reported in my as yet unanswered question here.

For some reason, myTableAdapter.Fill(getDataWithMySQL()) does not work any more. It doesn't throw an error and dt is populated with the correct data but the DataGridView is not updating. It has worked previously and I don't think I've changed anything that would affect this. Any ideas why the DataGridView is not updating?

Community
  • 1
  • 1
doovers
  • 8,545
  • 10
  • 42
  • 70
  • What's the `DataGridView.DataSource` property set to? Make sure it's set to your DataTable. – ShawnOrr Feb 17 '15 at 19:07
  • @Supersnake It's set to the datatable bindingsource. – doovers Feb 17 '15 at 23:13
  • Have you set your TableAdapter's ClearBeforeFill property to true? –  Feb 20 '15 at 12:21
  • You can also try to call dataGridViewInstance.Refresh()... –  Feb 20 '15 at 12:28
  • @NeillVerreynne I tried both your suggestions but neither worked unfortunately... Why would I change `ClearBeforeFill` to `True` though? – doovers Feb 20 '15 at 12:44
  • @doovers, ClearBeforeFill was just a wild guess that it might cause a refresh. If set to true any changes made after loaded will be lost and probably not the desired result. –  Feb 20 '15 at 12:46
  • @NeillVerreynne Ah that's ok as I was avoiding setting it to true so as not to lose the selected cell and scrollbar positions. – doovers Feb 20 '15 at 13:07
  • It will be pretty difficult to get much help considering the complex arrangement you have going on. Instead of returning a typed DS, why not change `getDataWithMySQL` to simply act on `MyTableAdapter`? I'd work to simplify it all the way around. – Ňɏssa Pøngjǣrdenlarp Feb 21 '15 at 15:00
  • Why is this question tagged w/ C#? – Josh Feb 23 '15 at 16:08
  • @Josh For more attention. While I'm working in VB.Net, I'd bet this case would apply equally to C# and there seems to be many more C# developers than VB.Net that might be able to weigh in with a solution. – doovers Feb 23 '15 at 20:33
  • Why do you need to fill a table that already filled? – Tu Tran Feb 26 '15 at 06:51
  • I want to update the `DataGridView` to reflect any changes that have been made to the database table it is bound to. I also don't want to lose my position on it. – doovers Feb 26 '15 at 06:54

2 Answers2

1

I believe your problem stems from the fact that you're creating a new datatable within the method call and returning that datatable. You've got a reference to the DataSet.DataTable that you want, just call Fill with that DataTable.

Your problem is that the datatable that you're filling isn't associated w/ the dataset that your grid is using.

Josh
  • 1,724
  • 13
  • 15
  • Thanks but the problem with filling with the `DataSet.DataTable` is that the performance is so poor. It takes considerably longer to do the `Fill` that way. And while what you say about the new `DataTable` not being associated with the Grid makes sense, the `DataTable` returned by the function is of the same type, so it shouldn't make any difference. Also, as I mentioned, this was working for a while which was how I was able to benchmark the performance of each method in the other question I have linked to. – doovers Feb 23 '15 at 20:42
  • If it was working for awhile then what changed? Can you look through source control? The type has nothing to do with whether the instance is associated with the DataGrid. – Josh Feb 23 '15 at 20:51
  • Unfortunately I'm not sure what changed, I've tried everything I could think of including writing a new application with only that code to see if I could get it to work but no joy. Source control is no good either because I've been a bad boy and neglected to implement it in this project. Lesson learned though! – doovers Feb 23 '15 at 21:06
  • OK. I've got nothing else to go on then. I've tried the code using the Fill operator on a DataSet table and it works fine. The more complicated the query the slower it gets, but I haven't seen anything too bad. – Josh Feb 23 '15 at 21:25
  • One of the problems is that the query has a number of joins (5 tables) which may be slowing it down. None of the tables are very big though, the largest has 500 rows and the rest are 10-100 so it shouldn't be that bad. But >600ms vs <10ms is a massive difference when you are updating the UI every 5 seconds. – doovers Feb 23 '15 at 21:30
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/71603/discussion-between-josh-and-doovers). – Josh Feb 24 '15 at 16:30
1

Most likely this is because the .Fill command takes a datatable in using ByRef. I think what's happening is you are returning a DataTable with your getDataWithMySQL() but then you are taking that DataTable and refilling it with the .Fill method of the adapter and the DataTable you were returning with the getDataWithMySQL() method goes into lala land to never be seen again.

Making some assumptions here, but try giving this a shot:

Private Async Sub updateUI()
    Dim sw As New Stopwatch
    While True
        Await Task.Delay(3000)
        sw.Restart()
        Dim dt as myDataSet.myDataTable = getDataWithMySQL("SELECT ... LEFT JOIN ...")
        UpdateDGV(dt)
        'myTableAdapter.Fill(myDataSet.myTable)
        logger.Debug(sw.ElapsedMilliseconds)
    End While
End Sub

' You need to change `DataGridView` here to be the actual datagridview control on the form
Private Sub UpdateDGV(newSource as myDataSet.myDataTable)
    DataGridView.SuspendLayout()
    DataGridView.DataSource = Nothing
    DataGridView.DataSource = newSource 
    DataDridView.ResumeLayout()
End Sub

' Make the function easier to reuse by passing in the SQL command
Private Function getDataWithMySQL(sqlCmd as string) As myDataSet.myDataTable
    Dim connStr As String = My.Settings.myConnectionString
    Dim dt As New myDataSet.myDataTable
    Using conn As New MySqlConnection(connStr)
        Using cmd As New MySqlCommand()
            With cmd
                .CommandText = sqlCmd
                .Connection = conn
            End With
            Try
                conn.Open()
                Dim sqladapter As New MySqlDataAdapter(cmd)
                sqladapter.Fill(dt)

            Catch ex As MySqlException
                MsgBox(ex.Message)
            End Try
        End Using
    End Using
    Return dt
End Function
  • Thanks for your answer. While it does work, there are a few problems with this approach. Firstly, the performance is equivalent to using `myTableAdapter.Fill(myDataSet.myTable)` and secondly the `DataGridView` loses its position which is a deal breaker. The latter can be avoided by setting `ClearBeforeFill` to `False` in the `TableAdapter` when using the `myTableAdapter.Fill(myDataSet.myTable)` method. So unfortunately, this answer defeats the purpose of doing it manually. – doovers Feb 25 '15 at 00:42
  • At least I tried... It's the thought that counts, right? – вʀaᴎᴅᴏƞ вєнᴎєƞ Feb 25 '15 at 00:52
  • Ha ha yeah deffo!! Appreciate the help though mate! – doovers Feb 25 '15 at 00:53