Movendo dados do SQL Anywhere para o SQL Server e depois de alguns soluços estava indo bem até que recebi o erro
A coluna "A_Future" não pode ser modificada porque é uma coluna computada ou é o resultado de uma UNION'
Justo, eu estava inserindo dados de SELECT * -- então usei isso para retornar apenas colunas que não foram calculadas.
'Remove computed columns from the SELECT query
Dim DR() As DataRow = MSSQLDT.Select("Computed = 'N'")
Dim vSelectedRows As Integer = DR.Count
Dim vCurrentRow As Integer = 0
strSQL = "SELECT "
For Each Row In DR
strSQL += Row("Name")
vCurrentRow += 1
If vCurrentRow = vSelectedRows Then
strSQL += " "
Else
strSQL += ", "
End If
Next
strSQL += "FROM " & vTable
Isso retorna a seguinte string de consulta...
SELECT Transaction_ID, Debit, Credit, Paid, P_Description, Document_Date, Supplier_ID, Nominal_Transaction, HOA_Code, Document_Saved, Document_ID, Document_No, Supplier_Inv_No, Type, Paid_Date, Part_Paid, Open_Editing, Editing_Name, Updated_Name, Updated, Reserve_Item, Hold, eCheck_Pending, eSig_Required, eSigOne_ID, eSigTwo_ID FROM A_Purchase_Ledger
.. e não inclui nenhuma coluna calculada. Executei novamente, mas ainda apresentou o mesmo erro (para todas as colunas calculadas)
Microsoft.Data.SqlClient.SqlException (0x80131904): The column "A_Future" cannot be modified because it is either a computed column or is the result of a UNION operator.
The column "A_Current" cannot be modified because it is either a computed column or is the result of a UNION operator.
The column "A_30" cannot be modified because it is either a computed column or is the result of a UNION operator.
The column "A_60" cannot be modified because it is either a computed column or is the result of a UNION operator.
The column "A_90" cannot be modified because it is either a computed column or is the result of a UNION operator.
The column "A_Older" cannot be modified because it is either a computed column or is the result of a UNION operator.
Isso não faz sentido agora, já que não estou tentando inserir dados neles, a menos que haja uma peculiaridade da qual SqlBulkCopy
eu não esteja ciente?
Os dados SELECT são adicionados a e DataTable
então vão para esta função
Public Function BulkUpdate_DataMS(DT As DataTable, HOAID As Integer, IsHASoftware As Boolean, TableName As String) As Boolean
Try
Using Conn As New Microsoft.Data.SqlClient.SqlConnection
If IsHASoftware = True Then
Conn.ConnectionString = HASConString
Else
Conn.ConnectionString = ReturnConnStringMS(HOAID)
End If
Conn.Open()
Using vTrans = Conn.BeginTransaction
Using vBulk As New Microsoft.Data.SqlClient.SqlBulkCopy(Conn, Microsoft.Data.SqlClient.SqlBulkCopyOptions.Default, vTrans)
vBulk.DestinationTableName = TableName
vBulk.WriteToServer(DT)
End Using
vTrans.Commit()
End Using
Conn.Close()
End Using
Return True
Catch ex As Exception
EmailError(ex, 222, PageName)
Return False
End Try
End Function
Você precisa definir o ,
ColumnMappings
caso contrário, ele fará apenas uma correspondência ordinal.Também não há necessidade de uma transação, pois a inserção em massa usará sua própria transação. E se você tiver uma,
Using
não precisa fechar a conexão manualmente.Você provavelmente também deveria considerar usar
Async
eAwait
para tudo isso.A maneira correta de fazer async não seria usar
Task.Run
, em vez disso, usarAwait
diretamente na inserção em massa dentro de uma função marcada comoAsync
Além disso, se você estiver lendo os dados de outro servidor, não precisa salvá-los em a
DataTable
. Você pode passar os dadosDbDataReader
que você obtém deExecuteReader
/ExecuteReaderAsync
diretamente paraWriteToServer
/WriteToServerAsync
.Não é a solução que eu estava procurando, iterando por milhares de linhas, mas parece que a atualização em massa não funciona onde valores computados estão envolvidos. Isso verifica se há algum computado e então os insere um de cada vez. Se alguém tiver uma solução melhor, eu adoraria ouvir.
Basicamente, puxando dinamicamente cada
Table
esquema,SQL Anywhere
alterando-o paraSQL Server
, adicionando a tabela eSQL Server
inserindo os dados