F# SqlCommand динамически записывает в таблицу SQL

Итак, я пытаюсь получить данные из одной таблицы (таблица 1), а затем записать выбранные данные во вторую таблицу (таблица 2). Я могу получить данные из таблицы1 и выбрать нужные данные. У меня проблемы с записью в таблицу2.

Вот что у меня есть на данный момент:

let insertData(data: string []List) =

    let tableName = data.Item(0).GetValue(0).ToString() //Gets the table Name
    let columnTypes = GetDevTableColumnsTypes tableName

    let mutable tableDataTemp = List.empty
    for i = 0 to data.Length-1 do
        let mutable rowDataTemp = List.empty

        for j = 0 to data.Item(i).Length-1 do
            if data.Item(i).GetValue(j).Equals(tableName) then //if statement removes table name from string array.
                System.Diagnostics.Debug.WriteLine("tableName removed from data")
            else
                let cellData = data.Item(i).GetValue(j)

                rowDataTemp <- cellData :: rowDataTemp

        let rowData = rowDataTemp |> List.toArray |> Array.rev
        tableDataTemp <- rowData :: tableDataTemp

    let tableData = tableDataTemp |> List.toArray |> Array.rev //Probably unneeded

    let cn = new SqlConnection(Settings.Azure.SQL.CCSettingDev)
    cn.Open()
    let sQL = "INSERT INTO [" + tableName + "] VALUES(@param1)"
    let db = new SqlCommand(sQL, cn)
    db.Parameters.AddWithValue("@param1", tableData)
    db.ExecuteNonQuery()

Когда я запускаю код, я получаю это исключение аргумента, указывающее на executeNonQuery:

Исключение типа «System.ArgumentException» возникло в System.Data.dll, но не было обработано в пользовательском коде.

Дополнительные сведения. Отсутствует сопоставление типа объекта System.Object[] с известным собственным типом управляемого поставщика.

На данный момент я работаю только с двумя таблицами, но вскоре программа будет работать с несколькими таблицами с разными именами столбцов, поэтому мне нужно, чтобы это работало независимо от таблицы, в которую она пишет. таблица1 и таблица2 имеют одинаковые столбцы. таблицы 3 и 4 имеют одинаковые столбцы, но отличаются от столбцов таблиц 1 и 2.

selectedData — это массив объектов, который содержит другие массивы объектов.

Если вы считаете, что есть лучший способ добавления данных вместо добавления массива, сообщите мне об этом.

Любая помощь будет оценена по достоинству.


person Mark    schedule 11.10.2016    source источник
comment
Я настоятельно рекомендую вам пересмотреть этот метод. Это старый добрый изменяемый код, который выполняет ввод данных уродливым образом. Этот код был бы плохим в C#. F# ничего не предлагает. Зачем использовать GetValue для доступа к элементу массива? Зачем использовать ToString(), когда массив уже является массивом строк? Зачем передавать имя таблицы и значения поля в одном и том же массиве? Что делает весь этот код??   -  person Panagiotis Kanavos    schedule 11.10.2016
comment
Пожалуйста, объясните, в чем заключается ваша реальная бизнес-проблема, а не то, как вы пытались ее решить. Похоже, вы хотите ОБЪЕДИНИТЬ список записей в таблицу? Или вставлять только новые записи? Напишите оператор INSERT ... WHERE, который соединяется с параметром таблицы и вставляет только новые записи. Передайте параметр таблицы как DataTable.   -  person Panagiotis Kanavos    schedule 11.10.2016
comment
если вы имеете в виду первую строку data.GetValue(0).ToString(). Когда я удаляю tostring, tableName становится объектом и, следовательно, несовместимым. Он передает (данные) имя таблицы плюс числовую ссылку на точку в массиве. Итак, скажем, переданное число равно 2. Это означает, что мне нужно 3-е значение в existsInTable1. У меня есть массив obj, в который я хочу добавить значения из массива во вторую таблицу. Я должен был упомянуть, что вся программа представляет собой веб-API.   -  person Mark    schedule 11.10.2016
comment
Не делай этого. используйте конкретные параметры. Если первое значение является именем таблицы, замените его параметром tableName. В любом случае, вы не объяснили, в чем заключается настоящая проблема.   -  person Panagiotis Kanavos    schedule 11.10.2016
comment
Хорошо, я пытаюсь добавить массив массивов в таблицу SQL. Программа выдает указанную мной ранее ошибку. Я не знаю почему. Я впервые делаю что-то подобное. Извини, если я причиняю боль.   -  person Mark    schedule 11.10.2016
comment
Это потому, что вся программа неверна, включая оператор SQL и параметры. Вы не можете передать массив команде SQL. Если вы хотите передать TVP, вы должны обращаться с ним как с таблицей, т.е. VALUES(@whatever) неверно, если только вы не передадите одно значение. Вы не можете избежать указания столбцов, иначе данные окажутся в неправильном месте. То, что вы знаете, что data.[2] равно John, а data.[3] равно Doe, не означает, что столбцы базы данных расположены в одном и том же порядке.   -  person Panagiotis Kanavos    schedule 11.10.2016
comment
Сначала попробуйте написать правильный оператор SQL. Затем попытайтесь выполнить это утверждение правильно. Затем попробуйте передать параметр с табличным значением. Или используйте SqlBulkCopy   -  person Panagiotis Kanavos    schedule 11.10.2016


Ответы (2)


Вам необходимо использовать параметр с табличным значением. Я думаю, что здесь самым простым способом было бы преобразовать ваш chosenData в массив SqlDataRecord, а затем сделать

let sQL = "INSERT INTO [" + tableName + "] SELECT * FROM @param1"
person Tarmil    schedule 11.10.2016
comment
Этого не достаточно. OP передает список вместо DataTable - person Panagiotis Kanavos; 11.10.2016
comment
Я не понимаю, как это работает. Должен ли я создать тип, содержащий имена и типы каждого столбца, потому что если это так, я не могу этого сделать. В программе не может быть таких жестко закодированных табличных значений, потому что, если таблицы в базе данных изменятся, мне придется изменить код, чего я не хочу. Я просто хочу, чтобы он работал независимо от того, какую таблицу он пишет. - person Mark; 11.10.2016
comment
@JacksonSentzke, ты не можешь этого сделать. Какой объект окажется в какой колонке? В любом случае, самый простой способ вставить данные — использовать SqlBulkCopy, передать ему DataTable (который не жестко запрограммирован) и убедиться, что столбцы таблицы данных соответствуют именам столбцов таблицы. Вставьте данные во временную таблицу, а затем объедините их в итоговую таблицу. - person Panagiotis Kanavos; 11.10.2016

пусть cn = новое SqlConnection (строка соединения) cn.Open()

for i=0 to tableData.Length-1 do
    let mutable columnsTemp = ""
    let mutable valuesTemp = ""
    for j = 0 to tableData.Item(i).Length-2 do
        columnsTemp <- columnsTemp + columnNames.GetValue(j).ToString() + ","
        valuesTemp <- valuesTemp + "'" + tableData.Item(i).GetValue(j).ToString() + "',"


    let columns = columnsTemp.Remove(columnsTemp.Length-1,1)
    let values = valuesTemp.Remove(valuesTemp.Length-1,1)
    let sQL = "INSERT INTO [" + tableName + "] (" + columns + ") VALUES (" + values + ")"
    let db = new SqlCommand(sQL, cn)
    db.ExecuteNonQuery()
person Mark    schedule 12.10.2016