J'ai donc une situation où j'utilise un SqlDataAdapter pour insérer des lignes dans une table dans une base de données SQL Server 2014.Pourquoi ce DataAdapter n'insère-t-il pas de lignes dans la base de données?
La source des données est une feuille de calcul Excel.
L'insertion fonctionne correctement lorsque l'objet DataTable est rempli en utilisant quelques boucles For et .Columns.Add et .Rows.Add pour copier les données de la feuille Excel. Ce code de travail que je n'ai pas inclus ici.
Cependant, je suis en train de refactoriser le code pour utiliser un OleDbDataReader. Voici ma fonction:
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
Quand je debug, le DataTable renvoyé par la fonction a des données dans l'ensemble, et par ailleurs semble être identique à la DataTable de la version précédente du code. Voici le code pour mettre à jour la base de données. Ce code est inchangé pour les deux cas.
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
Aucune exception n'est jamais levée. Le débogage de la ligne adp.Update (dt) n'a pas de latence comme si la requête n'était pas exécutée du tout. C'est la seule différence que je remarque entre les lignes/colonnes ajoutées DT et les DT peuplées OleDB - Il y a un léger temps de latence que les données sont insérées avec succès. Est-ce que je manque une sorte de fonctionnalité de base ou de propriété du DataTable
ou peut-être une propriété héritée ou créée pendant la charge? Est-ce autre chose que je n'ai pas pensé? Pourquoi mon SqlDataAdapter
insère-t-il des données dans la base de données lorsque la source est un DataTable
créé manuellement par rapport à un DataTable
rempli par OleDbReader
?
A 'DataTable' suit le' RowState' de chaque ligne, de sorte que la boucle d'ajouter manuellement fonctionne parce qu'ils sont 'Added'. Si vous chargez à partir d'une autre source, ils ne sont pas ajoutés/nouveaux. (Toujours patauger à travers ce code) – Plutonix
Avez-vous essayé d'utiliser cmd.ExecuteNonQuery plutôt que adp.update? – Benno
Si vous remplissez la table à l'aide d'un adaptateur de données, vous pouvez utiliser 'myDA.AcceptChangesDuringFill = False' afin que l'indicateur d'état de ligne ne soit pas effacé – Plutonix