2010-08-02 1 views
3

Je suis nouveau à C# et essaye de lier un datagridview à une base de données mssql dans Visual Studio 2010. Les liens de données sont OK et tout semble fonctionner. À l'exception de quelques erreurs étranges:Violation de la concurrence: le UpdateCommand affecté 0 des 1 enregistrements attendus

Je reçois l'erreur dans le sujet après: mise à jour la même ligne 2 fois, la suppression d'une nouvelle ligne insérée, après la mise à jour d'une ligne lorsqu'une autre ligne a été supprimée (mot modifications DeleteCommand)

Aucune des solutions que j'ai trouvé sur Google workes pour moi. J'espère que quelqu'un peut me aider. Voici te code:

private void fillDatagrid() 
     { 
      //fill datagrid ADO.NET 
      conn = new SqlConnection(TestApp.Properties.Settings.Default.TestdatabaseConnectionString); 
      cmd = conn.CreateCommand(); 
      conn.Open(); 
      cmd.CommandText = "SelectFrom"; 
      cmd.CommandType = CommandType.StoredProcedure; 
      cmd.Parameters.Add("@table", SqlDbType.NVarChar, 50).Value = "Countries"; 
      cmd.Parameters.Add("@filters", SqlDbType.NVarChar, 300).Value = ""; 

      adapt = new SqlDataAdapter(cmd); 
      dt = new DataTable(); 
      adapt.Fill(dt); 
      dt.TableName = "Countries"; 

      conn.Close(); 

      BindingSource src = new BindingSource(); 
      src.DataSource = dt; 
      dt.RowChanged += new DataRowChangeEventHandler(dt_RowChanged); 

      dgDatabaseGrid.DataSource = src; 
      dgDatabaseGrid.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells); 
      //dgDatabaseGrid.RowValidating += new DataGridViewCellCancelEventHandler(dgDatabaseGrid_RowValidating); 

      //disable columns: 
      dgDatabaseGrid.Columns[0].Visible = false; 
      dgDatabaseGrid.Columns["date_insert"].Visible = false; 
      dgDatabaseGrid.Columns["user_insert"].Visible = false; 
      dgDatabaseGrid.Columns["date_change"].Visible = false; 
      dgDatabaseGrid.Columns["user_change"].Visible = false; 
      dgDatabaseGrid.Columns["deleted"].Visible = false; 

      //auto size last column 
      dgDatabaseGrid.Columns["remarks"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; 


      SqlCommandBuilder cb = new SqlCommandBuilder(adapt); 
     } 

     void dt_RowChanged(object sender, DataRowChangeEventArgs e) 
     { 
      try 
      { 
       adapt.Update(dt); 
      } 
      catch (SqlException ex) 
      { 
       Debug.WriteLine(ex.Message); 
      } 
     } 

private void dgDatabaseGrid_UserDeletingRow(object sender, DataGridViewRowCancelEventArgs e) 
     { 
      if (!e.Row.IsNewRow) 
      { 


       DialogResult response = MessageBox.Show("Are you sure?", "Delete row?", 
            MessageBoxButtons.YesNo, 
            MessageBoxIcon.Question, 
            MessageBoxDefaultButton.Button2); 

       if (response == DialogResult.Yes) 
       { 

        //ipv delete --> deleted=1 
        conn.Open(); 
        cmd = conn.CreateCommand(); 
        cmd.CommandType = CommandType.StoredProcedure; 
        cmd.CommandText = "DeleteFrom"; 
        cmd.Parameters.Add("@table", SqlDbType.NVarChar, 50).Value = "Countries"; 
        cmd.Parameters.Add("@id", SqlDbType.Int).Value = e.Row.Cells[0].Value; 
        cmd.ExecuteNonQuery(); 
        conn.Close(); 


        //delete from datagrid: 
        dt.Rows[dgDatabaseGrid.SelectedCells[0].RowIndex].Delete(); 

       } 

       //always cancel! 
       e.Cancel = true; 

      } 
     } 

Répondre

1

après la mise à jour la même ligne 2 fois

Y at-il une colonne timestamp (ou toute autre colonne qui est modifiée/remplie sur le serveur Db)?

Votre problème peut se produire lorsque la ligne en mémoire est différente de ce qui est dans le Db. Et parce que vous utilisez un SP pour le SelectCmd il n'y a probablement pas d'actualisation après une mise à jour.

après la suppression d'une nouvelle ligne insérée

similaires, a fait pas aller chercher la nouvelle Id après un insert

après la mise à jour d'une ligne lorsqu'une autre ligne a été supprimée (mot modifications DeleteCommand)

absolument pas clair.
Mais pourquoi supprimer les lignes 'manuellement' au lieu de les laisser à adapter.Update()? Et êtes-vous sûr que les deux méthodes ne sont pas exécutées?

+0

Votre réponse est exactement ce que je devrais savoir, me donnant assez d'indices pour résoudre mon problème. Merci Henk. –

6

Je sais qu'il est très tard, mais peut-être cela aidera quelqu'un.

a fait les modifications suivantes à votre code:

try 
{ 
    adapt.Update(dt); 

Mettez ces lignes ici et utilisez votre variable

Me.yourTableAdapter.Update(Me.yourDataSet.yourTable) 
    Me.yourDataSet.youTable.AcceptChanges() 
    Me.yourTableAdapter.Fill(Me.yourDataSet.yourTable) 

cela a fonctionné comme un charme pour moi espère que cela fonctionnera pour vous .

} 
catch (SqlException ex) 
{ 
    Debug.WriteLine(ex.Message); 
} 
+0

Bien! cela m'a aidé à résoudre mon problème, cependant, édité pour de meilleurs résultats .. remplir un dataset.table qui contient déjà des données montrera des lignes dupliquées .. – CularBytes

+0

Me.yourTableAdapter.Update (Me.yourDataSet.yourTable) - J'ai exception à cette ligne déjà, donc pas sûr que la réponse ci-dessus fonctionne – phanvugiap

+0

Mais il y a un problème dans ceci, si vous liez un datagridview à l'ensemble de données les valeurs seront dupliquées jusqu'à ce que vous rechargiez le formulaire –

1

Je suis poursuivais cette erreur dans ma demande pendant des semaines! J'ai finalement trouvé mon problème.

Ce que je trouve dans ma demande ...

J'ai beaucoup textboxes, comboboxes, etc. lié avec DataBindings. Certains de ces champs sont mis à jour à partir de combinaisons d'autres champs. Tout cela fonctionne très bien à une exception près

Si l'un des champs calculés obtient recalculées après que vous EndEdit et avant que vous Update, cela entraînera une violation dbconcurrency.

Cette erreur ne doit pas nécessairement signifier que la ligne n'existe plus; cela signifie simplement qu'il n'a pas mis à jour une ligne pour une raison quelconque. Ma raison était que les données avaient trois états différents, donc il pensait que quelqu'un d'autre avait changé les données avant d'appeler la mise à jour.

En fait, il s'agit d'un seul MDF situé sur l'ordinateur de l'utilisateur afin que personne d'autre n'y ait accès pour le modifier pendant la mise à jour. Un utilisateur, une mise à jour. Mon code était l'utilisateur "autre".

Espérons que cela puisse aider quelqu'un d'autre dans la bonne direction pour son application.

+0

Après toutes les modifications, appelez simplement dataTable.AcceptChanges() ; – Vectoria

0

Si je peux ajouter mes deux cents.

J'ai lutté avec cela pendant un moment. Dans notre application, nous avons calculé des colonnes où la colonne est le résultat d'un calcul de deux ou plusieurs autres colonnes.

Cet Recalc a lancé l'adaptateur. J'ai dû mettre SqlCommandBuilder.ConflictOption = ConflictOption.OveriteChanges pour contourner ce problème.

Je ne sais pas s'il existe une option permettant à l'adaptateur d'ignorer les colonnes en lecture seule lorsqu'il effectue la vérification.

Questions connexes