2017-09-21 5 views
2

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?

+1

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

+0

Avez-vous essayé d'utiliser cmd.ExecuteNonQuery plutôt que adp.update? – Benno

+0

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

Répondre

2

Chaque DataTable suit la RowState de ses lignes, afin d'ajouter manuellement les données dans une boucle fonctionne car ils sont tous Added (il n'a rien à voir avec la création manuelle du DataTable - ses lignes les ). Lorsque vous chargez à partir d'une autre source comme Excel, ils sont et non ajouté/nouveau.

Si vous utilisez un DataAdapter pour remplir le tableau, vous pouvez le dire pas pour régler le RowState à Inchangé. Ceci est très utile pour la migration des données d'un magasin de données à un autre:

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