2016-11-16 3 views
-1

Простой вопрос:SqlDataAdapter.Fill (DataGridView.DataSource) дублирует все строки

Когда я звоню SqlDataAdapter.Fill(DataGridView.DataSource) во второй раз после того, как первоначально создание первых данных не обновлять содержащиеся строки. Он просто добавляет все строки, возвращаемые командой select, в мой DataGridView.

Если я назову его третьим, четвертым (так далее), он также просто добавит возвращенные строки.

Я понимаю, что функция .Fill (DataTable) ошибочна? Как правильно обновить уже существующий DataTable? Какая строка кода отвечает за это?


Оказывается, это должно быть проблемой кода;

DataGridView1.AutoGenerateColumns = False 
    Dim sql = "select * from myTable" 
    oDtSource = New DataTable 
    oAdapter = New SqlDataAdapter 
    oCon = sqlCon("serverName\Instance", "myDataBase") ' Returns a SqlConnection 
    oCmd = New SqlCommand(sql, oCon) 
    oCon.Open() 

    oDtSource.Clear() 

    oAdapter.MissingSchemaAction = MissingSchemaAction.AddWithKey 
    oAdapter.SelectCommand = oCmd 
    oAdapter.Fill(oDtSource) 
    DataGridView1.DataSource = oDtSource 

Для освежения я использую oAdapter.Fill(oDtSource) PrimaryKey устанавливается в базе данных

+0

Просьба показать, как вы настроили DataAdapter (я предполагаю, что вы пытаетесь обновить данные, иначе просто используйте New datatable или очистите строки). Не знаю, почему DV отличается от недостатка кода - это достойный вопрос. – Plutonix

+0

Я уверен, что Тим Шмельтер вернул меня на правильный путь. WorkTime закончилось, поэтому я должен буду это проверить завтра. Еще раз спасибо @Plutonix за то, что привлек меня к этому пути, чтобы попытаться использовать метод .Fill вместо создания новых таблиц снова и снова. – Luke

+0

Код был опубликован выше. – Luke

ответ

3

От MSDN:

Вы можете использовать Fill метод несколько раз на одной и той же DataTable. Если существует первичный ключ , входящие строки объединяются с соответствующими строками, которые уже существуют . Если первичный ключ не существует, входящие строки добавляются к DataTable.

Таким образом, либо сначала определите первичный ключ, либо очистите таблицу.

Dim table = CType(DataGridView.DataSource, DataTable) 
table.Clear() 
' fill ... 

Для определения первичного ключа (ов) вручную читать this. Для того, чтобы она автоматически создавать, если они определены в базе данных, необходимо установить MissingSchemaAction в AddWithKey:

' ... 
dataAdapter.MissingSchemaAction = MissingSchemaAction.AddWithKey 
' fill ... 
+0

То, что хорошо, должно было взглянуть на MSDN сразу. Виноват. Не можете найти команду для установки первичного ключа. Не могли бы вы мне помочь в этом? – Luke

+2

@ Luke: https://msdn.microsoft.com/en-us/library/z24kefs8(v=vs.110).aspx –

+0

Я все еще ничего не вижу. Я проверю это завтра. Огромное спасибо. Должен уйти с работы сейчас, иначе я буду застрять здесь до завтра ;-) – Luke

2

edit код не показывает PrimaryKey определяется для DataTable. Это настроит DataAdapter для выполнения обновлений и активирует обновление DataTable.Код использует MySQL но Provider все объекты работают так же в связи с этим:

' persistant form level vars 
Private daSample As MySqlDataAdapter 
Private dtSample As DataTable 
... 

В другом месте:

' there are caveats with WHERE clauses 
Dim sql = "SELECT Id, Name, Country, Animal FROM SAMPLE WHERE Color = 'onyx'" 

' using the ctor overload, no need for a DbCommand or Connection object 
daSample = New MySqlDataAdapter(sql, MySQLConnStr) 

' initialize the CommandBuilder, get other commands 
Dim cbSample = New MySqlCommandBuilder(daSample) 

daSample.UpdateCommand = cbSample.GetUpdateCommand 
daSample.InsertCommand = cbSample.GetInsertCommand 
daSample.DeleteCommand = cbSample.GetDeleteCommand 

dtSample = New DataTable() 
daSample.FillSchema(dtSample, SchemaType.Source) 
dtSample.PrimaryKey = New DataColumn() {dtSample.Columns("id")} 

daSample.Fill(dtSample) 

dgv1.DataSource = dtSample 

Чтобы забрать изменения, внесенные в БД из других приложений клиента:

daSample.Fill(dtSample) 

Первоначальный дисплей:

enter image description here

После того как я изменить строку «оникс» из браузера UI и Update измененная строка показывает вверх:

enter image description here

WHERE положение может быть немного вопроса. Поскольку он ограничивает подмножество данных, отодвинутых назад, Update будет только сравнивать строки в наборе новых. Итак, если я изменил строку onlyx на «синий», ее не удалят.

Одним из решений является использование .DefaultView.RowFilter на столе, но это может замедлить работу, поскольку для этого требуется, чтобы все строки были отфильтрованы клиентом. Это не идеально.

+0

Я удалил часть компилятора, потому что это дало мне исключение. Я довольно много копировал остальную часть кода, потому что я не нашел недостающую строку для меня. Он работает (без повторных строк, новые строки отображаются после обновления с помощью .Fill) только с одной небольшой проблемой; Вызов .Fill (Таблица) для обновления данных занимает 30 секунд, когда у меня около 1000 записей. Предполагается, что это займет много времени? – Luke

+0

Я бы не стал гадать, почему он медленно от такой маленькой информации. Легко использовать почти все, что угодно, используя класс «StopWatch». DGV только собирается перерисовывать строки, которые отображаются, поэтому почти наверняка не виноват. – Plutonix

Смежные вопросы