без изменений. Это очень полезно для переноса данных из одного хранилища данных в другое:

му у меня есть ситуация, когда я использую SqlDataAdapter для вставки строк в таблицу в базе данных SQL Server 2014.

Источником данных является электронная таблица Excel.

Вставка работает нормально, когда объект DataTable заполняется с использованием нескольких циклов For и .Columns.Add и .Rows.Add, чтобы скопировать данные из листа Excel. Этот рабочий код я здесь не включил.

Тем не менее, я рефакторинг кода для использования OleDbDataReader. Вот моя функция:

Private Function FillDataTable(path As String, name As String) As DataTable
        Dim fullpath As String = path
        Dim wsname As String = name
        Dim dt = New DataTable()
        Try
            Dim connectionstring As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source='" & fullpath & "';Extended Properties= 'Excel 8.0;HDR=Yes;IMEX=1'"
            Dim commandstring As String = "Select * From " & wsname
            Using con As New OleDbConnection(connectionstring)
                Using cmd As New OleDbCommand(commandstring, con)
                    con.Open()
                    Using dr As OleDbDataReader = cmd.ExecuteReader()
                        With dt
                            For Each c In aryFieldList
                                .Columns.Add(c.FieldName, ConvertType(c.DataType))
                            Next

                            .Columns.Add("SubmID")
                            .Columns("SubmID").DefaultValue = 0

                            .Columns.Add("S_ORDER")
                            .Columns("S_ORDER").DefaultValue = 0

                            .Columns.Add("C_ORDER")
                            .Columns("C_ORDER").DefaultValue = 0
                        End With
                        dt.Load(dr)
                    End Using
                End Using
            End Using

        Catch ex As Exception
            MsgBox(ex.Message)
        End Try
        Return dt

    End Function

Когда я отлаживаю, DataTable, который возвращается из функции, содержит данные в наборе, и в остальном кажется идентичным DataTable из предыдущей версии кода. Вот код для обновления базы данных. Этот кодбез изменений для обоих случаев.

    Dim dt = New DataTable()
    dt = FillDataTable(fullpath, wsname)

Using cn = New SqlConnection(ConfigurationManager.ConnectionStrings("Connection").ConnectionString)
    cn.Open()
    Using adp = New SqlDataAdapter()
        Dim sb As New StringBuilder

        [...StringBuilder code to build the Insert command here...]

        Dim cmd As New SqlCommand(sb.ToString, cn)

        With adp
            .InsertCommand = cmd
            .InsertCommand.Parameters.Add("SubmID", SqlDbType.Int, 1, "SubmID")
            .InsertCommand.Parameters.Add("S_ORDER", SqlDbType.Int, 1, "S_ORDER")
            .InsertCommand.Parameters.Add("C_ORDER", SqlDbType.Int, 1, "C_ORDER")

            For Each p In aryFieldList
                If p.Excluded = False Then
                    .InsertCommand.Parameters.Add(p.FieldName, p.DataType, p.Length, p.FieldName)
                End If
            Next
                adp.Update(dt)

        End With 'adp
    End Using 'adp
End Using 'cn

Никаких исключений не бывает. Отладка строки adp.Update (dt) не имеет задержки, как будто запрос вообще не выполняется. Это единственное различие, которое я замечаю между DT, добавленным в строки / столбцы, и DT, заполненным OleDB. Существует небольшая задержка, когда данные вставляются успешно.

Я пропускаю какую-то базовую функциональность или свойствоDataTable или, может быть, свойство, унаследованное или созданное во время загрузки? Это что-то еще, о чем я не думал? Почему мойSqlDataAdapter вставить данные в базу данных, когда источником являетсяDataTable создан вручную по сравнению сDataTable заполненыOleDbReader?

 Benno21 сент. 2017 г., 16:47
Вы пытались использовать cmd.ExecuteNonQuery, а не adp.update?
 Make StackOverflow Good Again21 сент. 2017 г., 16:49
Если вы заполните таблицу с помощью адаптера данных, вы можете использоватьmyDA.AcceptChangesDuringFill = False поэтому флаг строки не очищен
 Make StackOverflow Good Again21 сент. 2017 г., 16:45
A DataTable отслеживаетRowState каждой строки, поэтому цикл добавления вручную работает, потому что все ониAdded, Если вы загружаете из какого-либо другого источника, они не добавляются / новые. (Все еще пробираюсь через этот код)
 Jacob H21 сент. 2017 г., 16:59
@Plutonix Можно ли изменить RowState после или во время загрузки., Чтобы они были добавлены?
 Jacob H21 сент. 2017 г., 21:51
@Benno К вашему сведению, мы фактически использовали sqlbulkcopy вместо обоих, поскольку мы печатаем данные, проверяем и очищаем все столбцы Excel перед импортом, поэтому мы можем просто выполнить операцию ColumnMapping, и вставка 100 000 строк заняла менее 5 секунд. Операции адаптера занимали около 30 минут для тех же самых вставок. Мы также хотели избежать создания табличных типов в SQL для вставки. Спасибо за предложение!

Ответы на вопрос(1)

Решение Вопроса

DataTable отслеживаетRowState его строк, поэтому ручное добавление данных в цикле работает, потому что они всеAdded (это не имеет ничего общего с созданием вручнуюDataTable - этостроки). Когда вы загружаете из какого-либо другого источника, такого как Excel, онине добавлено / новый.

Если вы используетеDataAdapter чтобы заполнить таблицу, вы можете сказать этоне установитьRowState без изменений. Это очень полезно для переноса данных из одного хранилища данных в другое:

myDA.AcceptChangesDuringFill = False
...
rows = myDA.Fill(xlDT)

Ваш ответ на вопрос